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/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"
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 */
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));
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.reset(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.get(),
418 grpc_strhtons(port.get()),
419 /*is_balancer=*/false);
420 ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_locked,
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,
429 /* Query the SRV record */
430 grpc_ares_request_ref_locked(r);
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);
437 if (r->service_config_json_out != nullptr) {
438 grpc_ares_request_ref_locked(r);
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,
443 gpr_free(config_name);
445 grpc_ares_ev_driver_start_locked(r->ev_driver);
446 grpc_ares_request_unref_locked(r);
450 GRPC_CLOSURE_SCHED(r->on_done, error);
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) {
461 "Failed to parse %s to host:port while attempting to resolve as ip "
466 if (*port == nullptr) {
467 if (default_port == nullptr) {
469 "No port or default port for %s while attempting to resolve as "
474 port->reset(gpr_strdup(default_port));
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 */);
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);
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);
508 if (gpr_stricmp(host->get(), "localhost") == 0) {
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);
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) {
529 "Failed to parse %s into host:port during manual localhost "
534 if (*port == nullptr) {
535 if (default_port == nullptr) {
537 "No port or default port for %s during manual localhost "
542 port->reset(gpr_strdup(default_port));
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),
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),
565 // Let the address sorter figure out which one should be tried first.
566 grpc_cares_wrapper_address_sorting_sort(addrs->get());
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);
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) {
586 #endif /* GRPC_ARES_RESOLVE_LOCALHOST_MANUALLY */
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, "
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);
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,
614 grpc_ares_complete_request_locked(r);
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;
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);
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;
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);
645 void (*grpc_cancel_ares_request_locked)(grpc_ares_request* r) =
646 grpc_cancel_ares_request_locked_impl;
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.
652 grpc_error* grpc_ares_init(void) {
653 int status = ares_library_init(ARES_LIB_INIT_ALL);
654 if (status != ARES_SUCCESS) {
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);
662 return GRPC_ERROR_NONE;
665 void grpc_ares_cleanup(void) { ares_library_cleanup(); }
667 grpc_error* grpc_ares_init(void) { return GRPC_ERROR_NONE; }
668 void grpc_ares_cleanup(void) {}
669 #endif // GPR_WINDOWS
672 * grpc_resolve_address_ares related structs and functions
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;
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;
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;
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));
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);
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,
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));
746 r->default_port = default_port;
747 r->interested_parties = interested_parties;
749 GRPC_CLOSURE_CREATE(grpc_resolve_address_invoke_dns_lookup_ares_locked, r,
750 grpc_combiner_scheduler(r->combiner)),
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;
759 #endif /* GRPC_ARES == 1 */