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