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