xref: /aosp_15_r20/external/grpc-grpc/src/core/resolver/dns/c_ares/grpc_ares_wrapper.cc (revision cc02d7e222339f7a4f6ba5f422e6413f4bd931f2)
1 //
2 //
3 // Copyright 2016 gRPC authors.
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License");
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17 //
18 
19 #include <grpc/support/port_platform.h>
20 
21 #include <algorithm>
22 #include <vector>
23 
24 #include "absl/strings/string_view.h"
25 
26 #include <grpc/impl/channel_arg_names.h>
27 
28 #include "src/core/lib/gprpp/status_helper.h"
29 #include "src/core/lib/iomgr/sockaddr.h"
30 
31 // IWYU pragma: no_include <arpa/inet.h>
32 // IWYU pragma: no_include <arpa/nameser.h>
33 // IWYU pragma: no_include <inttypes.h>
34 // IWYU pragma: no_include <netdb.h>
35 // IWYU pragma: no_include <netinet/in.h>
36 // IWYU pragma: no_include <stdlib.h>
37 // IWYU pragma: no_include <sys/socket.h>
38 
39 #if GRPC_ARES == 1
40 
41 #include <string.h>
42 #include <sys/types.h>  // IWYU pragma: keep
43 
44 #include <string>
45 #include <utility>
46 
47 #include <address_sorting/address_sorting.h>
48 #include <ares.h>
49 
50 #include "absl/status/status.h"
51 #include "absl/status/statusor.h"
52 #include "absl/strings/str_cat.h"
53 #include "absl/strings/str_format.h"
54 
55 #include <grpc/support/alloc.h>
56 #include <grpc/support/log.h>
57 #include <grpc/support/string_util.h>
58 #include <grpc/support/sync.h>
59 
60 #include "src/core/resolver/dns/c_ares/grpc_ares_ev_driver.h"
61 #include "src/core/resolver/dns/c_ares/grpc_ares_wrapper.h"
62 #include "src/core/lib/address_utils/parse_address.h"
63 #include "src/core/lib/address_utils/sockaddr_utils.h"
64 #include "src/core/lib/channel/channel_args.h"
65 #include "src/core/lib/gpr/string.h"
66 #include "src/core/lib/gprpp/debug_location.h"
67 #include "src/core/lib/gprpp/host_port.h"
68 #include "src/core/lib/gprpp/time.h"
69 #include "src/core/lib/iomgr/error.h"
70 #include "src/core/lib/iomgr/exec_ctx.h"
71 #include "src/core/lib/iomgr/nameser.h"  // IWYU pragma: keep
72 #include "src/core/lib/iomgr/resolved_address.h"
73 #include "src/core/lib/iomgr/timer.h"
74 
75 using grpc_core::EndpointAddresses;
76 using grpc_core::EndpointAddressesList;
77 
78 grpc_core::TraceFlag grpc_trace_cares_address_sorting(false,
79                                                       "cares_address_sorting");
80 
81 grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver");
82 
83 typedef struct fd_node {
84   // default constructor exists only for linked list manipulation
fd_nodefd_node85   fd_node() : ev_driver(nullptr) {}
86 
fd_nodefd_node87   explicit fd_node(grpc_ares_ev_driver* ev_driver) : ev_driver(ev_driver) {}
88 
89   /// the owner of this fd node
90   grpc_ares_ev_driver* const ev_driver;
91   /// a closure wrapping on_readable_locked, which should be
92   /// invoked when the grpc_fd in this node becomes readable.
93   grpc_closure read_closure ABSL_GUARDED_BY(&grpc_ares_request::mu);
94   /// a closure wrapping on_writable_locked, which should be
95   /// invoked when the grpc_fd in this node becomes writable.
96   grpc_closure write_closure ABSL_GUARDED_BY(&grpc_ares_request::mu);
97   /// next fd node in the list
98   struct fd_node* next ABSL_GUARDED_BY(&grpc_ares_request::mu);
99 
100   /// wrapped fd that's polled by grpc's poller for the current platform
101   grpc_core::GrpcPolledFd* grpc_polled_fd
102       ABSL_GUARDED_BY(&grpc_ares_request::mu);
103   /// if the readable closure has been registered
104   bool readable_registered ABSL_GUARDED_BY(&grpc_ares_request::mu);
105   /// if the writable closure has been registered
106   bool writable_registered ABSL_GUARDED_BY(&grpc_ares_request::mu);
107   /// if the fd has been shutdown yet from grpc iomgr perspective
108   bool already_shutdown ABSL_GUARDED_BY(&grpc_ares_request::mu);
109 } fd_node;
110 
111 struct grpc_ares_ev_driver {
grpc_ares_ev_drivergrpc_ares_ev_driver112   explicit grpc_ares_ev_driver(grpc_ares_request* request) : request(request) {}
113 
114   /// the ares_channel owned by this event driver
115   ares_channel channel ABSL_GUARDED_BY(&grpc_ares_request::mu);
116   /// pollset set for driving the IO events of the channel
117   grpc_pollset_set* pollset_set ABSL_GUARDED_BY(&grpc_ares_request::mu);
118   /// refcount of the event driver
119   gpr_refcount refs;
120 
121   /// a list of grpc_fd that this event driver is currently using.
122   fd_node* fds ABSL_GUARDED_BY(&grpc_ares_request::mu);
123   /// is this event driver being shut down
124   bool shutting_down ABSL_GUARDED_BY(&grpc_ares_request::mu);
125   /// request object that's using this ev driver
126   grpc_ares_request* const request;
127   /// Owned by the ev_driver. Creates new GrpcPolledFd's
128   std::unique_ptr<grpc_core::GrpcPolledFdFactory> polled_fd_factory
129       ABSL_GUARDED_BY(&grpc_ares_request::mu);
130   /// query timeout in milliseconds
131   int query_timeout_ms ABSL_GUARDED_BY(&grpc_ares_request::mu);
132   /// alarm to cancel active queries
133   grpc_timer query_timeout ABSL_GUARDED_BY(&grpc_ares_request::mu);
134   /// cancels queries on a timeout
135   grpc_closure on_timeout_locked ABSL_GUARDED_BY(&grpc_ares_request::mu);
136   /// alarm to poll ares_process on in case fd events don't happen
137   grpc_timer ares_backup_poll_alarm ABSL_GUARDED_BY(&grpc_ares_request::mu);
138   /// polls ares_process on a periodic timer
139   grpc_closure on_ares_backup_poll_alarm_locked
140       ABSL_GUARDED_BY(&grpc_ares_request::mu);
141 };
142 
143 // TODO(apolcyn): make grpc_ares_hostbyname_request a sub-class
144 // of GrpcAresQuery.
145 typedef struct grpc_ares_hostbyname_request {
146   /// following members are set in create_hostbyname_request_locked
147   ///
148   /// the top-level request instance
149   grpc_ares_request* parent_request;
150   /// host to resolve, parsed from the name to resolve
151   char* host;
152   /// port to fill in sockaddr_in, parsed from the name to resolve
153   uint16_t port;
154   /// is it a grpclb address
155   bool is_balancer;
156   /// for logging and errors: the query type ("A" or "AAAA")
157   const char* qtype;
158 } grpc_ares_hostbyname_request;
159 
160 static void grpc_ares_request_ref_locked(grpc_ares_request* r)
161     ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu);
162 static void grpc_ares_request_unref_locked(grpc_ares_request* r)
163     ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu);
164 
165 // TODO(apolcyn): as a part of C++-ification, find a way to
166 // organize per-query and per-resolution information in such a way
167 // that doesn't involve allocating a number of different data
168 // structures.
169 class GrpcAresQuery final {
170  public:
GrpcAresQuery(grpc_ares_request * r,const std::string & name)171   explicit GrpcAresQuery(grpc_ares_request* r, const std::string& name)
172       : r_(r), name_(name) {
173     grpc_ares_request_ref_locked(r_);
174   }
175 
~GrpcAresQuery()176   ~GrpcAresQuery() { grpc_ares_request_unref_locked(r_); }
177 
parent_request()178   grpc_ares_request* parent_request() { return r_; }
179 
name()180   const std::string& name() { return name_; }
181 
182  private:
183   // the top level request instance
184   grpc_ares_request* r_;
185   /// for logging and errors
186   const std::string name_;
187 };
188 
grpc_ares_ev_driver_ref(grpc_ares_ev_driver * ev_driver)189 static grpc_ares_ev_driver* grpc_ares_ev_driver_ref(
190     grpc_ares_ev_driver* ev_driver)
191     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
192   GRPC_CARES_TRACE_LOG("request:%p Ref ev_driver %p", ev_driver->request,
193                        ev_driver);
194   gpr_ref(&ev_driver->refs);
195   return ev_driver;
196 }
197 
198 static void grpc_ares_complete_request_locked(grpc_ares_request* r)
199     ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu);
200 
grpc_ares_ev_driver_unref(grpc_ares_ev_driver * ev_driver)201 static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver* ev_driver)
202     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
203   GRPC_CARES_TRACE_LOG("request:%p Unref ev_driver %p", ev_driver->request,
204                        ev_driver);
205   if (gpr_unref(&ev_driver->refs)) {
206     GRPC_CARES_TRACE_LOG("request:%p destroy ev_driver %p", ev_driver->request,
207                          ev_driver);
208     GPR_ASSERT(ev_driver->fds == nullptr);
209     ares_destroy(ev_driver->channel);
210     grpc_ares_complete_request_locked(ev_driver->request);
211     delete ev_driver;
212   }
213 }
214 
fd_node_destroy_locked(fd_node * fdn)215 static void fd_node_destroy_locked(fd_node* fdn)
216     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
217   GRPC_CARES_TRACE_LOG("request:%p delete fd: %s", fdn->ev_driver->request,
218                        fdn->grpc_polled_fd->GetName());
219   GPR_ASSERT(!fdn->readable_registered);
220   GPR_ASSERT(!fdn->writable_registered);
221   GPR_ASSERT(fdn->already_shutdown);
222   delete fdn->grpc_polled_fd;
223   delete fdn;
224 }
225 
fd_node_shutdown_locked(fd_node * fdn,const char * reason)226 static void fd_node_shutdown_locked(fd_node* fdn, const char* reason)
227     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
228   if (!fdn->already_shutdown) {
229     fdn->already_shutdown = true;
230     fdn->grpc_polled_fd->ShutdownLocked(GRPC_ERROR_CREATE(reason));
231   }
232 }
233 
grpc_ares_ev_driver_on_queries_complete_locked(grpc_ares_ev_driver * ev_driver)234 void grpc_ares_ev_driver_on_queries_complete_locked(
235     grpc_ares_ev_driver* ev_driver)
236     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
237   // We mark the event driver as being shut down.
238   // grpc_ares_notify_on_event_locked will shut down any remaining
239   // fds.
240   ev_driver->shutting_down = true;
241   grpc_timer_cancel(&ev_driver->query_timeout);
242   grpc_timer_cancel(&ev_driver->ares_backup_poll_alarm);
243   grpc_ares_ev_driver_unref(ev_driver);
244 }
245 
grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver * ev_driver)246 void grpc_ares_ev_driver_shutdown_locked(grpc_ares_ev_driver* ev_driver)
247     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
248   ev_driver->shutting_down = true;
249   fd_node* fn = ev_driver->fds;
250   while (fn != nullptr) {
251     fd_node_shutdown_locked(fn, "grpc_ares_ev_driver_shutdown");
252     fn = fn->next;
253   }
254 }
255 
256 // Search fd in the fd_node list head. This is an O(n) search, the max possible
257 // value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests.
pop_fd_node_locked(fd_node ** head,ares_socket_t as)258 static fd_node* pop_fd_node_locked(fd_node** head, ares_socket_t as)
259     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
260   fd_node phony_head;
261   phony_head.next = *head;
262   fd_node* node = &phony_head;
263   while (node->next != nullptr) {
264     if (node->next->grpc_polled_fd->GetWrappedAresSocketLocked() == as) {
265       fd_node* ret = node->next;
266       node->next = node->next->next;
267       *head = phony_head.next;
268       return ret;
269     }
270     node = node->next;
271   }
272   return nullptr;
273 }
274 
calculate_next_ares_backup_poll_alarm(grpc_ares_ev_driver * driver)275 static grpc_core::Timestamp calculate_next_ares_backup_poll_alarm(
276     grpc_ares_ev_driver* driver)
277     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
278   // An alternative here could be to use ares_timeout to try to be more
279   // accurate, but that would require using "struct timeval"'s, which just makes
280   // things a bit more complicated. So just poll every second, as suggested
281   // by the c-ares code comments.
282   grpc_core::Duration until_next_ares_backup_poll_alarm =
283       grpc_core::Duration::Seconds(1);
284   GRPC_CARES_TRACE_LOG(
285       "request:%p ev_driver=%p. next ares process poll time in "
286       "%" PRId64 " ms",
287       driver->request, driver, until_next_ares_backup_poll_alarm.millis());
288   return grpc_core::Timestamp::Now() + until_next_ares_backup_poll_alarm;
289 }
290 
on_timeout(void * arg,grpc_error_handle error)291 static void on_timeout(void* arg, grpc_error_handle error) {
292   grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
293   grpc_core::MutexLock lock(&driver->request->mu);
294   GRPC_CARES_TRACE_LOG(
295       "request:%p ev_driver=%p on_timeout_locked. driver->shutting_down=%d. "
296       "err=%s",
297       driver->request, driver, driver->shutting_down,
298       grpc_core::StatusToString(error).c_str());
299   if (!driver->shutting_down && error.ok()) {
300     grpc_ares_ev_driver_shutdown_locked(driver);
301   }
302   grpc_ares_ev_driver_unref(driver);
303 }
304 
305 static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver)
306     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu);
307 
308 // In case of non-responsive DNS servers, dropped packets, etc., c-ares has
309 // intelligent timeout and retry logic, which we can take advantage of by
310 // polling ares_process_fd on time intervals. Overall, the c-ares library is
311 // meant to be called into and given a chance to proceed name resolution:
312 //   a) when fd events happen
313 //   b) when some time has passed without fd events having happened
314 // For the latter, we use this backup poller. Also see
315 // https://github.com/grpc/grpc/pull/17688 description for more details.
on_ares_backup_poll_alarm(void * arg,grpc_error_handle error)316 static void on_ares_backup_poll_alarm(void* arg, grpc_error_handle error) {
317   grpc_ares_ev_driver* driver = static_cast<grpc_ares_ev_driver*>(arg);
318   grpc_core::MutexLock lock(&driver->request->mu);
319   GRPC_CARES_TRACE_LOG(
320       "request:%p ev_driver=%p on_ares_backup_poll_alarm_locked. "
321       "driver->shutting_down=%d. "
322       "err=%s",
323       driver->request, driver, driver->shutting_down,
324       grpc_core::StatusToString(error).c_str());
325   if (!driver->shutting_down && error.ok()) {
326     fd_node* fdn = driver->fds;
327     while (fdn != nullptr) {
328       if (!fdn->already_shutdown) {
329         GRPC_CARES_TRACE_LOG(
330             "request:%p ev_driver=%p on_ares_backup_poll_alarm_locked; "
331             "ares_process_fd. fd=%s",
332             driver->request, driver, fdn->grpc_polled_fd->GetName());
333         ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
334         ares_process_fd(driver->channel, as, as);
335       }
336       fdn = fdn->next;
337     }
338     if (!driver->shutting_down) {
339       // InvalidateNow to avoid getting stuck re-initializing this timer
340       // in a loop while draining the currently-held WorkSerializer.
341       // Also see https://github.com/grpc/grpc/issues/26079.
342       grpc_core::ExecCtx::Get()->InvalidateNow();
343       grpc_core::Timestamp next_ares_backup_poll_alarm =
344           calculate_next_ares_backup_poll_alarm(driver);
345       grpc_ares_ev_driver_ref(driver);
346       GRPC_CLOSURE_INIT(&driver->on_ares_backup_poll_alarm_locked,
347                         on_ares_backup_poll_alarm, driver,
348                         grpc_schedule_on_exec_ctx);
349       grpc_timer_init(&driver->ares_backup_poll_alarm,
350                       next_ares_backup_poll_alarm,
351                       &driver->on_ares_backup_poll_alarm_locked);
352     }
353     grpc_ares_notify_on_event_locked(driver);
354   }
355   grpc_ares_ev_driver_unref(driver);
356 }
357 
on_readable(void * arg,grpc_error_handle error)358 static void on_readable(void* arg, grpc_error_handle error) {
359   fd_node* fdn = static_cast<fd_node*>(arg);
360   grpc_core::MutexLock lock(&fdn->ev_driver->request->mu);
361   GPR_ASSERT(fdn->readable_registered);
362   grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
363   const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
364   fdn->readable_registered = false;
365   GRPC_CARES_TRACE_LOG("request:%p readable on %s", fdn->ev_driver->request,
366                        fdn->grpc_polled_fd->GetName());
367   if (error.ok() && !ev_driver->shutting_down) {
368     ares_process_fd(ev_driver->channel, as, ARES_SOCKET_BAD);
369   } else {
370     // If error is not absl::OkStatus() or the resolution was cancelled, it
371     // means the fd has been shutdown or timed out. The pending lookups made on
372     // this ev_driver will be cancelled by the following ares_cancel() and the
373     // on_done callbacks will be invoked with a status of ARES_ECANCELLED. The
374     // remaining file descriptors in this ev_driver will be cleaned up in the
375     // follwing grpc_ares_notify_on_event_locked().
376     ares_cancel(ev_driver->channel);
377   }
378   grpc_ares_notify_on_event_locked(ev_driver);
379   grpc_ares_ev_driver_unref(ev_driver);
380 }
381 
on_writable(void * arg,grpc_error_handle error)382 static void on_writable(void* arg, grpc_error_handle error) {
383   fd_node* fdn = static_cast<fd_node*>(arg);
384   grpc_core::MutexLock lock(&fdn->ev_driver->request->mu);
385   GPR_ASSERT(fdn->writable_registered);
386   grpc_ares_ev_driver* ev_driver = fdn->ev_driver;
387   const ares_socket_t as = fdn->grpc_polled_fd->GetWrappedAresSocketLocked();
388   fdn->writable_registered = false;
389   GRPC_CARES_TRACE_LOG("request:%p writable on %s", ev_driver->request,
390                        fdn->grpc_polled_fd->GetName());
391   if (error.ok() && !ev_driver->shutting_down) {
392     ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, as);
393   } else {
394     // If error is not absl::OkStatus() or the resolution was cancelled, it
395     // means the fd has been shutdown or timed out. The pending lookups made on
396     // this ev_driver will be cancelled by the following ares_cancel() and the
397     // on_done callbacks will be invoked with a status of ARES_ECANCELLED. The
398     // remaining file descriptors in this ev_driver will be cleaned up in the
399     // follwing grpc_ares_notify_on_event_locked().
400     ares_cancel(ev_driver->channel);
401   }
402   grpc_ares_notify_on_event_locked(ev_driver);
403   grpc_ares_ev_driver_unref(ev_driver);
404 }
405 
406 // Get the file descriptors used by the ev_driver's ares channel, register
407 // driver_closure with these filedescriptors.
grpc_ares_notify_on_event_locked(grpc_ares_ev_driver * ev_driver)408 static void grpc_ares_notify_on_event_locked(grpc_ares_ev_driver* ev_driver)
409     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
410   fd_node* new_list = nullptr;
411   if (!ev_driver->shutting_down) {
412     ares_socket_t socks[ARES_GETSOCK_MAXNUM];
413     int socks_bitmask =
414         ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM);
415     for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) {
416       if (ARES_GETSOCK_READABLE(socks_bitmask, i) ||
417           ARES_GETSOCK_WRITABLE(socks_bitmask, i)) {
418         fd_node* fdn = pop_fd_node_locked(&ev_driver->fds, socks[i]);
419         // Create a new fd_node if sock[i] is not in the fd_node list.
420         if (fdn == nullptr) {
421           fdn = new fd_node(ev_driver);
422           fdn->grpc_polled_fd =
423               ev_driver->polled_fd_factory->NewGrpcPolledFdLocked(
424                   socks[i], ev_driver->pollset_set);
425           GRPC_CARES_TRACE_LOG("request:%p new fd: %s", ev_driver->request,
426                                fdn->grpc_polled_fd->GetName());
427           fdn->readable_registered = false;
428           fdn->writable_registered = false;
429           fdn->already_shutdown = false;
430         }
431         fdn->next = new_list;
432         new_list = fdn;
433         // Register read_closure if the socket is readable and read_closure has
434         // not been registered with this socket.
435         if (ARES_GETSOCK_READABLE(socks_bitmask, i) &&
436             !fdn->readable_registered) {
437           grpc_ares_ev_driver_ref(ev_driver);
438           GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable, fdn,
439                             grpc_schedule_on_exec_ctx);
440           if (fdn->grpc_polled_fd->IsFdStillReadableLocked()) {
441             GRPC_CARES_TRACE_LOG("request:%p schedule direct read on: %s",
442                                  ev_driver->request,
443                                  fdn->grpc_polled_fd->GetName());
444             grpc_core::ExecCtx::Run(DEBUG_LOCATION, &fdn->read_closure,
445                                     absl::OkStatus());
446           } else {
447             GRPC_CARES_TRACE_LOG("request:%p notify read on: %s",
448                                  ev_driver->request,
449                                  fdn->grpc_polled_fd->GetName());
450             fdn->grpc_polled_fd->RegisterForOnReadableLocked(
451                 &fdn->read_closure);
452           }
453           fdn->readable_registered = true;
454         }
455         // Register write_closure if the socket is writable and write_closure
456         // has not been registered with this socket.
457         if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) &&
458             !fdn->writable_registered) {
459           GRPC_CARES_TRACE_LOG("request:%p notify write on: %s",
460                                ev_driver->request,
461                                fdn->grpc_polled_fd->GetName());
462           grpc_ares_ev_driver_ref(ev_driver);
463           GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable, fdn,
464                             grpc_schedule_on_exec_ctx);
465           fdn->grpc_polled_fd->RegisterForOnWriteableLocked(
466               &fdn->write_closure);
467           fdn->writable_registered = true;
468         }
469       }
470     }
471   }
472   // Any remaining fds in ev_driver->fds were not returned by ares_getsock() and
473   // are therefore no longer in use, so they can be shut down and removed from
474   // the list.
475   while (ev_driver->fds != nullptr) {
476     fd_node* cur = ev_driver->fds;
477     ev_driver->fds = ev_driver->fds->next;
478     fd_node_shutdown_locked(cur, "c-ares fd shutdown");
479     if (!cur->readable_registered && !cur->writable_registered) {
480       fd_node_destroy_locked(cur);
481     } else {
482       cur->next = new_list;
483       new_list = cur;
484     }
485   }
486   ev_driver->fds = new_list;
487 }
488 
grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver * ev_driver)489 void grpc_ares_ev_driver_start_locked(grpc_ares_ev_driver* ev_driver)
490     ABSL_EXCLUSIVE_LOCKS_REQUIRED(&grpc_ares_request::mu) {
491   grpc_ares_notify_on_event_locked(ev_driver);
492   // Initialize overall DNS resolution timeout alarm
493   grpc_core::Duration timeout =
494       ev_driver->query_timeout_ms == 0
495           ? grpc_core::Duration::Infinity()
496           : grpc_core::Duration::Milliseconds(ev_driver->query_timeout_ms);
497   GRPC_CARES_TRACE_LOG(
498       "request:%p ev_driver=%p grpc_ares_ev_driver_start_locked. timeout in "
499       "%" PRId64 " ms",
500       ev_driver->request, ev_driver, timeout.millis());
501   grpc_ares_ev_driver_ref(ev_driver);
502   GRPC_CLOSURE_INIT(&ev_driver->on_timeout_locked, on_timeout, ev_driver,
503                     grpc_schedule_on_exec_ctx);
504   grpc_timer_init(&ev_driver->query_timeout,
505                   grpc_core::Timestamp::Now() + timeout,
506                   &ev_driver->on_timeout_locked);
507   // Initialize the backup poll alarm
508   grpc_core::Timestamp next_ares_backup_poll_alarm =
509       calculate_next_ares_backup_poll_alarm(ev_driver);
510   grpc_ares_ev_driver_ref(ev_driver);
511   GRPC_CLOSURE_INIT(&ev_driver->on_ares_backup_poll_alarm_locked,
512                     on_ares_backup_poll_alarm, ev_driver,
513                     grpc_schedule_on_exec_ctx);
514   grpc_timer_init(&ev_driver->ares_backup_poll_alarm,
515                   next_ares_backup_poll_alarm,
516                   &ev_driver->on_ares_backup_poll_alarm_locked);
517 }
518 
noop_inject_channel_config(ares_channel *)519 static void noop_inject_channel_config(ares_channel* /*channel*/) {}
520 
521 void (*grpc_ares_test_only_inject_config)(ares_channel* channel) =
522     noop_inject_channel_config;
523 
524 bool g_grpc_ares_test_only_force_tcp = false;
525 
grpc_ares_ev_driver_create_locked(grpc_ares_ev_driver ** ev_driver,grpc_pollset_set * pollset_set,int query_timeout_ms,grpc_ares_request * request)526 grpc_error_handle grpc_ares_ev_driver_create_locked(
527     grpc_ares_ev_driver** ev_driver, grpc_pollset_set* pollset_set,
528     int query_timeout_ms, grpc_ares_request* request)
529     ABSL_EXCLUSIVE_LOCKS_REQUIRED(request->mu) {
530   *ev_driver = new grpc_ares_ev_driver(request);
531   ares_options opts;
532   memset(&opts, 0, sizeof(opts));
533   opts.flags |= ARES_FLAG_STAYOPEN;
534   if (g_grpc_ares_test_only_force_tcp) {
535     opts.flags |= ARES_FLAG_USEVC;
536   }
537   int status = ares_init_options(&(*ev_driver)->channel, &opts, ARES_OPT_FLAGS);
538   grpc_ares_test_only_inject_config(&(*ev_driver)->channel);
539   GRPC_CARES_TRACE_LOG("request:%p grpc_ares_ev_driver_create_locked", request);
540   if (status != ARES_SUCCESS) {
541     grpc_error_handle err = GRPC_ERROR_CREATE(absl::StrCat(
542         "Failed to init ares channel. C-ares error: ", ares_strerror(status)));
543     delete *ev_driver;
544     return err;
545   }
546   gpr_ref_init(&(*ev_driver)->refs, 1);
547   (*ev_driver)->pollset_set = pollset_set;
548   (*ev_driver)->fds = nullptr;
549   (*ev_driver)->shutting_down = false;
550   (*ev_driver)->polled_fd_factory =
551       grpc_core::NewGrpcPolledFdFactory(&(*ev_driver)->request->mu);
552   (*ev_driver)
553       ->polled_fd_factory->ConfigureAresChannelLocked((*ev_driver)->channel);
554   (*ev_driver)->query_timeout_ms = query_timeout_ms;
555   return absl::OkStatus();
556 }
557 
log_address_sorting_list(const grpc_ares_request * r,const EndpointAddressesList & addresses,const char * input_output_str)558 static void log_address_sorting_list(const grpc_ares_request* r,
559                                      const EndpointAddressesList& addresses,
560                                      const char* input_output_str) {
561   for (size_t i = 0; i < addresses.size(); i++) {
562     auto addr_str = grpc_sockaddr_to_string(&addresses[i].address(), true);
563     gpr_log(GPR_INFO,
564             "(c-ares resolver) request:%p c-ares address sorting: %s[%" PRIuPTR
565             "]=%s",
566             r, input_output_str, i,
567             addr_str.ok() ? addr_str->c_str()
568                           : addr_str.status().ToString().c_str());
569   }
570 }
571 
grpc_cares_wrapper_address_sorting_sort(const grpc_ares_request * r,EndpointAddressesList * addresses)572 void grpc_cares_wrapper_address_sorting_sort(const grpc_ares_request* r,
573                                              EndpointAddressesList* addresses) {
574   if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_cares_address_sorting)) {
575     log_address_sorting_list(r, *addresses, "input");
576   }
577   address_sorting_sortable* sortables = static_cast<address_sorting_sortable*>(
578       gpr_zalloc(sizeof(address_sorting_sortable) * addresses->size()));
579   for (size_t i = 0; i < addresses->size(); ++i) {
580     sortables[i].user_data = &(*addresses)[i];
581     memcpy(&sortables[i].dest_addr.addr, &(*addresses)[i].address().addr,
582            (*addresses)[i].address().len);
583     sortables[i].dest_addr.len = (*addresses)[i].address().len;
584   }
585   address_sorting_rfc_6724_sort(sortables, addresses->size());
586   EndpointAddressesList sorted;
587   sorted.reserve(addresses->size());
588   for (size_t i = 0; i < addresses->size(); ++i) {
589     sorted.emplace_back(
590         *static_cast<EndpointAddresses*>(sortables[i].user_data));
591   }
592   gpr_free(sortables);
593   *addresses = std::move(sorted);
594   if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_cares_address_sorting)) {
595     log_address_sorting_list(r, *addresses, "output");
596   }
597 }
598 
grpc_ares_request_ref_locked(grpc_ares_request * r)599 static void grpc_ares_request_ref_locked(grpc_ares_request* r)
600     ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) {
601   r->pending_queries++;
602 }
603 
grpc_ares_request_unref_locked(grpc_ares_request * r)604 static void grpc_ares_request_unref_locked(grpc_ares_request* r)
605     ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) {
606   r->pending_queries--;
607   if (r->pending_queries == 0u) {
608     grpc_ares_ev_driver_on_queries_complete_locked(r->ev_driver);
609   }
610 }
611 
grpc_ares_complete_request_locked(grpc_ares_request * r)612 void grpc_ares_complete_request_locked(grpc_ares_request* r)
613     ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) {
614   // Invoke on_done callback and destroy the request
615   r->ev_driver = nullptr;
616   if (r->addresses_out != nullptr && *r->addresses_out != nullptr) {
617     grpc_cares_wrapper_address_sorting_sort(r, r->addresses_out->get());
618     r->error = absl::OkStatus();
619     // TODO(apolcyn): allow c-ares to return a service config
620     // with no addresses along side it
621   }
622   if (r->balancer_addresses_out != nullptr) {
623     EndpointAddressesList* balancer_addresses =
624         r->balancer_addresses_out->get();
625     if (balancer_addresses != nullptr) {
626       grpc_cares_wrapper_address_sorting_sort(r, balancer_addresses);
627     }
628   }
629   grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, r->error);
630 }
631 
632 // Note that the returned object takes a reference to qtype, so
633 // qtype must outlive it.
create_hostbyname_request_locked(grpc_ares_request * parent_request,const char * host,uint16_t port,bool is_balancer,const char * qtype)634 static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
635     grpc_ares_request* parent_request, const char* host, uint16_t port,
636     bool is_balancer, const char* qtype)
637     ABSL_EXCLUSIVE_LOCKS_REQUIRED(parent_request->mu) {
638   GRPC_CARES_TRACE_LOG(
639       "request:%p create_hostbyname_request_locked host:%s port:%d "
640       "is_balancer:%d qtype:%s",
641       parent_request, host, port, is_balancer, qtype);
642   grpc_ares_hostbyname_request* hr = new grpc_ares_hostbyname_request();
643   hr->parent_request = parent_request;
644   hr->host = gpr_strdup(host);
645   hr->port = port;
646   hr->is_balancer = is_balancer;
647   hr->qtype = qtype;
648   grpc_ares_request_ref_locked(parent_request);
649   return hr;
650 }
651 
destroy_hostbyname_request_locked(grpc_ares_hostbyname_request * hr)652 static void destroy_hostbyname_request_locked(grpc_ares_hostbyname_request* hr)
653     ABSL_EXCLUSIVE_LOCKS_REQUIRED(hr->parent_request->mu) {
654   grpc_ares_request_unref_locked(hr->parent_request);
655   gpr_free(hr->host);
656   delete hr;
657 }
658 
on_hostbyname_done_locked(void * arg,int status,int,struct hostent * hostent)659 static void on_hostbyname_done_locked(void* arg, int status, int /*timeouts*/,
660                                       struct hostent* hostent)
661     ABSL_NO_THREAD_SAFETY_ANALYSIS {
662   // This callback is invoked from the c-ares library, so disable thread safety
663   // analysis. Note that we are guaranteed to be holding r->mu, though.
664   grpc_ares_hostbyname_request* hr =
665       static_cast<grpc_ares_hostbyname_request*>(arg);
666   grpc_ares_request* r = hr->parent_request;
667   if (status == ARES_SUCCESS) {
668     GRPC_CARES_TRACE_LOG(
669         "request:%p on_hostbyname_done_locked qtype=%s host=%s ARES_SUCCESS", r,
670         hr->qtype, hr->host);
671     std::unique_ptr<EndpointAddressesList>* address_list_ptr =
672         hr->is_balancer ? r->balancer_addresses_out : r->addresses_out;
673     if (*address_list_ptr == nullptr) {
674       *address_list_ptr = std::make_unique<EndpointAddressesList>();
675     }
676     EndpointAddressesList& addresses = **address_list_ptr;
677     for (size_t i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
678       grpc_core::ChannelArgs args;
679       if (hr->is_balancer) {
680         args = args.Set(GRPC_ARG_DEFAULT_AUTHORITY, hr->host);
681       }
682       grpc_resolved_address address;
683       memset(&address, 0, sizeof(address));
684       switch (hostent->h_addrtype) {
685         case AF_INET6: {
686           address.len = sizeof(struct sockaddr_in6);
687           auto* addr = reinterpret_cast<struct sockaddr_in6*>(&address.addr);
688           memcpy(&addr->sin6_addr, hostent->h_addr_list[i],
689                  sizeof(struct in6_addr));
690           addr->sin6_family = static_cast<unsigned char>(hostent->h_addrtype);
691           addr->sin6_port = hr->port;
692           char output[INET6_ADDRSTRLEN];
693           ares_inet_ntop(AF_INET6, &addr->sin6_addr, output, INET6_ADDRSTRLEN);
694           GRPC_CARES_TRACE_LOG(
695               "request:%p c-ares resolver gets a AF_INET6 result: \n"
696               "  addr: %s\n  port: %d\n  sin6_scope_id: %d\n",
697               r, output, ntohs(hr->port), addr->sin6_scope_id);
698           break;
699         }
700         case AF_INET: {
701           address.len = sizeof(struct sockaddr_in);
702           auto* addr = reinterpret_cast<struct sockaddr_in*>(&address.addr);
703           memcpy(&addr->sin_addr, hostent->h_addr_list[i],
704                  sizeof(struct in_addr));
705           addr->sin_family = static_cast<unsigned char>(hostent->h_addrtype);
706           addr->sin_port = hr->port;
707           char output[INET_ADDRSTRLEN];
708           ares_inet_ntop(AF_INET, &addr->sin_addr, output, INET_ADDRSTRLEN);
709           GRPC_CARES_TRACE_LOG(
710               "request:%p c-ares resolver gets a AF_INET result: \n"
711               "  addr: %s\n  port: %d\n",
712               r, output, ntohs(hr->port));
713           break;
714         }
715       }
716       addresses.emplace_back(address, args);
717     }
718   } else {
719     std::string error_msg = absl::StrFormat(
720         "C-ares status is not ARES_SUCCESS qtype=%s name=%s is_balancer=%d: %s",
721         hr->qtype, hr->host, hr->is_balancer, ares_strerror(status));
722     GRPC_CARES_TRACE_LOG("request:%p on_hostbyname_done_locked: %s", r,
723                          error_msg.c_str());
724     grpc_error_handle error = GRPC_ERROR_CREATE(error_msg);
725     r->error = grpc_error_add_child(error, r->error);
726   }
727   destroy_hostbyname_request_locked(hr);
728 }
729 
on_srv_query_done_locked(void * arg,int status,int,unsigned char * abuf,int alen)730 static void on_srv_query_done_locked(void* arg, int status, int /*timeouts*/,
731                                      unsigned char* abuf,
732                                      int alen) ABSL_NO_THREAD_SAFETY_ANALYSIS {
733   // This callback is invoked from the c-ares library, so disable thread safety
734   // analysis. Note that we are guaranteed to be holding r->mu, though.
735   GrpcAresQuery* q = static_cast<GrpcAresQuery*>(arg);
736   grpc_ares_request* r = q->parent_request();
737   if (status == ARES_SUCCESS) {
738     GRPC_CARES_TRACE_LOG(
739         "request:%p on_srv_query_done_locked name=%s ARES_SUCCESS", r,
740         q->name().c_str());
741     struct ares_srv_reply* reply;
742     const int parse_status = ares_parse_srv_reply(abuf, alen, &reply);
743     GRPC_CARES_TRACE_LOG("request:%p ares_parse_srv_reply: %d", r,
744                          parse_status);
745     if (parse_status == ARES_SUCCESS) {
746       for (struct ares_srv_reply* srv_it = reply; srv_it != nullptr;
747            srv_it = srv_it->next) {
748         if (grpc_ares_query_ipv6()) {
749           grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
750               r, srv_it->host, htons(srv_it->port), true /* is_balancer */,
751               "AAAA");
752           ares_gethostbyname(r->ev_driver->channel, hr->host, AF_INET6,
753                              on_hostbyname_done_locked, hr);
754         }
755         grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
756             r, srv_it->host, htons(srv_it->port), true /* is_balancer */, "A");
757         ares_gethostbyname(r->ev_driver->channel, hr->host, AF_INET,
758                            on_hostbyname_done_locked, hr);
759       }
760     }
761     if (reply != nullptr) {
762       ares_free_data(reply);
763     }
764   } else {
765     std::string error_msg = absl::StrFormat(
766         "C-ares status is not ARES_SUCCESS qtype=SRV name=%s: %s", q->name(),
767         ares_strerror(status));
768     GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked: %s", r,
769                          error_msg.c_str());
770     grpc_error_handle error = GRPC_ERROR_CREATE(error_msg);
771     r->error = grpc_error_add_child(error, r->error);
772   }
773   delete q;
774 }
775 
776 static const char g_service_config_attribute_prefix[] = "grpc_config=";
777 
on_txt_done_locked(void * arg,int status,int,unsigned char * buf,int len)778 static void on_txt_done_locked(void* arg, int status, int /*timeouts*/,
779                                unsigned char* buf,
780                                int len) ABSL_NO_THREAD_SAFETY_ANALYSIS {
781   // This callback is invoked from the c-ares library, so disable thread safety
782   // analysis. Note that we are guaranteed to be holding r->mu, though.
783   GrpcAresQuery* q = static_cast<GrpcAresQuery*>(arg);
784   std::unique_ptr<GrpcAresQuery> query_deleter(q);
785   grpc_ares_request* r = q->parent_request();
786   const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1;
787   struct ares_txt_ext* result = nullptr;
788   struct ares_txt_ext* reply = nullptr;
789   grpc_error_handle error;
790   if (status != ARES_SUCCESS) goto fail;
791   GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked name=%s ARES_SUCCESS", r,
792                        q->name().c_str());
793   status = ares_parse_txt_reply_ext(buf, len, &reply);
794   if (status != ARES_SUCCESS) goto fail;
795   // Find service config in TXT record.
796   for (result = reply; result != nullptr; result = result->next) {
797     if (result->record_start &&
798         memcmp(result->txt, g_service_config_attribute_prefix, prefix_len) ==
799             0) {
800       break;
801     }
802   }
803   // Found a service config record.
804   if (result != nullptr) {
805     size_t service_config_len = result->length - prefix_len;
806     *r->service_config_json_out =
807         static_cast<char*>(gpr_malloc(service_config_len + 1));
808     memcpy(*r->service_config_json_out, result->txt + prefix_len,
809            service_config_len);
810     for (result = result->next; result != nullptr && !result->record_start;
811          result = result->next) {
812       *r->service_config_json_out = static_cast<char*>(
813           gpr_realloc(*r->service_config_json_out,
814                       service_config_len + result->length + 1));
815       memcpy(*r->service_config_json_out + service_config_len, result->txt,
816              result->length);
817       service_config_len += result->length;
818     }
819     (*r->service_config_json_out)[service_config_len] = '\0';
820     GRPC_CARES_TRACE_LOG("request:%p found service config: %s", r,
821                          *r->service_config_json_out);
822   }
823   // Clean up.
824   ares_free_data(reply);
825   grpc_ares_request_unref_locked(r);
826   return;
827 fail:
828   std::string error_msg =
829       absl::StrFormat("C-ares status is not ARES_SUCCESS qtype=TXT name=%s: %s",
830                       q->name(), ares_strerror(status));
831   GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked %s", r,
832                        error_msg.c_str());
833   error = GRPC_ERROR_CREATE(error_msg);
834   r->error = grpc_error_add_child(error, r->error);
835 }
836 
set_request_dns_server(grpc_ares_request * r,absl::string_view dns_server)837 grpc_error_handle set_request_dns_server(grpc_ares_request* r,
838                                          absl::string_view dns_server)
839     ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) {
840   if (!dns_server.empty()) {
841     GRPC_CARES_TRACE_LOG("request:%p Using DNS server %s", r,
842                          dns_server.data());
843     grpc_resolved_address addr;
844     if (grpc_parse_ipv4_hostport(dns_server, &addr, /*log_errors=*/false)) {
845       r->dns_server_addr.family = AF_INET;
846       struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(addr.addr);
847       memcpy(&r->dns_server_addr.addr.addr4, &in->sin_addr,
848              sizeof(struct in_addr));
849       r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
850       r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
851     } else if (grpc_parse_ipv6_hostport(dns_server, &addr,
852                                         /*log_errors=*/false)) {
853       r->dns_server_addr.family = AF_INET6;
854       struct sockaddr_in6* in6 =
855           reinterpret_cast<struct sockaddr_in6*>(addr.addr);
856       memcpy(&r->dns_server_addr.addr.addr6, &in6->sin6_addr,
857              sizeof(struct in6_addr));
858       r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
859       r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
860     } else {
861       return GRPC_ERROR_CREATE(
862           absl::StrCat("cannot parse authority ", dns_server));
863     }
864     int status =
865         ares_set_servers_ports(r->ev_driver->channel, &r->dns_server_addr);
866     if (status != ARES_SUCCESS) {
867       return GRPC_ERROR_CREATE(absl::StrCat(
868           "C-ares status is not ARES_SUCCESS: ", ares_strerror(status)));
869     }
870   }
871   return absl::OkStatus();
872 }
873 
874 // Common logic for all lookup methods.
875 // If an error occurs, callers must run the client callback.
grpc_dns_lookup_ares_continued(grpc_ares_request * r,const char * dns_server,const char * name,const char * default_port,grpc_pollset_set * interested_parties,int query_timeout_ms,std::string * host,std::string * port,bool check_port)876 grpc_error_handle grpc_dns_lookup_ares_continued(
877     grpc_ares_request* r, const char* dns_server, const char* name,
878     const char* default_port, grpc_pollset_set* interested_parties,
879     int query_timeout_ms, std::string* host, std::string* port, bool check_port)
880     ABSL_EXCLUSIVE_LOCKS_REQUIRED(r->mu) {
881   grpc_error_handle error;
882   // parse name, splitting it into host and port parts
883   grpc_core::SplitHostPort(name, host, port);
884   if (host->empty()) {
885     error =
886         grpc_error_set_str(GRPC_ERROR_CREATE("unparseable host:port"),
887                            grpc_core::StatusStrProperty::kTargetAddress, name);
888     return error;
889   } else if (check_port && port->empty()) {
890     if (default_port == nullptr || strlen(default_port) == 0) {
891       error = grpc_error_set_str(GRPC_ERROR_CREATE("no port in name"),
892                                  grpc_core::StatusStrProperty::kTargetAddress,
893                                  name);
894       return error;
895     }
896     *port = default_port;
897   }
898   error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties,
899                                             query_timeout_ms, r);
900   if (!error.ok()) return error;
901   // If dns_server is specified, use it.
902   error = set_request_dns_server(r, dns_server);
903   return error;
904 }
905 
inner_resolve_as_ip_literal_locked(const char * name,const char * default_port,std::unique_ptr<grpc_core::EndpointAddressesList> * addrs,std::string * host,std::string * port,std::string * hostport)906 static bool inner_resolve_as_ip_literal_locked(
907     const char* name, const char* default_port,
908     std::unique_ptr<grpc_core::EndpointAddressesList>* addrs, std::string* host,
909     std::string* port, std::string* hostport) {
910   if (!grpc_core::SplitHostPort(name, host, port)) {
911     gpr_log(GPR_ERROR,
912             "Failed to parse %s to host:port while attempting to resolve as ip "
913             "literal.",
914             name);
915     return false;
916   }
917   if (port->empty()) {
918     if (default_port == nullptr || strlen(default_port) == 0) {
919       gpr_log(GPR_ERROR,
920               "No port or default port for %s while attempting to resolve as "
921               "ip literal.",
922               name);
923       return false;
924     }
925     *port = default_port;
926   }
927   grpc_resolved_address addr;
928   *hostport = grpc_core::JoinHostPort(*host, atoi(port->c_str()));
929   if (grpc_parse_ipv4_hostport(hostport->c_str(), &addr,
930                                false /* log errors */) ||
931       grpc_parse_ipv6_hostport(hostport->c_str(), &addr,
932                                false /* log errors */)) {
933     GPR_ASSERT(*addrs == nullptr);
934     *addrs = std::make_unique<EndpointAddressesList>();
935     (*addrs)->emplace_back(addr, grpc_core::ChannelArgs());
936     return true;
937   }
938   return false;
939 }
940 
resolve_as_ip_literal_locked(const char * name,const char * default_port,std::unique_ptr<grpc_core::EndpointAddressesList> * addrs)941 static bool resolve_as_ip_literal_locked(
942     const char* name, const char* default_port,
943     std::unique_ptr<grpc_core::EndpointAddressesList>* addrs) {
944   std::string host;
945   std::string port;
946   std::string hostport;
947   bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs,
948                                                 &host, &port, &hostport);
949   return out;
950 }
951 
target_matches_localhost_inner(const char * name,std::string * host,std::string * port)952 static bool target_matches_localhost_inner(const char* name, std::string* host,
953                                            std::string* port) {
954   if (!grpc_core::SplitHostPort(name, host, port)) {
955     gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name);
956     return false;
957   }
958   return gpr_stricmp(host->c_str(), "localhost") == 0;
959 }
960 
target_matches_localhost(const char * name)961 static bool target_matches_localhost(const char* name) {
962   std::string host;
963   std::string port;
964   return target_matches_localhost_inner(name, &host, &port);
965 }
966 
967 #ifdef GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
inner_maybe_resolve_localhost_manually_locked(const grpc_ares_request * r,const char * name,const char * default_port,std::unique_ptr<grpc_core::EndpointAddressesList> * addrs,std::string * host,std::string * port)968 static bool inner_maybe_resolve_localhost_manually_locked(
969     const grpc_ares_request* r, const char* name, const char* default_port,
970     std::unique_ptr<grpc_core::EndpointAddressesList>* addrs, std::string* host,
971     std::string* port) {
972   grpc_core::SplitHostPort(name, host, port);
973   if (host->empty()) {
974     gpr_log(GPR_ERROR,
975             "Failed to parse %s into host:port during manual localhost "
976             "resolution check.",
977             name);
978     return false;
979   }
980   if (port->empty()) {
981     if (default_port == nullptr || strlen(default_port) == 0) {
982       gpr_log(GPR_ERROR,
983               "No port or default port for %s during manual localhost "
984               "resolution check.",
985               name);
986       return false;
987     }
988     *port = default_port;
989   }
990   if (gpr_stricmp(host->c_str(), "localhost") == 0) {
991     GPR_ASSERT(*addrs == nullptr);
992     *addrs = std::make_unique<grpc_core::EndpointAddressesList>();
993     uint16_t numeric_port = grpc_strhtons(port->c_str());
994     grpc_resolved_address address;
995     // Append the ipv6 loopback address.
996     memset(&address, 0, sizeof(address));
997     auto* ipv6_loopback_addr =
998         reinterpret_cast<struct sockaddr_in6*>(&address.addr);
999     ((char*)&ipv6_loopback_addr->sin6_addr)[15] = 1;
1000     ipv6_loopback_addr->sin6_family = AF_INET6;
1001     ipv6_loopback_addr->sin6_port = numeric_port;
1002     address.len = sizeof(struct sockaddr_in6);
1003     (*addrs)->emplace_back(address, grpc_core::ChannelArgs());
1004     // Append the ipv4 loopback address.
1005     memset(&address, 0, sizeof(address));
1006     auto* ipv4_loopback_addr =
1007         reinterpret_cast<struct sockaddr_in*>(&address.addr);
1008     ((char*)&ipv4_loopback_addr->sin_addr)[0] = 0x7f;
1009     ((char*)&ipv4_loopback_addr->sin_addr)[3] = 0x01;
1010     ipv4_loopback_addr->sin_family = AF_INET;
1011     ipv4_loopback_addr->sin_port = numeric_port;
1012     address.len = sizeof(struct sockaddr_in);
1013     (*addrs)->emplace_back(address, grpc_core::ChannelArgs());
1014     // Let the address sorter figure out which one should be tried first.
1015     grpc_cares_wrapper_address_sorting_sort(r, addrs->get());
1016     return true;
1017   }
1018   return false;
1019 }
1020 
grpc_ares_maybe_resolve_localhost_manually_locked(const grpc_ares_request * r,const char * name,const char * default_port,std::unique_ptr<grpc_core::EndpointAddressesList> * addrs)1021 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
1022     const grpc_ares_request* r, const char* name, const char* default_port,
1023     std::unique_ptr<grpc_core::EndpointAddressesList>* addrs) {
1024   std::string host;
1025   std::string port;
1026   return inner_maybe_resolve_localhost_manually_locked(r, name, default_port,
1027                                                        addrs, &host, &port);
1028 }
1029 #else   // GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
grpc_ares_maybe_resolve_localhost_manually_locked(const grpc_ares_request *,const char *,const char *,std::unique_ptr<grpc_core::EndpointAddressesList> *)1030 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
1031     const grpc_ares_request* /*r*/, const char* /*name*/,
1032     const char* /*default_port*/,
1033     std::unique_ptr<grpc_core::EndpointAddressesList>* /*addrs*/) {
1034   return false;
1035 }
1036 #endif  // GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
1037 
grpc_dns_lookup_hostname_ares_impl(const char * dns_server,const char * name,const char * default_port,grpc_pollset_set * interested_parties,grpc_closure * on_done,std::unique_ptr<grpc_core::EndpointAddressesList> * addrs,int query_timeout_ms)1038 static grpc_ares_request* grpc_dns_lookup_hostname_ares_impl(
1039     const char* dns_server, const char* name, const char* default_port,
1040     grpc_pollset_set* interested_parties, grpc_closure* on_done,
1041     std::unique_ptr<grpc_core::EndpointAddressesList>* addrs,
1042     int query_timeout_ms) {
1043   grpc_ares_request* r = new grpc_ares_request();
1044   grpc_core::MutexLock lock(&r->mu);
1045   r->ev_driver = nullptr;
1046   r->on_done = on_done;
1047   r->addresses_out = addrs;
1048   GRPC_CARES_TRACE_LOG(
1049       "request:%p c-ares grpc_dns_lookup_hostname_ares_impl name=%s, "
1050       "default_port=%s",
1051       r, name, default_port);
1052   // Early out if the target is an ipv4 or ipv6 literal.
1053   if (resolve_as_ip_literal_locked(name, default_port, addrs)) {
1054     grpc_ares_complete_request_locked(r);
1055     return r;
1056   }
1057   // Early out if the target is localhost and we're on Windows.
1058   if (grpc_ares_maybe_resolve_localhost_manually_locked(r, name, default_port,
1059                                                         addrs)) {
1060     grpc_ares_complete_request_locked(r);
1061     return r;
1062   }
1063   // Look up name using c-ares lib.
1064   std::string host;
1065   std::string port;
1066   grpc_error_handle error = grpc_dns_lookup_ares_continued(
1067       r, dns_server, name, default_port, interested_parties, query_timeout_ms,
1068       &host, &port, true);
1069   if (!error.ok()) {
1070     grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, error);
1071     return r;
1072   }
1073   r->pending_queries = 1;
1074   grpc_ares_hostbyname_request* hr = nullptr;
1075   if (grpc_ares_query_ipv6()) {
1076     hr = create_hostbyname_request_locked(r, host.c_str(),
1077                                           grpc_strhtons(port.c_str()),
1078                                           /*is_balancer=*/false, "AAAA");
1079     ares_gethostbyname(r->ev_driver->channel, hr->host, AF_INET6,
1080                        on_hostbyname_done_locked, hr);
1081   }
1082   hr = create_hostbyname_request_locked(r, host.c_str(),
1083                                         grpc_strhtons(port.c_str()),
1084                                         /*is_balancer=*/false, "A");
1085   ares_gethostbyname(r->ev_driver->channel, hr->host, AF_INET,
1086                      on_hostbyname_done_locked, hr);
1087   grpc_ares_ev_driver_start_locked(r->ev_driver);
1088   grpc_ares_request_unref_locked(r);
1089   return r;
1090 }
1091 
grpc_dns_lookup_srv_ares_impl(const char * dns_server,const char * name,grpc_pollset_set * interested_parties,grpc_closure * on_done,std::unique_ptr<grpc_core::EndpointAddressesList> * balancer_addresses,int query_timeout_ms)1092 grpc_ares_request* grpc_dns_lookup_srv_ares_impl(
1093     const char* dns_server, const char* name,
1094     grpc_pollset_set* interested_parties, grpc_closure* on_done,
1095     std::unique_ptr<grpc_core::EndpointAddressesList>* balancer_addresses,
1096     int query_timeout_ms) {
1097   grpc_ares_request* r = new grpc_ares_request();
1098   grpc_core::MutexLock lock(&r->mu);
1099   r->ev_driver = nullptr;
1100   r->on_done = on_done;
1101   r->balancer_addresses_out = balancer_addresses;
1102   GRPC_CARES_TRACE_LOG(
1103       "request:%p c-ares grpc_dns_lookup_srv_ares_impl name=%s", r, name);
1104   grpc_error_handle error;
1105   // Don't query for SRV records if the target is "localhost"
1106   if (target_matches_localhost(name)) {
1107     grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, error);
1108     return r;
1109   }
1110   // Look up name using c-ares lib.
1111   std::string host;
1112   std::string port;
1113   error = grpc_dns_lookup_ares_continued(r, dns_server, name, nullptr,
1114                                          interested_parties, query_timeout_ms,
1115                                          &host, &port, false);
1116   if (!error.ok()) {
1117     grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, error);
1118     return r;
1119   }
1120   r->pending_queries = 1;
1121   // Query the SRV record
1122   std::string service_name = absl::StrCat("_grpclb._tcp.", host);
1123   GrpcAresQuery* srv_query = new GrpcAresQuery(r, service_name);
1124   ares_query(r->ev_driver->channel, service_name.c_str(), ns_c_in, ns_t_srv,
1125              on_srv_query_done_locked, srv_query);
1126   grpc_ares_ev_driver_start_locked(r->ev_driver);
1127   grpc_ares_request_unref_locked(r);
1128   return r;
1129 }
1130 
grpc_dns_lookup_txt_ares_impl(const char * dns_server,const char * name,grpc_pollset_set * interested_parties,grpc_closure * on_done,char ** service_config_json,int query_timeout_ms)1131 grpc_ares_request* grpc_dns_lookup_txt_ares_impl(
1132     const char* dns_server, const char* name,
1133     grpc_pollset_set* interested_parties, grpc_closure* on_done,
1134     char** service_config_json, int query_timeout_ms) {
1135   grpc_ares_request* r = new grpc_ares_request();
1136   grpc_core::MutexLock lock(&r->mu);
1137   r->ev_driver = nullptr;
1138   r->on_done = on_done;
1139   r->service_config_json_out = service_config_json;
1140   GRPC_CARES_TRACE_LOG(
1141       "request:%p c-ares grpc_dns_lookup_txt_ares_impl name=%s", r, name);
1142   grpc_error_handle error;
1143   // Don't query for TXT records if the target is "localhost"
1144   if (target_matches_localhost(name)) {
1145     grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, error);
1146     return r;
1147   }
1148   // Look up name using c-ares lib.
1149   std::string host;
1150   std::string port;
1151   error = grpc_dns_lookup_ares_continued(r, dns_server, name, nullptr,
1152                                          interested_parties, query_timeout_ms,
1153                                          &host, &port, false);
1154   if (!error.ok()) {
1155     grpc_core::ExecCtx::Run(DEBUG_LOCATION, r->on_done, error);
1156     return r;
1157   }
1158   r->pending_queries = 1;
1159   // Query the TXT record
1160   std::string config_name = absl::StrCat("_grpc_config.", host);
1161   GrpcAresQuery* txt_query = new GrpcAresQuery(r, config_name);
1162   ares_search(r->ev_driver->channel, config_name.c_str(), ns_c_in, ns_t_txt,
1163               on_txt_done_locked, txt_query);
1164   grpc_ares_ev_driver_start_locked(r->ev_driver);
1165   grpc_ares_request_unref_locked(r);
1166   return r;
1167 }
1168 
1169 grpc_ares_request* (*grpc_dns_lookup_hostname_ares)(
1170     const char* dns_server, const char* name, const char* default_port,
1171     grpc_pollset_set* interested_parties, grpc_closure* on_done,
1172     std::unique_ptr<grpc_core::EndpointAddressesList>* addrs,
1173     int query_timeout_ms) = grpc_dns_lookup_hostname_ares_impl;
1174 
1175 grpc_ares_request* (*grpc_dns_lookup_srv_ares)(
1176     const char* dns_server, const char* name,
1177     grpc_pollset_set* interested_parties, grpc_closure* on_done,
1178     std::unique_ptr<grpc_core::EndpointAddressesList>* balancer_addresses,
1179     int query_timeout_ms) = grpc_dns_lookup_srv_ares_impl;
1180 
1181 grpc_ares_request* (*grpc_dns_lookup_txt_ares)(
1182     const char* dns_server, const char* name,
1183     grpc_pollset_set* interested_parties, grpc_closure* on_done,
1184     char** service_config_json,
1185     int query_timeout_ms) = grpc_dns_lookup_txt_ares_impl;
1186 
grpc_cancel_ares_request_impl(grpc_ares_request * r)1187 static void grpc_cancel_ares_request_impl(grpc_ares_request* r) {
1188   GPR_ASSERT(r != nullptr);
1189   grpc_core::MutexLock lock(&r->mu);
1190   GRPC_CARES_TRACE_LOG("request:%p grpc_cancel_ares_request ev_driver:%p", r,
1191                        r->ev_driver);
1192   if (r->ev_driver != nullptr) {
1193     grpc_ares_ev_driver_shutdown_locked(r->ev_driver);
1194   }
1195 }
1196 
1197 void (*grpc_cancel_ares_request)(grpc_ares_request* r) =
1198     grpc_cancel_ares_request_impl;
1199 
1200 // ares_library_init and ares_library_cleanup are currently no-op except under
1201 // Windows. Calling them may cause race conditions when other parts of the
1202 // binary calls these functions concurrently.
1203 #ifdef GPR_WINDOWS
grpc_ares_init(void)1204 grpc_error_handle grpc_ares_init(void) {
1205   int status = ares_library_init(ARES_LIB_INIT_ALL);
1206   if (status != ARES_SUCCESS) {
1207     return GRPC_ERROR_CREATE(
1208         absl::StrCat("ares_library_init failed: ", ares_strerror(status)));
1209   }
1210   return absl::OkStatus();
1211 }
1212 
grpc_ares_cleanup(void)1213 void grpc_ares_cleanup(void) { ares_library_cleanup(); }
1214 #else
grpc_ares_init(void)1215 grpc_error_handle grpc_ares_init(void) { return absl::OkStatus(); }
grpc_ares_cleanup(void)1216 void grpc_ares_cleanup(void) {}
1217 #endif  // GPR_WINDOWS
1218 
1219 #endif  // GRPC_ARES == 1
1220