Built motion from commit 6a09e18b.|2.6.11
[motion2.git] / legacy-libs / grpc / deps / grpc / src / core / ext / filters / client_channel / resolver / dns / c_ares / grpc_ares_wrapper.cc
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/string.h"
39 #include "src/core/lib/gprpp/host_port.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   grpc_core::UniquePtr<char> host;
359   grpc_core::UniquePtr<char> port;
360   grpc_core::SplitHostPort(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.reset(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.get(),
418                                           grpc_strhtons(port.get()),
419                                           /*is_balancer=*/false);
420     ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked,
421                        hr);
422   }
423   hr =
424       create_hostbyname_request_locked(r, host.get(), grpc_strhtons(port.get()),
425                                        /*is_balancer=*/false);
426   ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked,
427                      hr);
428   if (check_grpclb) {
429     /* Query the SRV record */
430     grpc_ares_request_ref_locked(r);
431     char* service_name;
432     gpr_asprintf(&service_name, "_grpclb._tcp.%s", host.get());
433     ares_query(*channel, service_name, ns_c_in, ns_t_srv,
434                on_srv_query_done_locked, r);
435     gpr_free(service_name);
436   }
437   if (r->service_config_json_out != nullptr) {
438     grpc_ares_request_ref_locked(r);
439     char* config_name;
440     gpr_asprintf(&config_name, "_grpc_config.%s", host.get());
441     ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_locked,
442                 r);
443     gpr_free(config_name);
444   }
445   grpc_ares_ev_driver_start_locked(r->ev_driver);
446   grpc_ares_request_unref_locked(r);
447   return;
448
449 error_cleanup:
450   GRPC_CLOSURE_SCHED(r->on_done, error);
451 }
452
453 static bool inner_resolve_as_ip_literal_locked(
454     const char* name, const char* default_port,
455     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
456     grpc_core::UniquePtr<char>* host, grpc_core::UniquePtr<char>* port,
457     grpc_core::UniquePtr<char>* hostport) {
458   grpc_core::SplitHostPort(name, host, port);
459   if (*host == nullptr) {
460     gpr_log(GPR_ERROR,
461             "Failed to parse %s to host:port while attempting to resolve as ip "
462             "literal.",
463             name);
464     return false;
465   }
466   if (*port == nullptr) {
467     if (default_port == nullptr) {
468       gpr_log(GPR_ERROR,
469               "No port or default port for %s while attempting to resolve as "
470               "ip literal.",
471               name);
472       return false;
473     }
474     port->reset(gpr_strdup(default_port));
475   }
476   grpc_resolved_address addr;
477   GPR_ASSERT(grpc_core::JoinHostPort(hostport, host->get(), atoi(port->get())));
478   if (grpc_parse_ipv4_hostport(hostport->get(), &addr,
479                                false /* log errors */) ||
480       grpc_parse_ipv6_hostport(hostport->get(), &addr,
481                                false /* log errors */)) {
482     GPR_ASSERT(*addrs == nullptr);
483     *addrs = grpc_core::MakeUnique<ServerAddressList>();
484     (*addrs)->emplace_back(addr.addr, addr.len, nullptr /* args */);
485     return true;
486   }
487   return false;
488 }
489
490 static bool resolve_as_ip_literal_locked(
491     const char* name, const char* default_port,
492     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
493   grpc_core::UniquePtr<char> host;
494   grpc_core::UniquePtr<char> port;
495   grpc_core::UniquePtr<char> hostport;
496   bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs,
497                                                 &host, &port, &hostport);
498   return out;
499 }
500
501 static bool target_matches_localhost_inner(const char* name,
502                                            grpc_core::UniquePtr<char>* host,
503                                            grpc_core::UniquePtr<char>* port) {
504   if (!grpc_core::SplitHostPort(name, host, port)) {
505     gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name);
506     return false;
507   }
508   if (gpr_stricmp(host->get(), "localhost") == 0) {
509     return true;
510   } else {
511     return false;
512   }
513 }
514
515 static bool target_matches_localhost(const char* name) {
516   grpc_core::UniquePtr<char> host;
517   grpc_core::UniquePtr<char> port;
518   return target_matches_localhost_inner(name, &host, &port);
519 }
520
521 #ifdef GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
522 static bool inner_maybe_resolve_localhost_manually_locked(
523     const char* name, const char* default_port,
524     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
525     grpc_core::UniquePtr<char>* host, grpc_core::UniquePtr<char>* port) {
526   grpc_core::SplitHostPort(name, host, port);
527   if (*host == nullptr) {
528     gpr_log(GPR_ERROR,
529             "Failed to parse %s into host:port during manual localhost "
530             "resolution check.",
531             name);
532     return false;
533   }
534   if (*port == nullptr) {
535     if (default_port == nullptr) {
536       gpr_log(GPR_ERROR,
537               "No port or default port for %s during manual localhost "
538               "resolution check.",
539               name);
540       return false;
541     }
542     port->reset(gpr_strdup(default_port));
543   }
544   if (gpr_stricmp(host->get(), "localhost") == 0) {
545     GPR_ASSERT(*addrs == nullptr);
546     *addrs = grpc_core::MakeUnique<grpc_core::ServerAddressList>();
547     uint16_t numeric_port = grpc_strhtons(port->get());
548     // Append the ipv6 loopback address.
549     struct sockaddr_in6 ipv6_loopback_addr;
550     memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr));
551     ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1;
552     ipv6_loopback_addr.sin6_family = AF_INET6;
553     ipv6_loopback_addr.sin6_port = numeric_port;
554     (*addrs)->emplace_back(&ipv6_loopback_addr, sizeof(ipv6_loopback_addr),
555                            nullptr /* args */);
556     // Append the ipv4 loopback address.
557     struct sockaddr_in ipv4_loopback_addr;
558     memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr));
559     ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f;
560     ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01;
561     ipv4_loopback_addr.sin_family = AF_INET;
562     ipv4_loopback_addr.sin_port = numeric_port;
563     (*addrs)->emplace_back(&ipv4_loopback_addr, sizeof(ipv4_loopback_addr),
564                            nullptr /* args */);
565     // Let the address sorter figure out which one should be tried first.
566     grpc_cares_wrapper_address_sorting_sort(addrs->get());
567     return true;
568   }
569   return false;
570 }
571
572 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
573     const char* name, const char* default_port,
574     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
575   grpc_core::UniquePtr<char> host;
576   grpc_core::UniquePtr<char> port;
577   return inner_maybe_resolve_localhost_manually_locked(name, default_port,
578                                                        addrs, &host, &port);
579 }
580 #else  /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
581 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
582     const char* name, const char* default_port,
583     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
584   return false;
585 }
586 #endif /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
587
588 static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
589     const char* dns_server, const char* name, const char* default_port,
590     grpc_pollset_set* interested_parties, grpc_closure* on_done,
591     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
592     bool check_grpclb, char** service_config_json, int query_timeout_ms,
593     grpc_combiner* combiner) {
594   grpc_ares_request* r =
595       static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
596   r->ev_driver = nullptr;
597   r->on_done = on_done;
598   r->addresses_out = addrs;
599   r->service_config_json_out = service_config_json;
600   r->error = GRPC_ERROR_NONE;
601   r->pending_queries = 0;
602   GRPC_CARES_TRACE_LOG(
603       "request:%p c-ares grpc_dns_lookup_ares_locked_impl name=%s, "
604       "default_port=%s",
605       r, name, default_port);
606   // Early out if the target is an ipv4 or ipv6 literal.
607   if (resolve_as_ip_literal_locked(name, default_port, addrs)) {
608     grpc_ares_complete_request_locked(r);
609     return r;
610   }
611   // Early out if the target is localhost and we're on Windows.
612   if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port,
613                                                         addrs)) {
614     grpc_ares_complete_request_locked(r);
615     return r;
616   }
617   // Don't query for SRV and TXT records if the target is "localhost", so
618   // as to cut down on lookups over the network, especially in tests:
619   // https://github.com/grpc/proposal/pull/79
620   if (target_matches_localhost(name)) {
621     check_grpclb = false;
622     r->service_config_json_out = nullptr;
623   }
624   // Look up name using c-ares lib.
625   grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
626       r, dns_server, name, default_port, interested_parties, check_grpclb,
627       query_timeout_ms, combiner);
628   return r;
629 }
630
631 grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
632     const char* dns_server, const char* name, const char* default_port,
633     grpc_pollset_set* interested_parties, grpc_closure* on_done,
634     grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
635     bool check_grpclb, char** service_config_json, int query_timeout_ms,
636     grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
637
638 static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {
639   GPR_ASSERT(r != nullptr);
640   if (r->ev_driver != nullptr) {
641     grpc_ares_ev_driver_shutdown_locked(r->ev_driver);
642   }
643 }
644
645 void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) =
646     grpc_cancel_ares_request_locked_impl;
647
648 // ares_library_init and ares_library_cleanup are currently no-op except under
649 // Windows. Calling them may cause race conditions when other parts of the
650 // binary calls these functions concurrently.
651 #ifdef GPR_WINDOWS
652 grpc_error* grpc_ares_init(void) {
653   int status = ares_library_init(ARES_LIB_INIT_ALL);
654   if (status != ARES_SUCCESS) {
655     char* error_msg;
656     gpr_asprintf(&error_msg, "ares_library_init failed: %s",
657                  ares_strerror(status));
658     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
659     gpr_free(error_msg);
660     return error;
661   }
662   return GRPC_ERROR_NONE;
663 }
664
665 void grpc_ares_cleanup(void) { ares_library_cleanup(); }
666 #else
667 grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; }
668 void grpc_ares_cleanup(void) {}
669 #endif  // GPR_WINDOWS
670
671 /*
672  * grpc_resolve_address_ares related structs and functions
673  */
674
675 typedef struct grpc_resolve_address_ares_request {
676   /* combiner that queries and related callbacks run under */
677   grpc_combiner* combiner;
678   /** the pointer to receive the resolved addresses */
679   grpc_resolved_addresses** addrs_out;
680   /** currently resolving addresses */
681   grpc_core::UniquePtr<ServerAddressList> addresses;
682   /** closure to call when the resolve_address_ares request completes */
683   grpc_closure* on_resolve_address_done;
684   /** a closure wrapping on_resolve_address_done, which should be invoked when
685      the grpc_dns_lookup_ares_locked operation is done. */
686   grpc_closure on_dns_lookup_done_locked;
687   /* target name */
688   const char* name;
689   /* default port to use if none is specified */
690   const char* default_port;
691   /* pollset_set to be driven by */
692   grpc_pollset_set* interested_parties;
693   /* underlying ares_request that the query is performed on */
694   grpc_ares_request* ares_request = nullptr;
695 } grpc_resolve_address_ares_request;
696
697 static void on_dns_lookup_done_locked(void* arg, grpc_error* error) {
698   grpc_resolve_address_ares_request* r =
699       static_cast<grpc_resolve_address_ares_request*>(arg);
700   gpr_free(r->ares_request);
701   grpc_resolved_addresses** resolved_addresses = r->addrs_out;
702   if (r->addresses == nullptr || r->addresses->empty()) {
703     *resolved_addresses = nullptr;
704   } else {
705     *resolved_addresses = static_cast<grpc_resolved_addresses*>(
706         gpr_zalloc(sizeof(grpc_resolved_addresses)));
707     (*resolved_addresses)->naddrs = r->addresses->size();
708     (*resolved_addresses)->addrs =
709         static_cast<grpc_resolved_address*>(gpr_zalloc(
710             sizeof(grpc_resolved_address) * (*resolved_addresses)->naddrs));
711     for (size_t i = 0; i < (*resolved_addresses)->naddrs; ++i) {
712       GPR_ASSERT(!(*r->addresses)[i].IsBalancer());
713       memcpy(&(*resolved_addresses)->addrs[i], &(*r->addresses)[i].address(),
714              sizeof(grpc_resolved_address));
715     }
716   }
717   GRPC_CLOSURE_SCHED(r->on_resolve_address_done, GRPC_ERROR_REF(error));
718   GRPC_COMBINER_UNREF(r->combiner, "on_dns_lookup_done_cb");
719   grpc_core::Delete(r);
720 }
721
722 static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
723     void* arg, grpc_error* unused_error) {
724   grpc_resolve_address_ares_request* r =
725       static_cast<grpc_resolve_address_ares_request*>(arg);
726   r->ares_request = grpc_dns_lookup_ares_locked(
727       nullptr /* dns_server */, r->name, r->default_port, r->interested_parties,
728       &r->on_dns_lookup_done_locked, &r->addresses, false /* check_grpclb */,
729       nullptr /* service_config_json */, GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS,
730       r->combiner);
731 }
732
733 static void grpc_resolve_address_ares_impl(const char* name,
734                                            const char* default_port,
735                                            grpc_pollset_set* interested_parties,
736                                            grpc_closure* on_done,
737                                            grpc_resolved_addresses** addrs) {
738   grpc_resolve_address_ares_request* r =
739       grpc_core::New<grpc_resolve_address_ares_request>();
740   r->combiner = grpc_combiner_create();
741   r->addrs_out = addrs;
742   r->on_resolve_address_done = on_done;
743   GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked, on_dns_lookup_done_locked, r,
744                     grpc_combiner_scheduler(r->combiner));
745   r->name = name;
746   r->default_port = default_port;
747   r->interested_parties = interested_parties;
748   GRPC_CLOSURE_SCHED(
749       GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r,
750                           grpc_combiner_scheduler(r->combiner)),
751       GRPC_ERROR_NONE);
752 }
753
754 void (*grpc_resolve_address_ares)(
755     const char* name, const char* default_port,
756     grpc_pollset_set* interested_parties, grpc_closure* on_done,
757     grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl;
758
759 #endif /* GRPC_ARES == 1 */