3 * Copyright 2016 gRPC authors.
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
9 * http://www.apache.org/licenses/LICENSE-2.0
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.
19 #include <grpc/support/port_platform.h>
23 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
24 #include "src/core/lib/iomgr/sockaddr.h"
27 #include <sys/types.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>
35 #include <address_sorting/address_sorting.h>
36 #include "src/core/ext/filters/client_channel/parse_address.h"
37 #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
38 #include "src/core/lib/gpr/host_port.h"
39 #include "src/core/lib/gpr/string.h"
40 #include "src/core/lib/iomgr/combiner.h"
41 #include "src/core/lib/iomgr/error.h"
42 #include "src/core/lib/iomgr/executor.h"
43 #include "src/core/lib/iomgr/iomgr_internal.h"
44 #include "src/core/lib/iomgr/nameser.h"
45 #include "src/core/lib/iomgr/sockaddr_utils.h"
47 using grpc_core::ServerAddress;
48 using grpc_core::ServerAddressList;
50 grpc_core::TraceFlag grpc_trace_cares_address_sorting(false,
51 "cares_address_sorting");
53 grpc_core::TraceFlag grpc_trace_cares_resolver(false, "cares_resolver");
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;
70 /** the errors explaining query failures, appended to in query callbacks */
74 typedef struct grpc_ares_hostbyname_request {
75 /** following members are set in create_hostbyname_request_locked
77 /** the top-level request instance */
78 grpc_ares_request* parent_request;
79 /** host to resolve, parsed from the name to resolve */
81 /** port to fill in sockaddr_in, parsed from the name to resolve */
83 /** is it a grpclb address */
85 } grpc_ares_hostbyname_request;
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++) {
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);
97 "c-ares address sorting: %s[%" PRIuPTR "]=<unprintable>",
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");
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;
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));
122 *addresses = std::move(sorted);
123 if (GRPC_TRACE_FLAG_ENABLED(grpc_trace_cares_address_sorting)) {
124 log_address_sorting_list(*addresses, "output");
128 static void grpc_ares_request_ref_locked(grpc_ares_request* r) {
129 r->pending_queries++;
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);
139 void grpc_ares_complete_request_locked(grpc_ares_request* r) {
140 /* Invoke on_done callback and destroy the
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
151 GRPC_CLOSURE_SCHED(r->on_done, r->error);
154 static grpc_ares_hostbyname_request* create_hostbyname_request_locked(
155 grpc_ares_request* parent_request, char* host, uint16_t port,
157 GRPC_CARES_TRACE_LOG(
158 "request:%p create_hostbyname_request_locked host:%s port:%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);
166 hr->is_balancer = is_balancer;
167 grpc_ares_request_ref_locked(parent_request);
171 static void destroy_hostbyname_request_locked(
172 grpc_ares_hostbyname_request* hr) {
173 grpc_ares_request_unref_locked(hr->parent_request);
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,
187 if (*r->addresses_out == nullptr) {
188 *r->addresses_out = grpc_core::MakeUnique<ServerAddressList>();
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));
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) {
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);
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));
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);
246 r->error = grpc_error_add_child(error, r->error);
248 destroy_hostbyname_request_locked(hr);
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,
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);
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);
278 if (reply != nullptr) {
279 ares_free_data(reply);
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,
287 grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
289 r->error = grpc_error_add_child(error, r->error);
291 grpc_ares_request_unref_locked(r);
294 static const char g_service_config_attribute_prefix[] = "grpc_config=";
296 static void on_txt_done_locked(void* arg, int status, int timeouts,
297 unsigned char* buf, int len) {
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) ==
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,
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,
330 service_config_len += result->length;
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);
337 ares_free_data(reply);
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);
345 r->error = grpc_error_add_child(error, r->error);
347 grpc_ares_request_unref_locked(r);
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 */
360 gpr_split_host_port(name, &host, &port);
361 if (host == nullptr) {
362 error = grpc_error_set_str(
363 GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
364 GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
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));
373 port = gpr_strdup(default_port);
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);
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));
405 int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
406 if (status != ARES_SUCCESS) {
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);
415 r->pending_queries = 1;
416 if (grpc_ares_query_ipv6()) {
417 hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port),
418 false /* is_balancer */);
419 ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked,
422 hr = create_hostbyname_request_locked(r, host, grpc_strhtons(port),
423 false /* is_balancer */);
424 ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_locked,
427 /* Query the SRV record */
428 grpc_ares_request_ref_locked(r);
430 gpr_asprintf(&service_name, "_grpclb._tcp.%s", host);
431 ares_query(*channel, service_name, ns_c_in, ns_t_srv,
432 on_srv_query_done_locked, r);
433 gpr_free(service_name);
435 if (r->service_config_json_out != nullptr) {
436 grpc_ares_request_ref_locked(r);
438 gpr_asprintf(&config_name, "_grpc_config.%s", host);
439 ares_search(*channel, config_name, ns_c_in, ns_t_txt, on_txt_done_locked,
441 gpr_free(config_name);
443 grpc_ares_ev_driver_start_locked(r->ev_driver);
444 grpc_ares_request_unref_locked(r);
450 GRPC_CLOSURE_SCHED(r->on_done, error);
455 static bool inner_resolve_as_ip_literal_locked(
456 const char* name, const char* default_port,
457 grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs, char** host,
458 char** port, char** hostport) {
459 gpr_split_host_port(name, host, port);
460 if (*host == nullptr) {
462 "Failed to parse %s to host:port while attempting to resolve as ip "
467 if (*port == nullptr) {
468 if (default_port == nullptr) {
470 "No port or default port for %s while attempting to resolve as "
475 *port = gpr_strdup(default_port);
477 grpc_resolved_address addr;
478 GPR_ASSERT(gpr_join_host_port(hostport, *host, atoi(*port)));
479 if (grpc_parse_ipv4_hostport(*hostport, &addr, false /* log errors */) ||
480 grpc_parse_ipv6_hostport(*hostport, &addr, false /* log errors */)) {
481 GPR_ASSERT(*addrs == nullptr);
482 *addrs = grpc_core::MakeUnique<ServerAddressList>();
483 (*addrs)->emplace_back(addr.addr, addr.len, nullptr /* args */);
489 static bool resolve_as_ip_literal_locked(
490 const char* name, const char* default_port,
491 grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
492 char* host = nullptr;
493 char* port = nullptr;
494 char* hostport = nullptr;
495 bool out = inner_resolve_as_ip_literal_locked(name, default_port, addrs,
496 &host, &port, &hostport);
503 static bool target_matches_localhost_inner(const char* name, char** host,
505 if (!gpr_split_host_port(name, host, port)) {
506 gpr_log(GPR_ERROR, "Unable to split host and port for name: %s", name);
509 if (gpr_stricmp(*host, "localhost") == 0) {
516 static bool target_matches_localhost(const char* name) {
517 char* host = nullptr;
518 char* port = nullptr;
519 bool out = target_matches_localhost_inner(name, &host, &port);
525 #ifdef GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY
526 static bool inner_maybe_resolve_localhost_manually_locked(
527 const char* name, const char* default_port,
528 grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs, char** host,
530 gpr_split_host_port(name, host, port);
531 if (*host == nullptr) {
533 "Failed to parse %s into host:port during manual localhost "
538 if (*port == nullptr) {
539 if (default_port == nullptr) {
541 "No port or default port for %s during manual localhost "
546 *port = gpr_strdup(default_port);
548 if (gpr_stricmp(*host, "localhost") == 0) {
549 GPR_ASSERT(*addrs == nullptr);
550 *addrs = grpc_core::MakeUnique<grpc_core::ServerAddressList>();
551 uint16_t numeric_port = grpc_strhtons(*port);
552 // Append the ipv6 loopback address.
553 struct sockaddr_in6 ipv6_loopback_addr;
554 memset(&ipv6_loopback_addr, 0, sizeof(ipv6_loopback_addr));
555 ((char*)&ipv6_loopback_addr.sin6_addr)[15] = 1;
556 ipv6_loopback_addr.sin6_family = AF_INET6;
557 ipv6_loopback_addr.sin6_port = numeric_port;
558 (*addrs)->emplace_back(&ipv6_loopback_addr, sizeof(ipv6_loopback_addr),
560 // Append the ipv4 loopback address.
561 struct sockaddr_in ipv4_loopback_addr;
562 memset(&ipv4_loopback_addr, 0, sizeof(ipv4_loopback_addr));
563 ((char*)&ipv4_loopback_addr.sin_addr)[0] = 0x7f;
564 ((char*)&ipv4_loopback_addr.sin_addr)[3] = 0x01;
565 ipv4_loopback_addr.sin_family = AF_INET;
566 ipv4_loopback_addr.sin_port = numeric_port;
567 (*addrs)->emplace_back(&ipv4_loopback_addr, sizeof(ipv4_loopback_addr),
569 // Let the address sorter figure out which one should be tried first.
570 grpc_cares_wrapper_address_sorting_sort(addrs->get());
576 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
577 const char* name, const char* default_port,
578 grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
579 char* host = nullptr;
580 char* port = nullptr;
581 bool out = inner_maybe_resolve_localhost_manually_locked(name, default_port,
582 addrs, &host, &port);
587 #else /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
588 static bool grpc_ares_maybe_resolve_localhost_manually_locked(
589 const char* name, const char* default_port,
590 grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs) {
593 #endif /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
595 static grpc_ares_request* grpc_dns_lookup_ares_locked_impl(
596 const char* dns_server, const char* name, const char* default_port,
597 grpc_pollset_set* interested_parties, grpc_closure* on_done,
598 grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
599 bool check_grpclb, char** service_config_json, int query_timeout_ms,
600 grpc_combiner* combiner) {
601 grpc_ares_request* r =
602 static_cast<grpc_ares_request*>(gpr_zalloc(sizeof(grpc_ares_request)));
603 r->ev_driver = nullptr;
604 r->on_done = on_done;
605 r->addresses_out = addrs;
606 r->service_config_json_out = service_config_json;
607 r->error = GRPC_ERROR_NONE;
608 r->pending_queries = 0;
609 GRPC_CARES_TRACE_LOG(
610 "request:%p c-ares grpc_dns_lookup_ares_locked_impl name=%s, "
612 r, name, default_port);
613 // Early out if the target is an ipv4 or ipv6 literal.
614 if (resolve_as_ip_literal_locked(name, default_port, addrs)) {
615 grpc_ares_complete_request_locked(r);
618 // Early out if the target is localhost and we're on Windows.
619 if (grpc_ares_maybe_resolve_localhost_manually_locked(name, default_port,
621 grpc_ares_complete_request_locked(r);
624 // Don't query for SRV and TXT records if the target is "localhost", so
625 // as to cut down on lookups over the network, especially in tests:
626 // https://github.com/grpc/proposal/pull/79
627 if (target_matches_localhost(name)) {
628 check_grpclb = false;
629 r->service_config_json_out = nullptr;
631 // Look up name using c-ares lib.
632 grpc_dns_lookup_ares_continue_after_check_localhost_and_ip_literals_locked(
633 r, dns_server, name, default_port, interested_parties, check_grpclb,
634 query_timeout_ms, combiner);
638 grpc_ares_request* (*grpc_dns_lookup_ares_locked)(
639 const char* dns_server, const char* name, const char* default_port,
640 grpc_pollset_set* interested_parties, grpc_closure* on_done,
641 grpc_core::UniquePtr<grpc_core::ServerAddressList>* addrs,
642 bool check_grpclb, char** service_config_json, int query_timeout_ms,
643 grpc_combiner* combiner) = grpc_dns_lookup_ares_locked_impl;
645 static void grpc_cancel_ares_request_locked_impl(grpc_ares_request* r) {
646 GPR_ASSERT(r != nullptr);
647 if (r->ev_driver != nullptr) {
648 grpc_ares_ev_driver_shutdown_locked(r->ev_driver);
652 void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) =
653 grpc_cancel_ares_request_locked_impl;
655 // ares_library_init and ares_library_cleanup are currently no-op except under
656 // Windows. Calling them may cause race conditions when other parts of the
657 // binary calls these functions concurrently.
659 grpc_error* grpc_ares_init(void) {
660 int status = ares_library_init(ARES_LIB_INIT_ALL);
661 if (status != ARES_SUCCESS) {
663 gpr_asprintf(&error_msg, "ares_library_init failed: %s",
664 ares_strerror(status));
665 grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
669 return GRPC_ERROR_NONE;
672 void grpc_ares_cleanup(void) { ares_library_cleanup(); }
674 grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; }
675 void grpc_ares_cleanup(void) {}
676 #endif // GPR_WINDOWS
679 * grpc_resolve_address_ares related structs and functions
682 typedef struct grpc_resolve_address_ares_request {
683 /* combiner that queries and related callbacks run under */
684 grpc_combiner* combiner;
685 /** the pointer to receive the resolved addresses */
686 grpc_resolved_addresses** addrs_out;
687 /** currently resolving addresses */
688 grpc_core::UniquePtr<ServerAddressList> addresses;
689 /** closure to call when the resolve_address_ares request completes */
690 grpc_closure* on_resolve_address_done;
691 /** a closure wrapping on_resolve_address_done, which should be invoked when
692 the grpc_dns_lookup_ares_locked operation is done. */
693 grpc_closure on_dns_lookup_done_locked;
696 /* default port to use if none is specified */
697 const char* default_port;
698 /* pollset_set to be driven by */
699 grpc_pollset_set* interested_parties;
700 /* underlying ares_request that the query is performed on */
701 grpc_ares_request* ares_request = nullptr;
702 } grpc_resolve_address_ares_request;
704 static void on_dns_lookup_done_locked(void* arg, grpc_error* error) {
705 grpc_resolve_address_ares_request* r =
706 static_cast<grpc_resolve_address_ares_request*>(arg);
707 gpr_free(r->ares_request);
708 grpc_resolved_addresses** resolved_addresses = r->addrs_out;
709 if (r->addresses == nullptr || r->addresses->empty()) {
710 *resolved_addresses = nullptr;
712 *resolved_addresses = static_cast<grpc_resolved_addresses*>(
713 gpr_zalloc(sizeof(grpc_resolved_addresses)));
714 (*resolved_addresses)->naddrs = r->addresses->size();
715 (*resolved_addresses)->addrs =
716 static_cast<grpc_resolved_address*>(gpr_zalloc(
717 sizeof(grpc_resolved_address) * (*resolved_addresses)->naddrs));
718 for (size_t i = 0; i < (*resolved_addresses)->naddrs; ++i) {
719 GPR_ASSERT(!(*r->addresses)[i].IsBalancer());
720 memcpy(&(*resolved_addresses)->addrs[i], &(*r->addresses)[i].address(),
721 sizeof(grpc_resolved_address));
724 GRPC_CLOSURE_SCHED(r->on_resolve_address_done, GRPC_ERROR_REF(error));
725 GRPC_COMBINER_UNREF(r->combiner, "on_dns_lookup_done_cb");
726 grpc_core::Delete(r);
729 static void grpc_resolve_address_invoke_dns_lookup_ares_locked(
730 void* arg, grpc_error* unused_error) {
731 grpc_resolve_address_ares_request* r =
732 static_cast<grpc_resolve_address_ares_request*>(arg);
733 r->ares_request = grpc_dns_lookup_ares_locked(
734 nullptr /* dns_server */, r->name, r->default_port, r->interested_parties,
735 &r->on_dns_lookup_done_locked, &r->addresses, false /* check_grpclb */,
736 nullptr /* service_config_json */, GRPC_DNS_ARES_DEFAULT_QUERY_TIMEOUT_MS,
740 static void grpc_resolve_address_ares_impl(const char* name,
741 const char* default_port,
742 grpc_pollset_set* interested_parties,
743 grpc_closure* on_done,
744 grpc_resolved_addresses** addrs) {
745 grpc_resolve_address_ares_request* r =
746 grpc_core::New<grpc_resolve_address_ares_request>();
747 r->combiner = grpc_combiner_create();
748 r->addrs_out = addrs;
749 r->on_resolve_address_done = on_done;
750 GRPC_CLOSURE_INIT(&r->on_dns_lookup_done_locked, on_dns_lookup_done_locked, r,
751 grpc_combiner_scheduler(r->combiner));
753 r->default_port = default_port;
754 r->interested_parties = interested_parties;
756 GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r,
757 grpc_combiner_scheduler(r->combiner)),
761 void (*grpc_resolve_address_ares)(
762 const char* name, const char* default_port,
763 grpc_pollset_set* interested_parties, grpc_closure* on_done,
764 grpc_resolved_addresses** addrs) = grpc_resolve_address_ares_impl;
766 #endif /* GRPC_ARES == 1 */