blob: 244b260dfa9450aefe94806ff392c1e755c5dca2 [file] [log] [blame]
Yuchen Zengd4bbfc72016-08-05 10:33:16 -07001/*
2 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02003 * Copyright 2016 gRPC authors.
Yuchen Zengd4bbfc72016-08-05 10:33:16 -07004 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02005 * 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
Yuchen Zengd4bbfc72016-08-05 10:33:16 -07008 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +02009 * http://www.apache.org/licenses/LICENSE-2.0
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070010 *
Jan Tattermusch7897ae92017-06-07 22:57:36 +020011 * 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.
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070016 *
17 */
18
19#include <grpc/support/port_platform.h>
Yuchen Zengd6b49852017-03-20 01:44:27 -070020#if GRPC_ARES == 1 && !defined(GRPC_UV)
Yuchen Zengd79f92a2016-08-08 01:18:32 -070021
Craig Tiller9eb0fde2017-03-31 16:59:30 -070022#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
Yuchen Zeng299dd8d2016-08-16 21:40:13 -070023#include "src/core/lib/iomgr/sockaddr.h"
Yuchen Zeng6eb83cc2016-08-23 00:44:18 -070024#include "src/core/lib/iomgr/socket_utils_posix.h"
Yuchen Zeng85750b02016-08-08 14:16:34 -070025
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070026#include <string.h>
27#include <sys/types.h>
28
29#include <ares.h>
30#include <grpc/support/alloc.h>
31#include <grpc/support/host_port.h>
32#include <grpc/support/log.h>
33#include <grpc/support/string_util.h>
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070034#include <grpc/support/time.h>
35#include <grpc/support/useful.h>
Yuchen Zengf3bdbb72017-05-18 18:22:23 -070036#include <nameser.h>
Mark D. Roth96fc54c2017-05-18 14:33:07 -070037
38#include "src/core/ext/filters/client_channel/parse_address.h"
Craig Tiller9eb0fde2017-03-31 16:59:30 -070039#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
Mark D. Roth96fc54c2017-05-18 14:33:07 -070040#include "src/core/lib/iomgr/error.h"
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070041#include "src/core/lib/iomgr/executor.h"
42#include "src/core/lib/iomgr/iomgr_internal.h"
43#include "src/core/lib/iomgr/sockaddr_utils.h"
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070044#include "src/core/lib/support/string.h"
45
Yuchen Zeng459480b2016-08-09 11:40:26 -070046static gpr_once g_basic_init = GPR_ONCE_INIT;
47static gpr_mu g_init_mu;
48
Yuchen Zeng3b4bed22017-06-04 01:41:15 -070049struct grpc_ares_request {
Mark D. Roth96fc54c2017-05-18 14:33:07 -070050 /** indicates the DNS server to use, if specified */
51 struct ares_addr_port_node dns_server_addr;
Yuchen Zeng3ae26632016-11-09 15:53:50 -080052 /** following members are set in grpc_resolve_address_ares_impl */
Yuchen Zeng3ae26632016-11-09 15:53:50 -080053 /** closure to call when the request completes */
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070054 grpc_closure *on_done;
Yuchen Zeng3ae26632016-11-09 15:53:50 -080055 /** the pointer to receive the resolved addresses */
Yuchen Zeng3385b4f2017-05-24 11:40:20 -070056 grpc_lb_addresses **lb_addrs_out;
Yuchen Zeng3ae26632016-11-09 15:53:50 -080057 /** the evernt driver used by this request */
Yuchen Zeng2648a952016-11-02 18:52:25 -070058 grpc_ares_ev_driver *ev_driver;
Yuchen Zeng3ae26632016-11-09 15:53:50 -080059 /** number of ongoing queries */
Yuchen Zeng2648a952016-11-02 18:52:25 -070060 gpr_refcount pending_queries;
61
62 /** mutex guarding the rest of the state */
63 gpr_mu mu;
Yuchen Zeng912327e2016-10-25 18:27:17 -070064 /** is there at least one successful query, set in on_done_cb */
65 bool success;
66 /** the errors explaining the request failure, set in on_done_cb */
Yuchen Zeng1d0c1c42016-08-18 15:36:24 -070067 grpc_error *error;
Yuchen Zeng3b4bed22017-06-04 01:41:15 -070068};
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070069
Yuchen Zengf3bdbb72017-05-18 18:22:23 -070070typedef struct grpc_ares_hostbyname_request {
71 /** following members are set in create_hostbyname_request */
72 /** the top-level request instance */
73 grpc_ares_request *parent_request;
74 /** host to resolve, parsed from the name to resolve */
75 char *host;
76 /** port to fill in sockaddr_in, parsed from the name to resolve */
77 uint16_t port;
78 /** is it a grpclb address */
79 bool is_balancer;
80} grpc_ares_hostbyname_request;
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070081
Yuchen Zengb48000c2016-08-09 22:44:23 -070082static void do_basic_init(void) { gpr_mu_init(&g_init_mu); }
Yuchen Zengd4bbfc72016-08-05 10:33:16 -070083
Yuchen Zenga0dbd9f2016-08-16 23:08:09 -070084static uint16_t strhtons(const char *port) {
85 if (strcmp(port, "http") == 0) {
86 return htons(80);
87 } else if (strcmp(port, "https") == 0) {
88 return htons(443);
89 }
90 return htons((unsigned short)atoi(port));
91}
92
Yuchen Zengf3bdbb72017-05-18 18:22:23 -070093static void grpc_ares_request_ref(grpc_ares_request *r) {
94 gpr_ref(&r->pending_queries);
95}
96
Yuchen Zeng117a3002016-11-17 19:43:36 -080097static void grpc_ares_request_unref(grpc_exec_ctx *exec_ctx,
98 grpc_ares_request *r) {
Yuchen Zenge5230b72017-03-17 15:10:49 -070099 /* If there are no pending queries, invoke on_done callback and destroy the
100 request */
Yuchen Zeng117a3002016-11-17 19:43:36 -0800101 if (gpr_unref(&r->pending_queries)) {
Yuchen Zeng15618622017-03-19 22:31:14 -0700102 /* TODO(zyc): Sort results with RFC6724 before invoking on_done. */
Yuchen Zeng117a3002016-11-17 19:43:36 -0800103 if (exec_ctx == NULL) {
Yuchen Zenge5230b72017-03-17 15:10:49 -0700104 /* A new exec_ctx is created here, as the c-ares interface does not
105 provide one in ares_host_callback. It's safe to schedule on_done with
106 the newly created exec_ctx, since the caller has been warned not to
107 acquire locks in on_done. ares_dns_resolver is using combiner to
108 protect resources needed by on_done. */
Yuchen Zeng117a3002016-11-17 19:43:36 -0800109 grpc_exec_ctx new_exec_ctx = GRPC_EXEC_CTX_INIT;
ncteisen274bbbe2017-06-08 14:57:11 -0700110 GRPC_CLOSURE_SCHED(&new_exec_ctx, r->on_done, r->error);
Yuchen Zeng117a3002016-11-17 19:43:36 -0800111 grpc_exec_ctx_finish(&new_exec_ctx);
112 } else {
ncteisen274bbbe2017-06-08 14:57:11 -0700113 GRPC_CLOSURE_SCHED(exec_ctx, r->on_done, r->error);
Yuchen Zeng117a3002016-11-17 19:43:36 -0800114 }
115 gpr_mu_destroy(&r->mu);
116 grpc_ares_ev_driver_destroy(r->ev_driver);
Yuchen Zeng117a3002016-11-17 19:43:36 -0800117 gpr_free(r);
118 }
119}
120
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700121static grpc_ares_hostbyname_request *create_hostbyname_request(
122 grpc_ares_request *parent_request, char *host, uint16_t port,
123 bool is_balancer) {
124 grpc_ares_hostbyname_request *hr =
125 gpr_zalloc(sizeof(grpc_ares_hostbyname_request));
126 hr->parent_request = parent_request;
127 hr->host = gpr_strdup(host);
128 hr->port = port;
129 hr->is_balancer = is_balancer;
130 grpc_ares_request_ref(parent_request);
131 return hr;
132}
133
134static void destroy_hostbyname_request(grpc_exec_ctx *exec_ctx,
135 grpc_ares_hostbyname_request *hr) {
136 grpc_ares_request_unref(exec_ctx, hr->parent_request);
137 gpr_free(hr->host);
138 gpr_free(hr);
139}
140
141static void on_hostbyname_done_cb(void *arg, int status, int timeouts,
142 struct hostent *hostent) {
143 grpc_ares_hostbyname_request *hr = (grpc_ares_hostbyname_request *)arg;
144 grpc_ares_request *r = hr->parent_request;
Yuchen Zeng2648a952016-11-02 18:52:25 -0700145 gpr_mu_lock(&r->mu);
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700146 if (status == ARES_SUCCESS) {
Yuchen Zeng1d0c1c42016-08-18 15:36:24 -0700147 GRPC_ERROR_UNREF(r->error);
148 r->error = GRPC_ERROR_NONE;
Yuchen Zeng912327e2016-10-25 18:27:17 -0700149 r->success = true;
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700150 grpc_lb_addresses **lb_addresses = r->lb_addrs_out;
151 if (*lb_addresses == NULL) {
152 *lb_addresses = grpc_lb_addresses_create(0, NULL);
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700153 }
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700154 size_t prev_naddr = (*lb_addresses)->num_addresses;
Yuchen Zeng912327e2016-10-25 18:27:17 -0700155 size_t i;
Yuchen Zeng9248d352016-08-16 16:33:10 -0700156 for (i = 0; hostent->h_addr_list[i] != NULL; i++) {
157 }
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700158 (*lb_addresses)->num_addresses += i;
159 (*lb_addresses)->addresses =
160 gpr_realloc((*lb_addresses)->addresses,
161 sizeof(grpc_lb_address) * (*lb_addresses)->num_addresses);
162 for (i = prev_naddr; i < (*lb_addresses)->num_addresses; i++) {
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700163 switch (hostent->h_addrtype) {
164 case AF_INET6: {
165 size_t addr_len = sizeof(struct sockaddr_in6);
166 struct sockaddr_in6 addr;
Yuchen Zeng3b4bed22017-06-04 01:41:15 -0700167 memset(&addr, 0, addr_len);
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700168 memcpy(&addr.sin6_addr, hostent->h_addr_list[i - prev_naddr],
169 sizeof(struct in6_addr));
170 addr.sin6_family = (sa_family_t)hostent->h_addrtype;
171 addr.sin6_port = hr->port;
172 grpc_lb_addresses_set_address(
173 *lb_addresses, i, &addr, addr_len,
174 hr->is_balancer /* is_balancer */,
175 hr->is_balancer ? strdup(hr->host) : NULL /* balancer_name */,
176 NULL /* user_data */);
177 char output[INET6_ADDRSTRLEN];
178 ares_inet_ntop(AF_INET6, &addr.sin6_addr, output, INET6_ADDRSTRLEN);
179 gpr_log(GPR_DEBUG,
180 "c-ares resolver gets a AF_INET6 result: \n"
181 " addr: %s\n port: %d\n sin6_scope_id: %d\n",
182 output, ntohs(hr->port), addr.sin6_scope_id);
183 break;
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700184 }
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700185 case AF_INET: {
186 size_t addr_len = sizeof(struct sockaddr_in);
187 struct sockaddr_in addr;
Yuchen Zeng3b4bed22017-06-04 01:41:15 -0700188 memset(&addr, 0, addr_len);
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700189 memcpy(&addr.sin_addr, hostent->h_addr_list[i - prev_naddr],
190 sizeof(struct in_addr));
191 addr.sin_family = (sa_family_t)hostent->h_addrtype;
192 addr.sin_port = hr->port;
193 grpc_lb_addresses_set_address(
194 *lb_addresses, i, &addr, addr_len,
195 hr->is_balancer /* is_balancer */,
196 hr->is_balancer ? strdup(hr->host) : NULL /* balancer_name */,
197 NULL /* user_data */);
198 char output[INET_ADDRSTRLEN];
199 ares_inet_ntop(AF_INET, &addr.sin_addr, output, INET_ADDRSTRLEN);
200 gpr_log(GPR_DEBUG,
201 "c-ares resolver gets a AF_INET result: \n"
202 " addr: %s\n port: %d\n",
203 output, ntohs(hr->port));
204 break;
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700205 }
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700206 }
207 }
Yuchen Zeng15a71c82016-08-17 11:50:06 -0700208 } else if (!r->success) {
Yuchen Zeng912327e2016-10-25 18:27:17 -0700209 char *error_msg;
210 gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
211 ares_strerror(status));
Yuchen Zeng0e8bc452017-03-23 14:44:14 -0700212 grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
Yuchen Zeng912327e2016-10-25 18:27:17 -0700213 gpr_free(error_msg);
Yuchen Zeng1d0c1c42016-08-18 15:36:24 -0700214 if (r->error == GRPC_ERROR_NONE) {
Yuchen Zeng912327e2016-10-25 18:27:17 -0700215 r->error = error;
216 } else {
217 r->error = grpc_error_add_child(error, r->error);
Yuchen Zeng15a71c82016-08-17 11:50:06 -0700218 }
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700219 }
Yuchen Zeng2648a952016-11-02 18:52:25 -0700220 gpr_mu_unlock(&r->mu);
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700221 destroy_hostbyname_request(NULL, hr);
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700222}
223
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700224static void on_srv_query_done_cb(void *arg, int status, int timeouts,
225 unsigned char *abuf, int alen) {
226 grpc_ares_request *r = (grpc_ares_request *)arg;
227 grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
228 gpr_log(GPR_DEBUG, "on_query_srv_done_cb");
229 if (status == ARES_SUCCESS) {
230 gpr_log(GPR_DEBUG, "on_query_srv_done_cb ARES_SUCCESS");
231 struct ares_srv_reply *reply;
232 const int parse_status = ares_parse_srv_reply(abuf, alen, &reply);
233 if (parse_status == ARES_SUCCESS) {
234 ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
235 for (struct ares_srv_reply *srv_it = reply; srv_it != NULL;
236 srv_it = srv_it->next) {
237 if (grpc_ipv6_loopback_available()) {
238 grpc_ares_hostbyname_request *hr = create_hostbyname_request(
239 r, srv_it->host, srv_it->port, true /* is_balancer */);
240 ares_gethostbyname(*channel, hr->host, AF_INET6,
241 on_hostbyname_done_cb, hr);
242 }
243 grpc_ares_hostbyname_request *hr = create_hostbyname_request(
244 r, srv_it->host, srv_it->port, true /* is_balancer */);
245 ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb,
246 hr);
247 grpc_ares_ev_driver_start(&exec_ctx, r->ev_driver);
248 }
249 }
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700250 if (reply != NULL) {
251 ares_free_data(reply);
252 }
253 } else if (!r->success) {
254 char *error_msg;
255 gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
256 ares_strerror(status));
257 grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
258 gpr_free(error_msg);
259 if (r->error == GRPC_ERROR_NONE) {
260 r->error = error;
261 } else {
262 r->error = grpc_error_add_child(error, r->error);
263 }
264 }
265 grpc_ares_request_unref(&exec_ctx, r);
266 grpc_exec_ctx_finish(&exec_ctx);
267}
268
Yuchen Zeng4ebace72017-06-05 17:24:06 -0700269static grpc_ares_request *grpc_dns_lookup_ares_impl(
Yuchen Zeng3b4bed22017-06-04 01:41:15 -0700270 grpc_exec_ctx *exec_ctx, const char *dns_server, const char *name,
271 const char *default_port, grpc_pollset_set *interested_parties,
272 grpc_closure *on_done, grpc_lb_addresses **addrs, bool check_grpclb) {
Mark D. Roth96fc54c2017-05-18 14:33:07 -0700273 grpc_error *error = GRPC_ERROR_NONE;
Yuchen Zenge5230b72017-03-17 15:10:49 -0700274 /* TODO(zyc): Enable tracing after #9603 is checked in */
275 /* if (grpc_dns_trace) {
276 gpr_log(GPR_DEBUG, "resolve_address (blocking): name=%s, default_port=%s",
277 name, default_port);
278 } */
279
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700280 /* parse name, splitting it into host and port parts */
Yuchen Zeng3ae26632016-11-09 15:53:50 -0800281 char *host;
282 char *port;
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700283 gpr_split_host_port(name, &host, &port);
284 if (host == NULL) {
Mark D. Roth96fc54c2017-05-18 14:33:07 -0700285 error = grpc_error_set_str(
Yuchen Zeng0e8bc452017-03-23 14:44:14 -0700286 GRPC_ERROR_CREATE_FROM_STATIC_STRING("unparseable host:port"),
287 GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
Yuchen Zeng3ae26632016-11-09 15:53:50 -0800288 goto error_cleanup;
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700289 } else if (port == NULL) {
290 if (default_port == NULL) {
Mark D. Roth96fc54c2017-05-18 14:33:07 -0700291 error = grpc_error_set_str(
Yuchen Zeng0e8bc452017-03-23 14:44:14 -0700292 GRPC_ERROR_CREATE_FROM_STATIC_STRING("no port in name"),
293 GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
Yuchen Zeng3ae26632016-11-09 15:53:50 -0800294 goto error_cleanup;
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700295 }
296 port = gpr_strdup(default_port);
Yuchen Zengdb53cc02016-08-10 05:04:53 -0700297 }
298
Yuchen Zeng117a3002016-11-17 19:43:36 -0800299 grpc_ares_ev_driver *ev_driver;
Mark D. Roth96fc54c2017-05-18 14:33:07 -0700300 error = grpc_ares_ev_driver_create(&ev_driver, interested_parties);
301 if (error != GRPC_ERROR_NONE) goto error_cleanup;
Yuchen Zeng117a3002016-11-17 19:43:36 -0800302
Yuchen Zeng3ae26632016-11-09 15:53:50 -0800303 grpc_ares_request *r = gpr_malloc(sizeof(grpc_ares_request));
304 gpr_mu_init(&r->mu);
305 r->ev_driver = ev_driver;
306 r->on_done = on_done;
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700307 r->lb_addrs_out = addrs;
Yuchen Zeng3ae26632016-11-09 15:53:50 -0800308 r->success = false;
309 r->error = GRPC_ERROR_NONE;
Yuchen Zengdc6b5692017-02-13 22:44:01 -0800310 ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
Mark D. Roth96fc54c2017-05-18 14:33:07 -0700311
312 // If dns_server is specified, use it.
313 if (dns_server != NULL) {
314 gpr_log(GPR_INFO, "Using DNS server %s", dns_server);
315 grpc_resolved_address addr;
316 if (grpc_parse_ipv4_hostport(dns_server, &addr, false /* log_errors */)) {
317 r->dns_server_addr.family = AF_INET;
318 memcpy(&r->dns_server_addr.addr.addr4, addr.addr, addr.len);
319 r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
320 r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
321 } else if (grpc_parse_ipv6_hostport(dns_server, &addr,
322 false /* log_errors */)) {
323 r->dns_server_addr.family = AF_INET6;
324 memcpy(&r->dns_server_addr.addr.addr6, addr.addr, addr.len);
325 r->dns_server_addr.tcp_port = grpc_sockaddr_get_port(&addr);
326 r->dns_server_addr.udp_port = grpc_sockaddr_get_port(&addr);
327 } else {
328 error = grpc_error_set_str(
329 GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
330 GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
Yuchen Zeng42e1f692017-05-21 15:34:37 -0700331 gpr_free(r);
Mark D. Roth96fc54c2017-05-18 14:33:07 -0700332 goto error_cleanup;
333 }
334 int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
335 if (status != ARES_SUCCESS) {
336 char *error_msg;
337 gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
338 ares_strerror(status));
339 error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
340 gpr_free(error_msg);
Yuchen Zeng42e1f692017-05-21 15:34:37 -0700341 gpr_free(r);
Mark D. Roth96fc54c2017-05-18 14:33:07 -0700342 goto error_cleanup;
343 }
344 }
345 // An extra reference is put here to avoid destroying the request in
346 // on_done_cb before calling grpc_ares_ev_driver_start.
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700347 gpr_ref_init(&r->pending_queries, 1);
Yuchen Zengdc6b5692017-02-13 22:44:01 -0800348 if (grpc_ipv6_loopback_available()) {
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700349 grpc_ares_hostbyname_request *hr = create_hostbyname_request(
350 r, host, strhtons(port), false /* is_balancer */);
351 ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_cb, hr);
Yuchen Zengdc6b5692017-02-13 22:44:01 -0800352 }
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700353 grpc_ares_hostbyname_request *hr = create_hostbyname_request(
354 r, host, strhtons(port), false /* is_balancer */);
355 ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb, hr);
Yuchen Zeng94c57762017-05-19 16:30:08 -0700356 if (check_grpclb) {
Yuchen Zengf3bdbb72017-05-18 18:22:23 -0700357 /* Query the SRV record */
358 grpc_ares_request_ref(r);
359 char *service_name;
360 gpr_asprintf(&service_name, "_grpclb._tcp.%s", host);
361 ares_query(*channel, service_name, ns_c_in, ns_t_srv, on_srv_query_done_cb,
362 r);
363 gpr_free(service_name);
364 }
Yuchen Zenge5230b72017-03-17 15:10:49 -0700365 /* TODO(zyc): Handle CNAME records here. */
Yuchen Zengdc6b5692017-02-13 22:44:01 -0800366 grpc_ares_ev_driver_start(exec_ctx, r->ev_driver);
367 grpc_ares_request_unref(exec_ctx, r);
Yuchen Zeng42e1f692017-05-21 15:34:37 -0700368 gpr_free(host);
369 gpr_free(port);
Yuchen Zeng3b4bed22017-06-04 01:41:15 -0700370 return r;
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700371
Yuchen Zeng3ae26632016-11-09 15:53:50 -0800372error_cleanup:
ncteisen274bbbe2017-06-08 14:57:11 -0700373 GRPC_CLOSURE_SCHED(exec_ctx, on_done, error);
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700374 gpr_free(host);
375 gpr_free(port);
Yuchen Zeng3b4bed22017-06-04 01:41:15 -0700376 return NULL;
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700377}
378
Yuchen Zeng3b4bed22017-06-04 01:41:15 -0700379grpc_ares_request *(*grpc_dns_lookup_ares)(
380 grpc_exec_ctx *exec_ctx, const char *dns_server, const char *name,
381 const char *default_port, grpc_pollset_set *interested_parties,
382 grpc_closure *on_done, grpc_lb_addresses **addrs,
383 bool check_grpclb) = grpc_dns_lookup_ares_impl;
Mark D. Roth96fc54c2017-05-18 14:33:07 -0700384
Yuchen Zeng3b4bed22017-06-04 01:41:15 -0700385void grpc_cancel_ares_request(grpc_exec_ctx *exec_ctx, grpc_ares_request *r) {
386 if (grpc_dns_lookup_ares == grpc_dns_lookup_ares_impl) {
387 grpc_ares_ev_driver_shutdown(exec_ctx, r->ev_driver);
388 }
389}
Yuchen Zeng8917aec2016-08-09 18:41:31 -0700390
Yuchen Zeng85750b02016-08-08 14:16:34 -0700391grpc_error *grpc_ares_init(void) {
Yuchen Zeng459480b2016-08-09 11:40:26 -0700392 gpr_once_init(&g_basic_init, do_basic_init);
393 gpr_mu_lock(&g_init_mu);
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700394 int status = ares_library_init(ARES_LIB_INIT_ALL);
Yuchen Zeng459480b2016-08-09 11:40:26 -0700395 gpr_mu_unlock(&g_init_mu);
396
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700397 if (status != ARES_SUCCESS) {
Yuchen Zeng912327e2016-10-25 18:27:17 -0700398 char *error_msg;
399 gpr_asprintf(&error_msg, "ares_library_init failed: %s",
400 ares_strerror(status));
Yuchen Zeng0e8bc452017-03-23 14:44:14 -0700401 grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
Yuchen Zeng912327e2016-10-25 18:27:17 -0700402 gpr_free(error_msg);
403 return error;
Yuchen Zengd4bbfc72016-08-05 10:33:16 -0700404 }
Yuchen Zeng85750b02016-08-08 14:16:34 -0700405 return GRPC_ERROR_NONE;
406}
407
Yuchen Zeng459480b2016-08-09 11:40:26 -0700408void grpc_ares_cleanup(void) {
409 gpr_mu_lock(&g_init_mu);
410 ares_library_cleanup();
411 gpr_mu_unlock(&g_init_mu);
412}
Yuchen Zeng299dd8d2016-08-16 21:40:13 -0700413
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700414/*
415 * grpc_resolve_address_ares related structs and functions
416 */
417
418typedef struct grpc_resolve_address_ares_request {
419 /** the pointer to receive the resolved addresses */
420 grpc_resolved_addresses **addrs_out;
421 /** currently resolving lb addresses */
422 grpc_lb_addresses *lb_addrs;
423 /** closure to call when the resolve_address_ares request completes */
424 grpc_closure *on_resolve_address_done;
425 /** a closure wrapping on_dns_lookup_done_cb, which should be invoked when the
426 grpc_dns_lookup_ares operation is done. */
427 grpc_closure on_dns_lookup_done;
428} grpc_resolve_address_ares_request;
429
430static void on_dns_lookup_done_cb(grpc_exec_ctx *exec_ctx, void *arg,
431 grpc_error *error) {
432 grpc_resolve_address_ares_request *r =
433 (grpc_resolve_address_ares_request *)arg;
434 grpc_resolved_addresses **resolved_addresses = r->addrs_out;
435 if (r->lb_addrs == NULL || r->lb_addrs->num_addresses == 0) {
436 *resolved_addresses = NULL;
437 } else {
438 *resolved_addresses = gpr_zalloc(sizeof(grpc_resolved_addresses));
439 (*resolved_addresses)->naddrs = r->lb_addrs->num_addresses;
440 (*resolved_addresses)->addrs = gpr_zalloc(sizeof(grpc_resolved_address) *
441 (*resolved_addresses)->naddrs);
442 for (size_t i = 0; i < (*resolved_addresses)->naddrs; i++) {
443 GPR_ASSERT(!r->lb_addrs->addresses[i].is_balancer);
444 memcpy(&(*resolved_addresses)->addrs[i],
445 &r->lb_addrs->addresses[i].address, sizeof(grpc_resolved_address));
446 }
447 }
ncteisen274bbbe2017-06-08 14:57:11 -0700448 GRPC_CLOSURE_SCHED(exec_ctx, r->on_resolve_address_done,
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700449 GRPC_ERROR_REF(error));
Yuchen Zeng4c15fac2017-05-24 16:40:20 -0700450 grpc_lb_addresses_destroy(exec_ctx, r->lb_addrs);
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700451 gpr_free(r);
452}
453
Yuchen Zeng4ebace72017-06-05 17:24:06 -0700454static void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx,
455 const char *name,
456 const char *default_port,
457 grpc_pollset_set *interested_parties,
458 grpc_closure *on_done,
459 grpc_resolved_addresses **addrs) {
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700460 grpc_resolve_address_ares_request *r =
461 gpr_zalloc(sizeof(grpc_resolve_address_ares_request));
462 r->addrs_out = addrs;
463 r->on_resolve_address_done = on_done;
ncteisen274bbbe2017-06-08 14:57:11 -0700464 GRPC_CLOSURE_INIT(&r->on_dns_lookup_done, on_dns_lookup_done_cb, r,
Yuchen Zeng3385b4f2017-05-24 11:40:20 -0700465 grpc_schedule_on_exec_ctx);
466 grpc_dns_lookup_ares(exec_ctx, NULL /* dns_server */, name, default_port,
467 interested_parties, &r->on_dns_lookup_done, &r->lb_addrs,
468 false /* check_grpclb */);
469}
470
471void (*grpc_resolve_address_ares)(
472 grpc_exec_ctx *exec_ctx, const char *name, const char *default_port,
473 grpc_pollset_set *interested_parties, grpc_closure *on_done,
474 grpc_resolved_addresses **addrs) = grpc_resolve_address_ares_impl;
475
Yuchen Zengd6b49852017-03-20 01:44:27 -0700476#endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */