ad0f14601213e71e09c14f647c8396d62fb1b6d2
[motion2.git] /
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 #if GRPC_ARES == 1
22
23 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
24 #include "src/core/lib/iomgr/sockaddr.h"
25
26 #include <string.h>
27 #include <sys/types.h>
28
29 #include <ares.h>
30 #include <grpc/support/alloc.h>
31 #include <grpc/support/log.h>
32 #include <grpc/support/string_util.h>
33 #include <grpc/support/time.h>
34
35 #include <address_sorting/address_sorting.h>
36 #include "src/core/ext/filters/client_channel/parse_address.h"
37 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
38 #include "src/core/lib/gpr/host_port.h"
39 #include "src/core/lib/gpr/string.h"
40 #include "src/core/lib/iomgr/combiner.h"
41 #include "src/core/lib/iomgr/error.h"
42 #include "src/core/lib/iomgr/executor.h"
43 #include "src/core/lib/iomgr/iomgr_internal.h"
44 #include "src/core/lib/iomgr/nameser.h"
45 #include "src/core/lib/iomgr/sockaddr_utils.h"
46
47 using grpc_core::ServerAddress;
48 using grpc_core::ServerAddressList;
49
50 grpc_core::TraceFlag grpc_trace_cares_address_sorting(false,
51                                                       "cares_address_sorting");
52
53 grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver");
54
55 struct grpc_ares_request {
56   /** indicates the DNS server to use, if specified */
57   struct ares_addr_port_node dns_server_addr;
58   /** following members are set in grpc_resolve_address_ares_impl */
59   /** closure to call when the request completes */
60   grpc_closure* on_done;
61   /** the pointer to receive the resolved addresses */
62   grpc_core::UniquePtr<grpc_core::ServerAddressList>* addresses_out;
63   /** the pointer to receive the service config in JSON */
64   char** service_config_json_out;
65   /** the evernt driver used by this request */
66   grpc_ares_ev_driver* ev_driver;
67   /** number of ongoing queries */
68   size_t pending_queries;
69
70   /** the errors explaining query failures, appended to in query callbacks */
71   grpc_error* error;
72 };
73
74 typedef struct grpc_ares_hostbyname_request {
75   /** following members are set in create_hostbyname_request_locked
76    */
77   /** the top-level request instance */
78   grpc_ares_request* parent_request;
79   /** host to resolve, parsed from the name to resolve */
80   char* host;
81   /** port to fill in sockaddr_in, parsed from the name to resolve */
82   uint16_t port;
83   /** is it a grpclb address */
84   bool is_balancer;
85 } grpc_ares_hostbyname_request;
86
87 static void log_address_sorting_list(const ServerAddressList& addresses,
88                                      const char* input_output_str) {
89   for (size_t i = 0; i < addresses.size(); i++) {
90     char* addr_str;
91     if (grpc_sockaddr_to_string(&addr_str, &addresses[i].address(), true)) {
92       gpr_log(GPR_INFO, "c-ares address sorting: %s[%" PRIuPTR "]=%s",
93               input_output_str, i, addr_str);
94       gpr_free(addr_str);
95     } else {
96       gpr_log(GPR_INFO,
97               "c-ares address sorting: %s[%" PRIuPTR "]=<unprintable>",
98               input_output_str, i);
99     }
100   }
101 }
102
103 void grpc_cares_wrapper_address_sorting_sort(ServerAddressList* addresses) {
104   if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_cares_address_sorting)) {
105     log_address_sorting_list(*addresses, "input");
106   }
107   address_sorting_sortable* sortables = (address_sorting_sortable*)gpr_zalloc(
108       sizeof(address_sorting_sortable) * addresses->size());
109   for (size_t i = 0; i < addresses->size(); ++i) {
110     sortables[i].user_data = &(*addresses)[i];
111     memcpy(&sortables[i].dest_addr.addr, &(*addresses)[i].address().addr,
112            (*addresses)[i].address().len);
113     sortables[i].dest_addr.len = (*addresses)[i].address().len;
114   }
115   address_sorting_rfc_6724_sort(sortables, addresses->size());
116   ServerAddressList sorted;
117   sorted.reserve(addresses->size());
118   for (size_t i = 0; i < addresses->size(); ++i) {
119     sorted.emplace_back(*static_cast<ServerAddress*>(sortables[i].user_data));
120   }
121   gpr_free(sortables);
122   *addresses = std::move(sorted);
123   if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_cares_address_sorting)) {
124     log_address_sorting_list(*addresses, "output");
125   }
126 }
127
128 static void grpc_ares_request_ref_locked(grpc_ares_request* r) {
129   r->pending_queries++;
130 }
131
132 static void grpc_ares_request_unref_locked(grpc_ares_request* r) {
133   r->pending_queries--;
134   if (r->pending_queries == 0u) {
135     grpc_ares_ev_driver_on_queries_complete_locked(r->ev_driver);
136   }
137 }
138
139 void grpc_ares_complete_request_locked(grpc_ares_request* r) {
140   /* Invoke on_done callback and destroy the
141      request */
142   r->ev_driver = nullptr;
143   ServerAddressList* addresses = r->addresses_out->get();
144   if (addresses != nullptr) {
145     grpc_cares_wrapper_address_sorting_sort(addresses);
146     GRPC_ERROR_UNREF(r->error);
147     r->error = GRPC_ERROR_NONE;
148     // TODO(apolcyn): allow c-ares to return a service config
149     // with no addresses along side it
150   }
151   GRPC_CLOSURE_SCHED(r->on_done, r->error);
152 }
153
154 static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
155     grpc_ares_request* parent_request, char* host, uint16_t port,
156     bool is_balancer) {
157   GRPC_CARES_TRACE_LOG(
158       "request:%p create_hostbyname_request_locked host:%s port:%d "
159       "is_balancer:%d",
160       parent_request, host, port, is_balancer);
161   grpc_ares_hostbyname_request* hr = static_cast<grpc_ares_hostbyname_request*>(
162       gpr_zalloc(sizeof(grpc_ares_hostbyname_request)));
163   hr->parent_request = parent_request;
164   hr->host = gpr_strdup(host);
165   hr->port = port;
166   hr->is_balancer = is_balancer;
167   grpc_ares_request_ref_locked(parent_request);
168   return hr;
169 }
170
171 static void destroy_hostbyname_request_locked(
172     grpc_ares_hostbyname_request* hr) {
173   grpc_ares_request_unref_locked(hr->parent_request);
174   gpr_free(hr->host);
175   gpr_free(hr);
176 }
177
178 static void on_hostbyname_done_locked(void* arg, int status, int timeouts,
179                                       struct hostent* hostent) {
180   grpc_ares_hostbyname_request* hr =
181       static_cast<grpc_ares_hostbyname_request*>(arg);
182   grpc_ares_request* r = hr->parent_request;
183   if (status == ARES_SUCCESS) {
184     GRPC_CARES_TRACE_LOG(
185         "request:%p on_hostbyname_done_locked host=%s ARES_SUCCESS", r,
186         hr->host);
187     if (*r->addresses_out == nullptr) {
188       *r->addresses_out = grpc_core::MakeUnique<ServerAddressList>();
189     }
190     ServerAddressList& addresses = **r->addresses_out;
191     for (size_t i = 0; hostent->h_addr_list[i] != nullptr; ++i) {
192       grpc_core::InlinedVector<grpc_arg, 2> args_to_add;
193       if (hr->is_balancer) {
194         args_to_add.emplace_back(grpc_channel_arg_integer_create(
195             const_cast<char*>(GRPC_ARG_ADDRESS_IS_BALANCER), 1));
196         args_to_add.emplace_back(grpc_channel_arg_string_create(
197             const_cast<char*>(GRPC_ARG_ADDRESS_BALANCER_NAME), hr->host));
198       }
199       grpc_channel_args* args = grpc_channel_args_copy_and_add(
200           nullptr, args_to_add.data(), args_to_add.size());
201       switch (hostent->h_addrtype) {
202         case AF_INET6: {
203           size_t addr_len = sizeof(struct sockaddr_in6);
204           struct sockaddr_in6 addr;
205           memset(&addr, 0, addr_len);
206           memcpy(&addr.sin6_addr, hostent->h_addr_list[i],
207                  sizeof(struct in6_addr));
208           addr.sin6_family = static_cast<unsigned char>(hostent->h_addrtype);
209           addr.sin6_port = hr->port;
210           addresses.emplace_back(&addr, addr_len, args);
211           char output[INET6_ADDRSTRLEN];
212           ares_inet_ntop(AF_INET6, &addr.sin6_addr, output, INET6_ADDRSTRLEN);
213           GRPC_CARES_TRACE_LOG(
214               "request:%p c-ares resolver gets a AF_INET6 result: \n"
215               "  addr: %s\n  port: %d\n  sin6_scope_id: %d\n",
216               r, output, ntohs(hr->port), addr.sin6_scope_id);
217           break;
218         }
219         case AF_INET: {
220           size_t addr_len = sizeof(struct sockaddr_in);
221           struct sockaddr_in addr;
222           memset(&addr, 0, addr_len);
223           memcpy(&addr.sin_addr, hostent->h_addr_list[i],
224                  sizeof(struct in_addr));
225           addr.sin_family = static_cast<unsigned char>(hostent->h_addrtype);
226           addr.sin_port = hr->port;
227           addresses.emplace_back(&addr, addr_len, args);
228           char output[INET_ADDRSTRLEN];
229           ares_inet_ntop(AF_INET, &addr.sin_addr, output, INET_ADDRSTRLEN);
230           GRPC_CARES_TRACE_LOG(
231               "request:%p c-ares resolver gets a AF_INET result: \n"
232               "  addr: %s\n  port: %d\n",
233               r, output, ntohs(hr->port));
234           break;
235         }
236       }
237     }
238   } else {
239     char* error_msg;
240     gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
241                  ares_strerror(status));
242     GRPC_CARES_TRACE_LOG("request:%p on_hostbyname_done_locked host=%s %s", r,
243                          hr->host, error_msg);
244     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
245     gpr_free(error_msg);
246     r->error = grpc_error_add_child(error, r->error);
247   }
248   destroy_hostbyname_request_locked(hr);
249 }
250
251 static void on_srv_query_done_locked(void* arg, int status, int timeouts,
252                                      unsigned char* abuf, int alen) {
253   grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
254   if (status == ARES_SUCCESS) {
255     GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked ARES_SUCCESS", r);
256     struct ares_srv_reply* reply;
257     const int parse_status = ares_parse_srv_reply(abuf, alen, &reply);
258     GRPC_CARES_TRACE_LOG("request:%p ares_parse_srv_reply: %d", r,
259                          parse_status);
260     if (parse_status == ARES_SUCCESS) {
261       ares_channel* channel =
262           grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
263       for (struct ares_srv_reply* srv_it = reply; srv_it != nullptr;
264            srv_it = srv_it->next) {
265         if (grpc_ares_query_ipv6()) {
266           grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
267               r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
268           ares_gethostbyname(*channel, hr->host, AF_INET6,
269                              on_hostbyname_done_locked, hr);
270         }
271         grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
272             r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
273         ares_gethostbyname(*channel, hr->host, AF_INET,
274                            on_hostbyname_done_locked, hr);
275         grpc_ares_ev_driver_start_locked(r->ev_driver);
276       }
277     }
278     if (reply != nullptr) {
279       ares_free_data(reply);
280     }
281   } else {
282     char* error_msg;
283     gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
284                  ares_strerror(status));
285     GRPC_CARES_TRACE_LOG("request:%p on_srv_query_done_locked %s", r,
286                          error_msg);
287     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
288     gpr_free(error_msg);
289     r->error = grpc_error_add_child(error, r->error);
290   }
291   grpc_ares_request_unref_locked(r);
292 }
293
294 static const char g_service_config_attribute_prefix[] = "grpc_config=";
295
296 static void on_txt_done_locked(void* arg, int status, int timeouts,
297                                unsigned char* buf, int len) {
298   char* error_msg;
299   grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
300   const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1;
301   struct ares_txt_ext* result = nullptr;
302   struct ares_txt_ext* reply = nullptr;
303   grpc_error* error = GRPC_ERROR_NONE;
304   if (status != ARES_SUCCESS) goto fail;
305   GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked ARES_SUCCESS", r);
306   status = ares_parse_txt_reply_ext(buf, len, &reply);
307   if (status != ARES_SUCCESS) goto fail;
308   // Find service config in TXT record.
309   for (result = reply; result != nullptr; result = result->next) {
310     if (result->record_start &&
311         memcmp(result->txt, g_service_config_attribute_prefix, prefix_len) ==
312             0) {
313       break;
314     }
315   }
316   // Found a service config record.
317   if (result != nullptr) {
318     size_t service_config_len = result->length - prefix_len;
319     *r->service_config_json_out =
320         static_cast<char*>(gpr_malloc(service_config_len + 1));
321     memcpy(*r->service_config_json_out, result->txt + prefix_len,
322            service_config_len);
323     for (result = result->next; result != nullptr && !result->record_start;
324          result = result->next) {
325       *r->service_config_json_out = static_cast<char*>(
326           gpr_realloc(*r->service_config_json_out,
327                       service_config_len + result->length + 1));
328       memcpy(*r->service_config_json_out + service_config_len, result->txt,
329              result->length);
330       service_config_len += result->length;
331     }
332     (*r->service_config_json_out)[service_config_len] = '\0';
333     GRPC_CARES_TRACE_LOG("request:%p found service config: %s", r,
334                          *r->service_config_json_out);
335   }
336   // Clean up.
337   ares_free_data(reply);
338   goto done;
339 fail:
340   gpr_asprintf(&error_msg, "C-ares TXT lookup status is not ARES_SUCCESS: %s",
341                ares_strerror(status));
342   error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
343   GRPC_CARES_TRACE_LOG("request:%p on_txt_done_locked %s", r, error_msg);
344   gpr_free(error_msg);
345   r->error = grpc_error_add_child(error, r->error);
346 done:
347   grpc_ares_request_unref_locked(r);
348 }
349
350 void grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
351     grpc_ares_request* r, const char* dns_server, const char* name,
352     const char* default_port, grpc_pollset_set* interested_parties,
353     bool check_grpclb, int query_timeout_ms, grpc_combiner* combiner) {
354   grpc_error* error = GRPC_ERROR_NONE;
355   grpc_ares_hostbyname_request* hr = nullptr;
356   ares_channel* channel = nullptr;
357   /* parse name, splitting it into host and port parts */
358   char* host;
359   char* port;
360   gpr_split_host_port(name, &host, &port);
361   if (host == nullptr) {
362     error = grpc_error_set_str(
363         GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
364         GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
365     goto error_cleanup;
366   } else if (port == nullptr) {
367     if (default_port == nullptr) {
368       error = grpc_error_set_str(
369           GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
370           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
371       goto error_cleanup;
372     }
373     port = gpr_strdup(default_port);
374   }
375   error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties,
376                                             query_timeout_ms, combiner, r);
377   if (error != GRPC_ERROR_NONE) goto error_cleanup;
378   channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
379   // If dns_server is specified, use it.
380   if (dns_server != nullptr) {
381     GRPC_CARES_TRACE_LOG("request:%p Using DNS server %s", r, dns_server);
382     grpc_resolved_address addr;
383     if (grpc_parse_ipv4_hostport(dns_server, &addr, false /* log_errors */)) {
384       r->dns_server_addr.family = AF_INET;
385       struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(addr.addr);
386       memcpy(&r->dns_server_addr.addr.addr4, &in->sin_addr,
387              sizeof(struct in_addr));
388       r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
389       r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
390     } else if (grpc_parse_ipv6_hostport(dns_server, &addr,
391                                         false /* log_errors */)) {
392       r->dns_server_addr.family = AF_INET6;
393       struct sockaddr_in6* in6 =
394           reinterpret_cast<struct sockaddr_in6*>(addr.addr);
395       memcpy(&r->dns_server_addr.addr.addr6, &in6->sin6_addr,
396              sizeof(struct in6_addr));
397       r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
398       r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
399     } else {
400       error = grpc_error_set_str(
401           GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
402           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
403       goto error_cleanup;
404     }
405     int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
406     if (status != ARES_SUCCESS) {
407       char* error_msg;
408       gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
409                    ares_strerror(status));
410       error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
411       gpr_free(error_msg);
412       goto error_cleanup;
413     }
414   }
415   r->pending_queries = 1;
416   if (grpc_ares_query_ipv6()) {
417     hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port),
418                                           false /* is_balancer */);
419     ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked,
420                        hr);
421   }
422   hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port),
423                                         false /* is_balancer */);
424   ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked,
425                      hr);
426   if (check_grpclb) {
427     /* Query the SRV record */
428     grpc_ares_request_ref_locked(r);
429     char* service_name;
430     gpr_asprintf(&service_name, "_grpclb._tcp.%s", host);
431     ares_query(*channel, service_name, ns_c_in, ns_t_srv,
432                on_srv_query_done_locked, r);
433     gpr_free(service_name);
434   }
435   if (r->service_config_json_out != nullptr) {
436     grpc_ares_request_ref_locked(r);
437     char* config_name;
438     gpr_asprintf(&config_name, "_grpc_config.%s", host);
439     ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_locked,
440                 r);
441     gpr_free(config_name);
442   }
443   grpc_ares_ev_driver_start_locked(r->ev_driver);
444   grpc_ares_request_unref_locked(r);
445   gpr_free(host);
446   gpr_free(port);
447   return;
448
449 error_cleanup:
450   GRPC_CLOSURE_SCHED(r->on_done, error);
451   gpr_free(host);
452   gpr_free(port);
453 }
454
455 static bool inner_resolve_as_ip_literal_locked(
456     const char* name, const char* default_port,
457     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs, char** host,
458     char** port, char** hostport) {
459   gpr_split_host_port(name, host, port);
460   if (*host == nullptr) {
461     gpr_log(GPR_ERROR,
462             "Failed to parse %s to host:port while attempting to resolve as ip "
463             "literal.",
464             name);
465     return false;
466   }
467   if (*port == nullptr) {
468     if (default_port == nullptr) {
469       gpr_log(GPR_ERROR,
470               "No port or default port for %s while attempting to resolve as "
471               "ip literal.",
472               name);
473       return false;
474     }
475     *port = gpr_strdup(default_port);
476   }
477   grpc_resolved_address addr;
478   GPR_ASSERT(gpr_join_host_port(hostport, *host, atoi(*port)));
479   if (grpc_parse_ipv4_hostport(*hostport, &addr, false /* log errors */) ||
480       grpc_parse_ipv6_hostport(*hostport, &addr, false /* log errors */)) {
481     GPR_ASSERT(*addrs == nullptr);
482     *addrs = grpc_core::MakeUnique<ServerAddressList>();
483     (*addrs)->emplace_back(addr.addr, addr.len, nullptr /* args */);
484     return true;
485   }
486   return false;
487 }
488
489 static bool resolve_as_ip_literal_locked(
490     const char* name, const char* default_port,
491     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
492   char* host = nullptr;
493   char* port = nullptr;
494   char* hostport = nullptr;
495   bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs,
496                                                 &host, &port, &hostport);
497   gpr_free(host);
498   gpr_free(port);
499   gpr_free(hostport);
500   return out;
501 }
502
503 static bool target_matches_localhost_inner(const char* name, char** host,
504                                            char** port) {
505   if (!gpr_split_host_port(name, host, port)) {
506     gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name);
507     return false;
508   }
509   if (gpr_stricmp(*host, "localhost") == 0) {
510     return true;
511   } else {
512     return false;
513   }
514 }
515
516 static bool target_matches_localhost(const char* name) {
517   char* host = nullptr;
518   char* port = nullptr;
519   bool out = target_matches_localhost_inner(name, &host, &port);
520   gpr_free(host);
521   gpr_free(port);
522   return out;
523 }
524
525 #ifdef GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
526 static bool inner_maybe_resolve_localhost_manually_locked(
527     const char* name, const char* default_port,
528     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs, char** host,
529     char** port) {
530   gpr_split_host_port(name, host, port);
531   if (*host == nullptr) {
532     gpr_log(GPR_ERROR,
533             "Failed to parse %s into host:port during manual localhost "
534             "resolution check.",
535             name);
536     return false;
537   }
538   if (*port == nullptr) {
539     if (default_port == nullptr) {
540       gpr_log(GPR_ERROR,
541               "No port or default port for %s during manual localhost "
542               "resolution check.",
543               name);
544       return false;
545     }
546     *port = gpr_strdup(default_port);
547   }
548   if (gpr_stricmp(*host, "localhost") == 0) {
549     GPR_ASSERT(*addrs == nullptr);
550     *addrs = grpc_core::MakeUnique<grpc_core::ServerAddressList>();
551     uint16_t numeric_port = grpc_strhtons(*port);
552     // Append the ipv6 loopback address.
553     struct sockaddr_in6 ipv6_loopback_addr;
554     memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr));
555     ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1;
556     ipv6_loopback_addr.sin6_family = AF_INET6;
557     ipv6_loopback_addr.sin6_port = numeric_port;
558     (*addrs)->emplace_back(&ipv6_loopback_addr, sizeof(ipv6_loopback_addr),
559                            nullptr /* args */);
560     // Append the ipv4 loopback address.
561     struct sockaddr_in ipv4_loopback_addr;
562     memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr));
563     ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f;
564     ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01;
565     ipv4_loopback_addr.sin_family = AF_INET;
566     ipv4_loopback_addr.sin_port = numeric_port;
567     (*addrs)->emplace_back(&ipv4_loopback_addr, sizeof(ipv4_loopback_addr),
568                            nullptr /* args */);
569     // Let the address sorter figure out which one should be tried first.
570     grpc_cares_wrapper_address_sorting_sort(addrs->get());
571     return true;
572   }
573   return false;
574 }
575
576 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
577     const char* name, const char* default_port,
578     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
579   char* host = nullptr;
580   char* port = nullptr;
581   bool out = inner_maybe_resolve_localhost_manually_locked(name, default_port,
582                                                            addrs, &host, &port);
583   gpr_free(host);
584   gpr_free(port);
585   return out;
586 }
587 #else  /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
588 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
589     const char* name, const char* default_port,
590     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
591   return false;
592 }
593 #endif /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
594
595 static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
596     const char* dns_server, const char* name, const char* default_port,
597     grpc_pollset_set* interested_parties, grpc_closure* on_done,
598     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
599     bool check_grpclb, char** service_config_json, int query_timeout_ms,
600     grpc_combiner* combiner) {
601   grpc_ares_request* r =
602       static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
603   r->ev_driver = nullptr;
604   r->on_done = on_done;
605   r->addresses_out = addrs;
606   r->service_config_json_out = service_config_json;
607   r->error = GRPC_ERROR_NONE;
608   r->pending_queries = 0;
609   GRPC_CARES_TRACE_LOG(
610       "request:%p c-ares grpc_dns_lookup_ares_locked_impl name=%s, "
611       "default_port=%s",
612       r, name, default_port);
613   // Early out if the target is an ipv4 or ipv6 literal.
614   if (resolve_as_ip_literal_locked(name, default_port, addrs)) {
615     grpc_ares_complete_request_locked(r);
616     return r;
617   }
618   // Early out if the target is localhost and we're on Windows.
619   if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port,
620                                                         addrs)) {
621     grpc_ares_complete_request_locked(r);
622     return r;
623   }
624   // Don't query for SRV and TXT records if the target is "localhost", so
625   // as to cut down on lookups over the network, especially in tests:
626   // https://github.com/grpc/proposal/pull/79
627   if (target_matches_localhost(name)) {
628     check_grpclb = false;
629     r->service_config_json_out = nullptr;
630   }
631   // Look up name using c-ares lib.
632   grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
633       r, dns_server, name, default_port, interested_parties, check_grpclb,
634       query_timeout_ms, combiner);
635   return r;
636 }
637
638 grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
639     const char* dns_server, const char* name, const char* default_port,
640     grpc_pollset_set* interested_parties, grpc_closure* on_done,
641     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
642     bool check_grpclb, char** service_config_json, int query_timeout_ms,
643     grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
644
645 static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {
646   GPR_ASSERT(r != nullptr);
647   if (r->ev_driver != nullptr) {
648     grpc_ares_ev_driver_shutdown_locked(r->ev_driver);
649   }
650 }
651
652 void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) =
653     grpc_cancel_ares_request_locked_impl;
654
655 // ares_library_init and ares_library_cleanup are currently no-op except under
656 // Windows. Calling them may cause race conditions when other parts of the
657 // binary calls these functions concurrently.
658 #ifdef GPR_WINDOWS
659 grpc_error* grpc_ares_init(void) {
660   int status = ares_library_init(ARES_LIB_INIT_ALL);
661   if (status != ARES_SUCCESS) {
662     char* error_msg;
663     gpr_asprintf(&error_msg, "ares_library_init failed: %s",
664                  ares_strerror(status));
665     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
666     gpr_free(error_msg);
667     return error;
668   }
669   return GRPC_ERROR_NONE;
670 }
671
672 void grpc_ares_cleanup(void) { ares_library_cleanup(); }
673 #else
674 grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; }
675 void grpc_ares_cleanup(void) {}
676 #endif  // GPR_WINDOWS
677
678 /*
679  * grpc_resolve_address_ares related structs and functions
680  */
681
682 typedef struct grpc_resolve_address_ares_request {
683   /* combiner that queries and related callbacks run under */
684   grpc_combiner* combiner;
685   /** the pointer to receive the resolved addresses */
686   grpc_resolved_addresses** addrs_out;
687   /** currently resolving addresses */
688   grpc_core::UniquePtr<ServerAddressList> addresses;
689   /** closure to call when the resolve_address_ares request completes */
690   grpc_closure* on_resolve_address_done;
691   /** a closure wrapping on_resolve_address_done, which should be invoked when
692      the grpc_dns_lookup_ares_locked operation is done. */
693   grpc_closure on_dns_lookup_done_locked;
694   /* target name */
695   const char* name;
696   /* default port to use if none is specified */
697   const char* default_port;
698   /* pollset_set to be driven by */
699   grpc_pollset_set* interested_parties;
700   /* underlying ares_request that the query is performed on */
701   grpc_ares_request* ares_request = nullptr;
702 } grpc_resolve_address_ares_request;
703
704 static void on_dns_lookup_done_locked(void* arg, grpc_error* error) {
705   grpc_resolve_address_ares_request* r =
706       static_cast<grpc_resolve_address_ares_request*>(arg);
707   gpr_free(r->ares_request);
708   grpc_resolved_addresses** resolved_addresses = r->addrs_out;
709   if (r->addresses == nullptr || r->addresses->empty()) {
710     *resolved_addresses = nullptr;
711   } else {
712     *resolved_addresses = static_cast<grpc_resolved_addresses*>(
713         gpr_zalloc(sizeof(grpc_resolved_addresses)));
714     (*resolved_addresses)->naddrs = r->addresses->size();
715     (*resolved_addresses)->addrs =
716         static_cast<grpc_resolved_address*>(gpr_zalloc(
717             sizeof(grpc_resolved_address) * (*resolved_addresses)->naddrs));
718     for (size_t i = 0; i < (*resolved_addresses)->naddrs; ++i) {
719       GPR_ASSERT(!(*r->addresses)[i].IsBalancer());
720       memcpy(&(*resolved_addresses)->addrs[i], &(*r->addresses)[i].address(),
721              sizeof(grpc_resolved_address));
722     }
723   }
724   GRPC_CLOSURE_SCHED(r->on_resolve_address_done, GRPC_ERROR_REF(error));
725   GRPC_COMBINER_UNREF(r->combiner, "on_dns_lookup_done_cb");
726   grpc_core::Delete(r);
727 }
728
729 static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
730     void* arg, grpc_error* unused_error) {
731   grpc_resolve_address_ares_request* r =
732       static_cast<grpc_resolve_address_ares_request*>(arg);
733   r->ares_request = grpc_dns_lookup_ares_locked(
734       nullptr /* dns_server */, r->name, r->default_port, r->interested_parties,
735       &r->on_dns_lookup_done_locked, &r->addresses, false /* check_grpclb */,
736       nullptr /* service_config_json */, GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS,
737       r->combiner);
738 }
739
740 static void grpc_resolve_address_ares_impl(const char* name,
741                                            const char* default_port,
742                                            grpc_pollset_set* interested_parties,
743                                            grpc_closure* on_done,
744                                            grpc_resolved_addresses** addrs) {
745   grpc_resolve_address_ares_request* r =
746       grpc_core::New<grpc_resolve_address_ares_request>();
747   r->combiner = grpc_combiner_create();
748   r->addrs_out = addrs;
749   r->on_resolve_address_done = on_done;
750   GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked, on_dns_lookup_done_locked, r,
751                     grpc_combiner_scheduler(r->combiner));
752   r->name = name;
753   r->default_port = default_port;
754   r->interested_parties = interested_parties;
755   GRPC_CLOSURE_SCHED(
756       GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r,
757                           grpc_combiner_scheduler(r->combiner)),
758       GRPC_ERROR_NONE);
759 }
760
761 void (*grpc_resolve_address_ares)(
762     const char* name, const char* default_port,
763     grpc_pollset_set* interested_parties, grpc_closure* on_done,
764     grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl;
765
766 #endif /* GRPC_ARES == 1 */