• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 && !defined(GRPC_UV)
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/error.h"
41 #include "src/core/lib/iomgr/executor.h"
42 #include "src/core/lib/iomgr/iomgr_internal.h"
43 #include "src/core/lib/iomgr/nameser.h"
44 #include "src/core/lib/iomgr/sockaddr_utils.h"
45 
46 static gpr_once g_basic_init = GPR_ONCE_INIT;
47 static gpr_mu g_init_mu;
48 
49 grpc_core::TraceFlag grpc_trace_cares_address_sorting(false,
50                                                       "cares_address_sorting");
51 
52 grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver");
53 
54 struct grpc_ares_request {
55   /** indicates the DNS server to use, if specified */
56   struct ares_addr_port_node dns_server_addr;
57   /** following members are set in grpc_resolve_address_ares_impl */
58   /** closure to call when the request completes */
59   grpc_closure* on_done;
60   /** the pointer to receive the resolved addresses */
61   grpc_lb_addresses** lb_addrs_out;
62   /** the pointer to receive the service config in JSON */
63   char** service_config_json_out;
64   /** the evernt driver used by this request */
65   grpc_ares_ev_driver* ev_driver;
66   /** number of ongoing queries */
67   size_t pending_queries;
68 
69   /** is there at least one successful query, set in on_done_cb */
70   bool success;
71   /** the errors explaining the request failure, set in on_done_cb */
72   grpc_error* error;
73 };
74 
75 typedef struct grpc_ares_hostbyname_request {
76   /** following members are set in create_hostbyname_request_locked
77    */
78   /** the top-level request instance */
79   grpc_ares_request* parent_request;
80   /** host to resolve, parsed from the name to resolve */
81   char* host;
82   /** port to fill in sockaddr_in, parsed from the name to resolve */
83   uint16_t port;
84   /** is it a grpclb address */
85   bool is_balancer;
86 } grpc_ares_hostbyname_request;
87 
do_basic_init(void)88 static void do_basic_init(void) { gpr_mu_init(&g_init_mu); }
89 
log_address_sorting_list(grpc_lb_addresses * lb_addrs,const char * input_output_str)90 static void log_address_sorting_list(grpc_lb_addresses* lb_addrs,
91                                      const char* input_output_str) {
92   for (size_t i = 0; i < lb_addrs->num_addresses; i++) {
93     char* addr_str;
94     if (grpc_sockaddr_to_string(&addr_str, &lb_addrs->addresses[i].address,
95                                 true)) {
96       gpr_log(GPR_DEBUG, "c-ares address sorting: %s[%" PRIuPTR "]=%s",
97               input_output_str, i, addr_str);
98       gpr_free(addr_str);
99     } else {
100       gpr_log(GPR_DEBUG,
101               "c-ares address sorting: %s[%" PRIuPTR "]=<unprintable>",
102               input_output_str, i);
103     }
104   }
105 }
106 
grpc_cares_wrapper_address_sorting_sort(grpc_lb_addresses * lb_addrs)107 void grpc_cares_wrapper_address_sorting_sort(grpc_lb_addresses* lb_addrs) {
108   if (grpc_trace_cares_address_sorting.enabled()) {
109     log_address_sorting_list(lb_addrs, "input");
110   }
111   address_sorting_sortable* sortables = (address_sorting_sortable*)gpr_zalloc(
112       sizeof(address_sorting_sortable) * lb_addrs->num_addresses);
113   for (size_t i = 0; i < lb_addrs->num_addresses; i++) {
114     sortables[i].user_data = &lb_addrs->addresses[i];
115     memcpy(&sortables[i].dest_addr.addr, &lb_addrs->addresses[i].address.addr,
116            lb_addrs->addresses[i].address.len);
117     sortables[i].dest_addr.len = lb_addrs->addresses[i].address.len;
118   }
119   address_sorting_rfc_6724_sort(sortables, lb_addrs->num_addresses);
120   grpc_lb_address* sorted_lb_addrs = (grpc_lb_address*)gpr_zalloc(
121       sizeof(grpc_lb_address) * lb_addrs->num_addresses);
122   for (size_t i = 0; i < lb_addrs->num_addresses; i++) {
123     sorted_lb_addrs[i] = *(grpc_lb_address*)sortables[i].user_data;
124   }
125   gpr_free(sortables);
126   gpr_free(lb_addrs->addresses);
127   lb_addrs->addresses = sorted_lb_addrs;
128   if (grpc_trace_cares_address_sorting.enabled()) {
129     log_address_sorting_list(lb_addrs, "output");
130   }
131 }
132 
grpc_ares_request_ref_locked(grpc_ares_request * r)133 static void grpc_ares_request_ref_locked(grpc_ares_request* r) {
134   r->pending_queries++;
135 }
136 
grpc_ares_request_unref_locked(grpc_ares_request * r)137 static void grpc_ares_request_unref_locked(grpc_ares_request* r) {
138   r->pending_queries--;
139   if (r->pending_queries == 0u) {
140     grpc_ares_ev_driver_on_queries_complete_locked(r->ev_driver);
141   }
142 }
143 
grpc_ares_complete_request_locked(grpc_ares_request * r)144 void grpc_ares_complete_request_locked(grpc_ares_request* r) {
145   /* Invoke on_done callback and destroy the
146      request */
147   grpc_lb_addresses* lb_addrs = *(r->lb_addrs_out);
148   if (lb_addrs != nullptr) {
149     grpc_cares_wrapper_address_sorting_sort(lb_addrs);
150   }
151   GRPC_CLOSURE_SCHED(r->on_done, r->error);
152   gpr_free(r);
153 }
154 
create_hostbyname_request_locked(grpc_ares_request * parent_request,char * host,uint16_t port,bool is_balancer)155 static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
156     grpc_ares_request* parent_request, char* host, uint16_t port,
157     bool is_balancer) {
158   grpc_ares_hostbyname_request* hr = static_cast<grpc_ares_hostbyname_request*>(
159       gpr_zalloc(sizeof(grpc_ares_hostbyname_request)));
160   hr->parent_request = parent_request;
161   hr->host = gpr_strdup(host);
162   hr->port = port;
163   hr->is_balancer = is_balancer;
164   grpc_ares_request_ref_locked(parent_request);
165   return hr;
166 }
167 
destroy_hostbyname_request_locked(grpc_ares_hostbyname_request * hr)168 static void destroy_hostbyname_request_locked(
169     grpc_ares_hostbyname_request* hr) {
170   grpc_ares_request_unref_locked(hr->parent_request);
171   gpr_free(hr->host);
172   gpr_free(hr);
173 }
174 
on_hostbyname_done_locked(void * arg,int status,int timeouts,struct hostent * hostent)175 static void on_hostbyname_done_locked(void* arg, int status, int timeouts,
176                                       struct hostent* hostent) {
177   grpc_ares_hostbyname_request* hr =
178       static_cast<grpc_ares_hostbyname_request*>(arg);
179   grpc_ares_request* r = hr->parent_request;
180   if (status == ARES_SUCCESS) {
181     GRPC_ERROR_UNREF(r->error);
182     r->error = GRPC_ERROR_NONE;
183     r->success = true;
184     grpc_lb_addresses** lb_addresses = r->lb_addrs_out;
185     if (*lb_addresses == nullptr) {
186       *lb_addresses = grpc_lb_addresses_create(0, nullptr);
187     }
188     size_t prev_naddr = (*lb_addresses)->num_addresses;
189     size_t i;
190     for (i = 0; hostent->h_addr_list[i] != nullptr; i++) {
191     }
192     (*lb_addresses)->num_addresses += i;
193     (*lb_addresses)->addresses = static_cast<grpc_lb_address*>(
194         gpr_realloc((*lb_addresses)->addresses,
195                     sizeof(grpc_lb_address) * (*lb_addresses)->num_addresses));
196     for (i = prev_naddr; i < (*lb_addresses)->num_addresses; i++) {
197       switch (hostent->h_addrtype) {
198         case AF_INET6: {
199           size_t addr_len = sizeof(struct sockaddr_in6);
200           struct sockaddr_in6 addr;
201           memset(&addr, 0, addr_len);
202           memcpy(&addr.sin6_addr, hostent->h_addr_list[i - prev_naddr],
203                  sizeof(struct in6_addr));
204           addr.sin6_family = static_cast<unsigned char>(hostent->h_addrtype);
205           addr.sin6_port = hr->port;
206           grpc_lb_addresses_set_address(
207               *lb_addresses, i, &addr, addr_len,
208               hr->is_balancer /* is_balancer */,
209               hr->is_balancer ? hr->host : nullptr /* balancer_name */,
210               nullptr /* user_data */);
211           char output[INET6_ADDRSTRLEN];
212           ares_inet_ntop(AF_INET6, &addr.sin6_addr, output, INET6_ADDRSTRLEN);
213           gpr_log(GPR_DEBUG,
214                   "c-ares resolver gets a AF_INET6 result: \n"
215                   "  addr: %s\n  port: %d\n  sin6_scope_id: %d\n",
216                   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 - prev_naddr],
224                  sizeof(struct in_addr));
225           addr.sin_family = static_cast<unsigned char>(hostent->h_addrtype);
226           addr.sin_port = hr->port;
227           grpc_lb_addresses_set_address(
228               *lb_addresses, i, &addr, addr_len,
229               hr->is_balancer /* is_balancer */,
230               hr->is_balancer ? hr->host : nullptr /* balancer_name */,
231               nullptr /* user_data */);
232           char output[INET_ADDRSTRLEN];
233           ares_inet_ntop(AF_INET, &addr.sin_addr, output, INET_ADDRSTRLEN);
234           gpr_log(GPR_DEBUG,
235                   "c-ares resolver gets a AF_INET result: \n"
236                   "  addr: %s\n  port: %d\n",
237                   output, ntohs(hr->port));
238           break;
239         }
240       }
241     }
242   } else if (!r->success) {
243     char* error_msg;
244     gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
245                  ares_strerror(status));
246     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
247     gpr_free(error_msg);
248     if (r->error == GRPC_ERROR_NONE) {
249       r->error = error;
250     } else {
251       r->error = grpc_error_add_child(error, r->error);
252     }
253   }
254   destroy_hostbyname_request_locked(hr);
255 }
256 
on_srv_query_done_locked(void * arg,int status,int timeouts,unsigned char * abuf,int alen)257 static void on_srv_query_done_locked(void* arg, int status, int timeouts,
258                                      unsigned char* abuf, int alen) {
259   grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
260   gpr_log(GPR_DEBUG, "on_query_srv_done_locked");
261   if (status == ARES_SUCCESS) {
262     gpr_log(GPR_DEBUG, "on_query_srv_done_locked ARES_SUCCESS");
263     struct ares_srv_reply* reply;
264     const int parse_status = ares_parse_srv_reply(abuf, alen, &reply);
265     if (parse_status == ARES_SUCCESS) {
266       ares_channel* channel =
267           grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
268       for (struct ares_srv_reply* srv_it = reply; srv_it != nullptr;
269            srv_it = srv_it->next) {
270         if (grpc_ares_query_ipv6()) {
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_INET6,
274                              on_hostbyname_done_locked, hr);
275         }
276         grpc_ares_hostbyname_request* hr = create_hostbyname_request_locked(
277             r, srv_it->host, htons(srv_it->port), true /* is_balancer */);
278         ares_gethostbyname(*channel, hr->host, AF_INET,
279                            on_hostbyname_done_locked, hr);
280         grpc_ares_ev_driver_start_locked(r->ev_driver);
281       }
282     }
283     if (reply != nullptr) {
284       ares_free_data(reply);
285     }
286   } else if (!r->success) {
287     char* error_msg;
288     gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
289                  ares_strerror(status));
290     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
291     gpr_free(error_msg);
292     if (r->error == GRPC_ERROR_NONE) {
293       r->error = error;
294     } else {
295       r->error = grpc_error_add_child(error, r->error);
296     }
297   }
298   grpc_ares_request_unref_locked(r);
299 }
300 
301 static const char g_service_config_attribute_prefix[] = "grpc_config=";
302 
on_txt_done_locked(void * arg,int status,int timeouts,unsigned char * buf,int len)303 static void on_txt_done_locked(void* arg, int status, int timeouts,
304                                unsigned char* buf, int len) {
305   gpr_log(GPR_DEBUG, "on_txt_done_locked");
306   char* error_msg;
307   grpc_ares_request* r = static_cast<grpc_ares_request*>(arg);
308   const size_t prefix_len = sizeof(g_service_config_attribute_prefix) - 1;
309   struct ares_txt_ext* result = nullptr;
310   struct ares_txt_ext* reply = nullptr;
311   grpc_error* error = GRPC_ERROR_NONE;
312   if (status != ARES_SUCCESS) goto fail;
313   status = ares_parse_txt_reply_ext(buf, len, &reply);
314   if (status != ARES_SUCCESS) goto fail;
315   // Find service config in TXT record.
316   for (result = reply; result != nullptr; result = result->next) {
317     if (result->record_start &&
318         memcmp(result->txt, g_service_config_attribute_prefix, prefix_len) ==
319             0) {
320       break;
321     }
322   }
323   // Found a service config record.
324   if (result != nullptr) {
325     size_t service_config_len = result->length - prefix_len;
326     *r->service_config_json_out =
327         static_cast<char*>(gpr_malloc(service_config_len + 1));
328     memcpy(*r->service_config_json_out, result->txt + prefix_len,
329            service_config_len);
330     for (result = result->next; result != nullptr && !result->record_start;
331          result = result->next) {
332       *r->service_config_json_out = static_cast<char*>(
333           gpr_realloc(*r->service_config_json_out,
334                       service_config_len + result->length + 1));
335       memcpy(*r->service_config_json_out + service_config_len, result->txt,
336              result->length);
337       service_config_len += result->length;
338     }
339     (*r->service_config_json_out)[service_config_len] = '\0';
340     gpr_log(GPR_INFO, "found service config: %s", *r->service_config_json_out);
341   }
342   // Clean up.
343   ares_free_data(reply);
344   goto done;
345 fail:
346   gpr_asprintf(&error_msg, "C-ares TXT lookup status is not ARES_SUCCESS: %s",
347                ares_strerror(status));
348   error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
349   gpr_free(error_msg);
350   if (r->error == GRPC_ERROR_NONE) {
351     r->error = error;
352   } else {
353     r->error = grpc_error_add_child(error, r->error);
354   }
355 done:
356   grpc_ares_request_unref_locked(r);
357 }
358 
359 static grpc_ares_request*
grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(const char * dns_server,const char * name,const char * default_port,grpc_pollset_set * interested_parties,grpc_closure * on_done,grpc_lb_addresses ** addrs,bool check_grpclb,char ** service_config_json,grpc_combiner * combiner)360 grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
361     const char* dns_server, const char* name, const char* default_port,
362     grpc_pollset_set* interested_parties, grpc_closure* on_done,
363     grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json,
364     grpc_combiner* combiner) {
365   grpc_error* error = GRPC_ERROR_NONE;
366   grpc_ares_hostbyname_request* hr = nullptr;
367   grpc_ares_request* r = nullptr;
368   ares_channel* channel = nullptr;
369   /* TODO(zyc): Enable tracing after #9603 is checked in */
370   /* if (grpc_dns_trace) {
371       gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s",
372               name, default_port);
373      } */
374 
375   /* parse name, splitting it into host and port parts */
376   char* host;
377   char* port;
378   gpr_split_host_port(name, &host, &port);
379   if (host == nullptr) {
380     error = grpc_error_set_str(
381         GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
382         GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
383     goto error_cleanup;
384   } else if (port == nullptr) {
385     if (default_port == nullptr) {
386       error = grpc_error_set_str(
387           GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
388           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
389       goto error_cleanup;
390     }
391     port = gpr_strdup(default_port);
392   }
393   r = static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
394   r->ev_driver = nullptr;
395   r->on_done = on_done;
396   r->lb_addrs_out = addrs;
397   r->service_config_json_out = service_config_json;
398   r->success = false;
399   r->error = GRPC_ERROR_NONE;
400   r->pending_queries = 0;
401   error = grpc_ares_ev_driver_create_locked(&r->ev_driver, interested_parties,
402                                             combiner, r);
403   if (error != GRPC_ERROR_NONE) goto error_cleanup;
404   channel = grpc_ares_ev_driver_get_channel_locked(r->ev_driver);
405   // If dns_server is specified, use it.
406   if (dns_server != nullptr) {
407     gpr_log(GPR_INFO, "Using DNS server %s", dns_server);
408     grpc_resolved_address addr;
409     if (grpc_parse_ipv4_hostport(dns_server, &addr, false /* log_errors */)) {
410       r->dns_server_addr.family = AF_INET;
411       struct sockaddr_in* in = reinterpret_cast<struct sockaddr_in*>(addr.addr);
412       memcpy(&r->dns_server_addr.addr.addr4, &in->sin_addr,
413              sizeof(struct in_addr));
414       r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
415       r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
416     } else if (grpc_parse_ipv6_hostport(dns_server, &addr,
417                                         false /* log_errors */)) {
418       r->dns_server_addr.family = AF_INET6;
419       struct sockaddr_in6* in6 =
420           reinterpret_cast<struct sockaddr_in6*>(addr.addr);
421       memcpy(&r->dns_server_addr.addr.addr6, &in6->sin6_addr,
422              sizeof(struct in6_addr));
423       r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
424       r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
425     } else {
426       error = grpc_error_set_str(
427           GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
428           GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
429       goto error_cleanup;
430     }
431     int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
432     if (status != ARES_SUCCESS) {
433       char* error_msg;
434       gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
435                    ares_strerror(status));
436       error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
437       gpr_free(error_msg);
438       goto error_cleanup;
439     }
440   }
441   r->pending_queries = 1;
442   if (grpc_ares_query_ipv6()) {
443     hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port),
444                                           false /* is_balancer */);
445     ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked,
446                        hr);
447   }
448   hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port),
449                                         false /* is_balancer */);
450   ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked,
451                      hr);
452   if (check_grpclb) {
453     /* Query the SRV record */
454     grpc_ares_request_ref_locked(r);
455     char* service_name;
456     gpr_asprintf(&service_name, "_grpclb._tcp.%s", host);
457     ares_query(*channel, service_name, ns_c_in, ns_t_srv,
458                on_srv_query_done_locked, r);
459     gpr_free(service_name);
460   }
461   if (service_config_json != nullptr) {
462     grpc_ares_request_ref_locked(r);
463     char* config_name;
464     gpr_asprintf(&config_name, "_grpc_config.%s", host);
465     ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_locked,
466                 r);
467     gpr_free(config_name);
468   }
469   grpc_ares_ev_driver_start_locked(r->ev_driver);
470   grpc_ares_request_unref_locked(r);
471   gpr_free(host);
472   gpr_free(port);
473   return r;
474 
475 error_cleanup:
476   GRPC_CLOSURE_SCHED(on_done, error);
477   gpr_free(r);
478   gpr_free(host);
479   gpr_free(port);
480   return nullptr;
481 }
482 
inner_resolve_as_ip_literal_locked(const char * name,const char * default_port,grpc_lb_addresses ** addrs,char ** host,char ** port,char ** hostport)483 static bool inner_resolve_as_ip_literal_locked(const char* name,
484                                                const char* default_port,
485                                                grpc_lb_addresses** addrs,
486                                                char** host, char** port,
487                                                char** hostport) {
488   gpr_split_host_port(name, host, port);
489   if (*host == nullptr) {
490     gpr_log(GPR_ERROR,
491             "Failed to parse %s to host:port while attempting to resolve as ip "
492             "literal.",
493             name);
494     return false;
495   }
496   if (*port == nullptr) {
497     if (default_port == nullptr) {
498       gpr_log(GPR_ERROR,
499               "No port or default port for %s while attempting to resolve as "
500               "ip literal.",
501               name);
502       return false;
503     }
504     *port = gpr_strdup(default_port);
505   }
506   grpc_resolved_address addr;
507   GPR_ASSERT(gpr_join_host_port(hostport, *host, atoi(*port)));
508   if (grpc_parse_ipv4_hostport(*hostport, &addr, false /* log errors */) ||
509       grpc_parse_ipv6_hostport(*hostport, &addr, false /* log errors */)) {
510     GPR_ASSERT(*addrs == nullptr);
511     *addrs = grpc_lb_addresses_create(1, nullptr);
512     grpc_lb_addresses_set_address(
513         *addrs, 0, addr.addr, addr.len, false /* is_balancer */,
514         nullptr /* balancer_name */, nullptr /* user_data */);
515     return true;
516   }
517   return false;
518 }
519 
resolve_as_ip_literal_locked(const char * name,const char * default_port,grpc_lb_addresses ** addrs)520 static bool resolve_as_ip_literal_locked(const char* name,
521                                          const char* default_port,
522                                          grpc_lb_addresses** addrs) {
523   char* host = nullptr;
524   char* port = nullptr;
525   char* hostport = nullptr;
526   bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs,
527                                                 &host, &port, &hostport);
528   gpr_free(host);
529   gpr_free(port);
530   gpr_free(hostport);
531   return out;
532 }
533 
grpc_dns_lookup_ares_locked_impl(const char * dns_server,const char * name,const char * default_port,grpc_pollset_set * interested_parties,grpc_closure * on_done,grpc_lb_addresses ** addrs,bool check_grpclb,char ** service_config_json,grpc_combiner * combiner)534 static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
535     const char* dns_server, const char* name, const char* default_port,
536     grpc_pollset_set* interested_parties, grpc_closure* on_done,
537     grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json,
538     grpc_combiner* combiner) {
539   // Early out if the target is an ipv4 or ipv6 literal.
540   if (resolve_as_ip_literal_locked(name, default_port, addrs)) {
541     GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
542     return nullptr;
543   }
544   // Early out if the target is localhost and we're on Windows.
545   if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port,
546                                                         addrs)) {
547     GRPC_CLOSURE_SCHED(on_done, GRPC_ERROR_NONE);
548     return nullptr;
549   }
550   // Look up name using c-ares lib.
551   return grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
552       dns_server, name, default_port, interested_parties, on_done, addrs,
553       check_grpclb, service_config_json, combiner);
554 }
555 
556 grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
557     const char* dns_server, const char* name, const char* default_port,
558     grpc_pollset_set* interested_parties, grpc_closure* on_done,
559     grpc_lb_addresses** addrs, bool check_grpclb, char** service_config_json,
560     grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
561 
grpc_cancel_ares_request(grpc_ares_request * r)562 void grpc_cancel_ares_request(grpc_ares_request* r) {
563   if (grpc_dns_lookup_ares_locked == grpc_dns_lookup_ares_locked_impl) {
564     if (r != nullptr) {
565       grpc_ares_ev_driver_shutdown_locked(r->ev_driver);
566     }
567   }
568 }
569 
grpc_ares_init(void)570 grpc_error* grpc_ares_init(void) {
571   gpr_once_init(&g_basic_init, do_basic_init);
572   gpr_mu_lock(&g_init_mu);
573   int status = ares_library_init(ARES_LIB_INIT_ALL);
574   gpr_mu_unlock(&g_init_mu);
575 
576   if (status != ARES_SUCCESS) {
577     char* error_msg;
578     gpr_asprintf(&error_msg, "ares_library_init failed: %s",
579                  ares_strerror(status));
580     grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
581     gpr_free(error_msg);
582     return error;
583   }
584   return GRPC_ERROR_NONE;
585 }
586 
grpc_ares_cleanup(void)587 void grpc_ares_cleanup(void) {
588   gpr_mu_lock(&g_init_mu);
589   ares_library_cleanup();
590   gpr_mu_unlock(&g_init_mu);
591 }
592 
593 /*
594  * grpc_resolve_address_ares related structs and functions
595  */
596 
597 typedef struct grpc_resolve_address_ares_request {
598   /* combiner that queries and related callbacks run under */
599   grpc_combiner* combiner;
600   /** the pointer to receive the resolved addresses */
601   grpc_resolved_addresses** addrs_out;
602   /** currently resolving lb addresses */
603   grpc_lb_addresses* lb_addrs;
604   /** closure to call when the resolve_address_ares request completes */
605   grpc_closure* on_resolve_address_done;
606   /** a closure wrapping on_dns_lookup_done_cb, which should be invoked when the
607       grpc_dns_lookup_ares_locked operation is done. */
608   grpc_closure on_dns_lookup_done;
609   /* target name */
610   const char* name;
611   /* default port to use if none is specified */
612   const char* default_port;
613   /* pollset_set to be driven by */
614   grpc_pollset_set* interested_parties;
615 } grpc_resolve_address_ares_request;
616 
on_dns_lookup_done_cb(void * arg,grpc_error * error)617 static void on_dns_lookup_done_cb(void* arg, grpc_error* error) {
618   grpc_resolve_address_ares_request* r =
619       static_cast<grpc_resolve_address_ares_request*>(arg);
620   grpc_resolved_addresses** resolved_addresses = r->addrs_out;
621   if (r->lb_addrs == nullptr || r->lb_addrs->num_addresses == 0) {
622     *resolved_addresses = nullptr;
623   } else {
624     *resolved_addresses = static_cast<grpc_resolved_addresses*>(
625         gpr_zalloc(sizeof(grpc_resolved_addresses)));
626     (*resolved_addresses)->naddrs = r->lb_addrs->num_addresses;
627     (*resolved_addresses)->addrs =
628         static_cast<grpc_resolved_address*>(gpr_zalloc(
629             sizeof(grpc_resolved_address) * (*resolved_addresses)->naddrs));
630     for (size_t i = 0; i < (*resolved_addresses)->naddrs; i++) {
631       GPR_ASSERT(!r->lb_addrs->addresses[i].is_balancer);
632       memcpy(&(*resolved_addresses)->addrs[i],
633              &r->lb_addrs->addresses[i].address, sizeof(grpc_resolved_address));
634     }
635   }
636   GRPC_CLOSURE_SCHED(r->on_resolve_address_done, GRPC_ERROR_REF(error));
637   if (r->lb_addrs != nullptr) grpc_lb_addresses_destroy(r->lb_addrs);
638   GRPC_COMBINER_UNREF(r->combiner, "on_dns_lookup_done_cb");
639   gpr_free(r);
640 }
641 
grpc_resolve_address_invoke_dns_lookup_ares_locked(void * arg,grpc_error * unused_error)642 static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
643     void* arg, grpc_error* unused_error) {
644   grpc_resolve_address_ares_request* r =
645       static_cast<grpc_resolve_address_ares_request*>(arg);
646   grpc_dns_lookup_ares_locked(
647       nullptr /* dns_server */, r->name, r->default_port, r->interested_parties,
648       &r->on_dns_lookup_done, &r->lb_addrs, false /* check_grpclb */,
649       nullptr /* service_config_json */, r->combiner);
650 }
651 
grpc_resolve_address_ares_impl(const char * name,const char * default_port,grpc_pollset_set * interested_parties,grpc_closure * on_done,grpc_resolved_addresses ** addrs)652 static void grpc_resolve_address_ares_impl(const char* name,
653                                            const char* default_port,
654                                            grpc_pollset_set* interested_parties,
655                                            grpc_closure* on_done,
656                                            grpc_resolved_addresses** addrs) {
657   grpc_resolve_address_ares_request* r =
658       static_cast<grpc_resolve_address_ares_request*>(
659           gpr_zalloc(sizeof(grpc_resolve_address_ares_request)));
660   r->combiner = grpc_combiner_create();
661   r->addrs_out = addrs;
662   r->on_resolve_address_done = on_done;
663   GRPC_CLOSURE_INIT(&r->on_dns_lookup_done, on_dns_lookup_done_cb, r,
664                     grpc_schedule_on_exec_ctx);
665   r->name = name;
666   r->default_port = default_port;
667   r->interested_parties = interested_parties;
668   GRPC_CLOSURE_SCHED(
669       GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r,
670                           grpc_combiner_scheduler(r->combiner)),
671       GRPC_ERROR_NONE);
672 }
673 
674 void (*grpc_resolve_address_ares)(
675     const char* name, const char* default_port,
676     grpc_pollset_set* interested_parties, grpc_closure* on_done,
677     grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl;
678 
679 #endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */
680