aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c37
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h4
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c23
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c325
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h23
-rw-r--r--src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.c74
-rw-r--r--src/core/lib/iomgr/ev_epollsig_linux.c5
-rw-r--r--src/python/grpcio/grpc_core_dependencies.py1
8 files changed, 380 insertions, 112 deletions
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
index 578e8d697f..4080fb1770 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c
@@ -80,6 +80,8 @@ typedef struct {
grpc_combiner *combiner;
/** are we currently resolving? */
bool resolving;
+ /** the pending resolving request */
+ grpc_ares_request *pending_request;
/** which version of the result have we published? */
int published_version;
/** which version of the result is current? */
@@ -97,7 +99,7 @@ typedef struct {
gpr_backoff backoff_state;
/** currently resolving addresses */
- grpc_resolved_addresses *addresses;
+ grpc_lb_addresses *lb_addresses;
} ares_dns_resolver;
static void dns_ares_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *r);
@@ -124,6 +126,9 @@ static void dns_ares_shutdown_locked(grpc_exec_ctx *exec_ctx,
if (r->have_retry_timer) {
grpc_timer_cancel(exec_ctx, &r->retry_timer);
}
+ if (r->pending_request != NULL) {
+ grpc_cancel_ares_request(exec_ctx, r->pending_request);
+ }
if (r->next_completion != NULL) {
*r->target_result = NULL;
grpc_closure_sched(
@@ -160,19 +165,11 @@ static void dns_ares_on_resolved_locked(grpc_exec_ctx *exec_ctx, void *arg,
grpc_channel_args *result = NULL;
GPR_ASSERT(r->resolving);
r->resolving = false;
- if (r->addresses != NULL) {
- grpc_lb_addresses *addresses = grpc_lb_addresses_create(
- r->addresses->naddrs, NULL /* user_data_vtable */);
- for (size_t i = 0; i < r->addresses->naddrs; ++i) {
- grpc_lb_addresses_set_address(
- addresses, i, &r->addresses->addrs[i].addr,
- r->addresses->addrs[i].len, false /* is_balancer */,
- NULL /* balancer_name */, NULL /* user_data */);
- }
- grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(addresses);
+ r->pending_request = NULL;
+ if (r->lb_addresses != NULL) {
+ grpc_arg new_arg = grpc_lb_addresses_create_channel_arg(r->lb_addresses);
result = grpc_channel_args_copy_and_add(r->channel_args, &new_arg, 1);
- grpc_resolved_addresses_destroy(r->addresses);
- grpc_lb_addresses_destroy(exec_ctx, addresses);
+ grpc_lb_addresses_destroy(exec_ctx, r->lb_addresses);
} else {
const char *msg = grpc_error_string(error);
gpr_log(GPR_DEBUG, "dns resolution failed: %s", msg);
@@ -224,10 +221,11 @@ static void dns_ares_start_resolving_locked(grpc_exec_ctx *exec_ctx,
GRPC_RESOLVER_REF(&r->base, "dns-resolving");
GPR_ASSERT(!r->resolving);
r->resolving = true;
- r->addresses = NULL;
- grpc_dns_lookup_ares(exec_ctx, r->dns_server, r->name_to_resolve,
- r->default_port, r->interested_parties,
- &r->dns_ares_on_resolved_locked, &r->addresses);
+ r->lb_addresses = NULL;
+ r->pending_request = grpc_dns_lookup_ares(
+ exec_ctx, r->dns_server, r->name_to_resolve, r->default_port,
+ r->interested_parties, &r->dns_ares_on_resolved_locked, &r->lb_addresses,
+ true /* check_grpclb */);
}
static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
@@ -237,6 +235,7 @@ static void dns_ares_maybe_finish_next_locked(grpc_exec_ctx *exec_ctx,
*r->target_result = r->resolved_result == NULL
? NULL
: grpc_channel_args_copy(r->resolved_result);
+ gpr_log(GPR_DEBUG, "dns_ares_maybe_finish_next_locked");
grpc_closure_sched(exec_ctx, r->next_completion, GRPC_ERROR_NONE);
r->next_completion = NULL;
r->published_version = r->resolved_version;
@@ -260,10 +259,10 @@ static void dns_ares_destroy(grpc_exec_ctx *exec_ctx, grpc_resolver *gr) {
static grpc_resolver *dns_ares_create(grpc_exec_ctx *exec_ctx,
grpc_resolver_args *args,
const char *default_port) {
- // Get name from args.
+ /* Get name from args. */
const char *path = args->uri->path;
if (path[0] == '/') ++path;
- // Create resolver.
+ /* Create resolver. */
ares_dns_resolver *r = gpr_zalloc(sizeof(ares_dns_resolver));
grpc_resolver_init(&r->base, &dns_ares_resolver_vtable, args->combiner);
if (0 != strcmp(args->uri->authority, "")) {
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
index aa88940021..b45d7299e2 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h
@@ -62,5 +62,9 @@ grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver,
of ARES_ECANCELLED. */
void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver *ev_driver);
+/* Shutdown all the grpc_fds used by \a ev_driver */
+void grpc_ares_ev_driver_shutdown(grpc_exec_ctx *exec_ctx,
+ grpc_ares_ev_driver *ev_driver);
+
#endif /* GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_EV_DRIVER_H \
*/
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
index 1e4f3eb5ab..f036630f02 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
@@ -114,9 +114,12 @@ static void fd_node_destroy(grpc_exec_ctx *exec_ctx, fd_node *fdn) {
GPR_ASSERT(!fdn->writable_registered);
gpr_mu_destroy(&fdn->mu);
grpc_pollset_set_del_fd(exec_ctx, fdn->ev_driver->pollset_set, fdn->grpc_fd);
- grpc_fd_shutdown(exec_ctx, fdn->grpc_fd,
- GRPC_ERROR_CREATE_FROM_STATIC_STRING("fd node destroyed"));
- grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, NULL, "c-ares query finished");
+ /* c-ares library has closed the fd inside grpc_fd. This fd may be picked up
+ immediately by another thread, and should not be closed by the following
+ grpc_fd_orphan. To prevent this fd from being closed by grpc_fd_orphan,
+ a fd pointer is provided. */
+ int fd;
+ grpc_fd_orphan(exec_ctx, fdn->grpc_fd, NULL, &fd, "c-ares query finished");
gpr_free(fdn);
}
@@ -155,6 +158,20 @@ void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver *ev_driver) {
grpc_ares_ev_driver_unref(ev_driver);
}
+void grpc_ares_ev_driver_shutdown(grpc_exec_ctx *exec_ctx,
+ grpc_ares_ev_driver *ev_driver) {
+ gpr_mu_lock(&ev_driver->mu);
+ ev_driver->shutting_down = true;
+ fd_node *fn = ev_driver->fds;
+ while (fn != NULL) {
+ grpc_fd_shutdown(
+ exec_ctx, fn->grpc_fd,
+ GRPC_ERROR_CREATE_FROM_STATIC_STRING("grpc_ares_ev_driver_shutdown"));
+ fn = fn->next;
+ }
+ gpr_mu_unlock(&ev_driver->mu);
+}
+
// Search fd in the fd_node list head. This is an O(n) search, the max possible
// value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests.
static fd_node *pop_fd_node(fd_node **head, int fd) {
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
index e0cfd8b629..a184255745 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c
@@ -48,6 +48,7 @@
#include <grpc/support/string_util.h>
#include <grpc/support/time.h>
#include <grpc/support/useful.h>
+#include <nameser.h>
#include "src/core/ext/filters/client_channel/parse_address.h"
#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h"
@@ -60,20 +61,14 @@
static gpr_once g_basic_init = GPR_ONCE_INIT;
static gpr_mu g_init_mu;
-typedef struct grpc_ares_request {
+struct grpc_ares_request {
/** indicates the DNS server to use, if specified */
struct ares_addr_port_node dns_server_addr;
/** following members are set in grpc_resolve_address_ares_impl */
- /** host to resolve, parsed from the name to resolve */
- char *host;
- /** port to fill in sockaddr_in, parsed from the name to resolve */
- char *port;
- /** default port to use */
- char *default_port;
/** closure to call when the request completes */
grpc_closure *on_done;
/** the pointer to receive the resolved addresses */
- grpc_resolved_addresses **addrs_out;
+ grpc_lb_addresses **lb_addrs_out;
/** the evernt driver used by this request */
grpc_ares_ev_driver *ev_driver;
/** number of ongoing queries */
@@ -85,7 +80,19 @@ typedef struct grpc_ares_request {
bool success;
/** the errors explaining the request failure, set in on_done_cb */
grpc_error *error;
-} grpc_ares_request;
+};
+
+typedef struct grpc_ares_hostbyname_request {
+ /** following members are set in create_hostbyname_request */
+ /** the top-level request instance */
+ grpc_ares_request *parent_request;
+ /** host to resolve, parsed from the name to resolve */
+ char *host;
+ /** port to fill in sockaddr_in, parsed from the name to resolve */
+ uint16_t port;
+ /** is it a grpclb address */
+ bool is_balancer;
+} grpc_ares_hostbyname_request;
static void do_basic_init(void) { gpr_mu_init(&g_init_mu); }
@@ -98,6 +105,10 @@ static uint16_t strhtons(const char *port) {
return htons((unsigned short)atoi(port));
}
+static void grpc_ares_request_ref(grpc_ares_request *r) {
+ gpr_ref(&r->pending_queries);
+}
+
static void grpc_ares_request_unref(grpc_exec_ctx *exec_ctx,
grpc_ares_request *r) {
/* If there are no pending queries, invoke on_done callback and destroy the
@@ -118,67 +129,95 @@ static void grpc_ares_request_unref(grpc_exec_ctx *exec_ctx,
}
gpr_mu_destroy(&r->mu);
grpc_ares_ev_driver_destroy(r->ev_driver);
- gpr_free(r->host);
- gpr_free(r->port);
- gpr_free(r->default_port);
gpr_free(r);
}
}
-static void on_done_cb(void *arg, int status, int timeouts,
- struct hostent *hostent) {
- grpc_ares_request *r = (grpc_ares_request *)arg;
+static grpc_ares_hostbyname_request *create_hostbyname_request(
+ grpc_ares_request *parent_request, char *host, uint16_t port,
+ bool is_balancer) {
+ grpc_ares_hostbyname_request *hr =
+ gpr_zalloc(sizeof(grpc_ares_hostbyname_request));
+ hr->parent_request = parent_request;
+ hr->host = gpr_strdup(host);
+ hr->port = port;
+ hr->is_balancer = is_balancer;
+ grpc_ares_request_ref(parent_request);
+ return hr;
+}
+
+static void destroy_hostbyname_request(grpc_exec_ctx *exec_ctx,
+ grpc_ares_hostbyname_request *hr) {
+ grpc_ares_request_unref(exec_ctx, hr->parent_request);
+ gpr_free(hr->host);
+ gpr_free(hr);
+}
+
+static void on_hostbyname_done_cb(void *arg, int status, int timeouts,
+ struct hostent *hostent) {
+ grpc_ares_hostbyname_request *hr = (grpc_ares_hostbyname_request *)arg;
+ grpc_ares_request *r = hr->parent_request;
gpr_mu_lock(&r->mu);
if (status == ARES_SUCCESS) {
GRPC_ERROR_UNREF(r->error);
r->error = GRPC_ERROR_NONE;
r->success = true;
- grpc_resolved_addresses **addresses = r->addrs_out;
- if (*addresses == NULL) {
- *addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
- (*addresses)->naddrs = 0;
- (*addresses)->addrs = NULL;
+ grpc_lb_addresses **lb_addresses = r->lb_addrs_out;
+ if (*lb_addresses == NULL) {
+ *lb_addresses = grpc_lb_addresses_create(0, NULL);
}
- size_t prev_naddr = (*addresses)->naddrs;
+ size_t prev_naddr = (*lb_addresses)->num_addresses;
size_t i;
for (i = 0; hostent->h_addr_list[i] != NULL; i++) {
}
- (*addresses)->naddrs += i;
- (*addresses)->addrs =
- gpr_realloc((*addresses)->addrs,
- sizeof(grpc_resolved_address) * (*addresses)->naddrs);
- for (i = prev_naddr; i < (*addresses)->naddrs; i++) {
- memset(&(*addresses)->addrs[i], 0, sizeof(grpc_resolved_address));
- if (hostent->h_addrtype == AF_INET6) {
- (*addresses)->addrs[i].len = sizeof(struct sockaddr_in6);
- struct sockaddr_in6 *addr =
- (struct sockaddr_in6 *)&(*addresses)->addrs[i].addr;
- addr->sin6_family = (sa_family_t)hostent->h_addrtype;
- addr->sin6_port = strhtons(r->port);
-
- char output[INET6_ADDRSTRLEN];
- memcpy(&addr->sin6_addr, hostent->h_addr_list[i - prev_naddr],
- sizeof(struct in6_addr));
- ares_inet_ntop(AF_INET6, &addr->sin6_addr, output, INET6_ADDRSTRLEN);
- gpr_log(GPR_DEBUG,
- "c-ares resolver gets a AF_INET6 result: \n"
- " addr: %s\n port: %s\n sin6_scope_id: %d\n",
- output, r->port, addr->sin6_scope_id);
- } else {
- (*addresses)->addrs[i].len = sizeof(struct sockaddr_in);
- struct sockaddr_in *addr =
- (struct sockaddr_in *)&(*addresses)->addrs[i].addr;
- memcpy(&addr->sin_addr, hostent->h_addr_list[i - prev_naddr],
- sizeof(struct in_addr));
- addr->sin_family = (sa_family_t)hostent->h_addrtype;
- addr->sin_port = strhtons(r->port);
-
- char output[INET_ADDRSTRLEN];
- ares_inet_ntop(AF_INET, &addr->sin_addr, output, INET_ADDRSTRLEN);
- gpr_log(GPR_DEBUG,
- "c-ares resolver gets a AF_INET result: \n"
- " addr: %s\n port: %s\n",
- output, r->port);
+ (*lb_addresses)->num_addresses += i;
+ (*lb_addresses)->addresses =
+ gpr_realloc((*lb_addresses)->addresses,
+ sizeof(grpc_lb_address) * (*lb_addresses)->num_addresses);
+ for (i = prev_naddr; i < (*lb_addresses)->num_addresses; i++) {
+ switch (hostent->h_addrtype) {
+ case AF_INET6: {
+ size_t addr_len = sizeof(struct sockaddr_in6);
+ struct sockaddr_in6 addr;
+ memset(&addr, 0, addr_len);
+ memcpy(&addr.sin6_addr, hostent->h_addr_list[i - prev_naddr],
+ sizeof(struct in6_addr));
+ addr.sin6_family = (sa_family_t)hostent->h_addrtype;
+ addr.sin6_port = hr->port;
+ grpc_lb_addresses_set_address(
+ *lb_addresses, i, &addr, addr_len,
+ hr->is_balancer /* is_balancer */,
+ hr->is_balancer ? strdup(hr->host) : NULL /* balancer_name */,
+ NULL /* user_data */);
+ char output[INET6_ADDRSTRLEN];
+ ares_inet_ntop(AF_INET6, &addr.sin6_addr, output, INET6_ADDRSTRLEN);
+ gpr_log(GPR_DEBUG,
+ "c-ares resolver gets a AF_INET6 result: \n"
+ " addr: %s\n port: %d\n sin6_scope_id: %d\n",
+ output, ntohs(hr->port), addr.sin6_scope_id);
+ break;
+ }
+ case AF_INET: {
+ size_t addr_len = sizeof(struct sockaddr_in);
+ struct sockaddr_in addr;
+ memset(&addr, 0, addr_len);
+ memcpy(&addr.sin_addr, hostent->h_addr_list[i - prev_naddr],
+ sizeof(struct in_addr));
+ addr.sin_family = (sa_family_t)hostent->h_addrtype;
+ addr.sin_port = hr->port;
+ grpc_lb_addresses_set_address(
+ *lb_addresses, i, &addr, addr_len,
+ hr->is_balancer /* is_balancer */,
+ hr->is_balancer ? strdup(hr->host) : NULL /* balancer_name */,
+ NULL /* user_data */);
+ char output[INET_ADDRSTRLEN];
+ ares_inet_ntop(AF_INET, &addr.sin_addr, output, INET_ADDRSTRLEN);
+ gpr_log(GPR_DEBUG,
+ "c-ares resolver gets a AF_INET result: \n"
+ " addr: %s\n port: %d\n",
+ output, ntohs(hr->port));
+ break;
+ }
}
}
} else if (!r->success) {
@@ -194,14 +233,58 @@ static void on_done_cb(void *arg, int status, int timeouts,
}
}
gpr_mu_unlock(&r->mu);
- grpc_ares_request_unref(NULL, r);
+ destroy_hostbyname_request(NULL, hr);
+}
+
+static void on_srv_query_done_cb(void *arg, int status, int timeouts,
+ unsigned char *abuf, int alen) {
+ grpc_ares_request *r = (grpc_ares_request *)arg;
+ grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+ gpr_log(GPR_DEBUG, "on_query_srv_done_cb");
+ if (status == ARES_SUCCESS) {
+ gpr_log(GPR_DEBUG, "on_query_srv_done_cb ARES_SUCCESS");
+ struct ares_srv_reply *reply;
+ const int parse_status = ares_parse_srv_reply(abuf, alen, &reply);
+ if (parse_status == ARES_SUCCESS) {
+ ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
+ for (struct ares_srv_reply *srv_it = reply; srv_it != NULL;
+ srv_it = srv_it->next) {
+ if (grpc_ipv6_loopback_available()) {
+ grpc_ares_hostbyname_request *hr = create_hostbyname_request(
+ r, srv_it->host, srv_it->port, true /* is_balancer */);
+ ares_gethostbyname(*channel, hr->host, AF_INET6,
+ on_hostbyname_done_cb, hr);
+ }
+ grpc_ares_hostbyname_request *hr = create_hostbyname_request(
+ r, srv_it->host, srv_it->port, true /* is_balancer */);
+ ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb,
+ hr);
+ grpc_ares_ev_driver_start(&exec_ctx, r->ev_driver);
+ }
+ }
+ if (reply != NULL) {
+ ares_free_data(reply);
+ }
+ } else if (!r->success) {
+ char *error_msg;
+ gpr_asprintf(&error_msg, "C-ares status is not ARES_SUCCESS: %s",
+ ares_strerror(status));
+ grpc_error *error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
+ gpr_free(error_msg);
+ if (r->error == GRPC_ERROR_NONE) {
+ r->error = error;
+ } else {
+ r->error = grpc_error_add_child(error, r->error);
+ }
+ }
+ grpc_ares_request_unref(&exec_ctx, r);
+ grpc_exec_ctx_finish(&exec_ctx);
}
-void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
- const char *name, const char *default_port,
- grpc_pollset_set *interested_parties,
- grpc_closure *on_done,
- grpc_resolved_addresses **addrs) {
+static grpc_ares_request *grpc_dns_lookup_ares_impl(
+ grpc_exec_ctx *exec_ctx, 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) {
grpc_error *error = GRPC_ERROR_NONE;
/* TODO(zyc): Enable tracing after #9603 is checked in */
/* if (grpc_dns_trace) {
@@ -236,10 +319,7 @@ void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
gpr_mu_init(&r->mu);
r->ev_driver = ev_driver;
r->on_done = on_done;
- r->addrs_out = addrs;
- r->default_port = gpr_strdup(default_port);
- r->port = port;
- r->host = host;
+ r->lb_addrs_out = addrs;
r->success = false;
r->error = GRPC_ERROR_NONE;
ares_channel *channel = grpc_ares_ev_driver_get_channel(r->ev_driver);
@@ -263,6 +343,7 @@ void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
error = grpc_error_set_str(
GRPC_ERROR_CREATE_FROM_STATIC_STRING("cannot parse authority"),
GRPC_ERROR_STR_TARGET_ADDRESS, grpc_slice_from_copied_string(name));
+ gpr_free(r);
goto error_cleanup;
}
int status = ares_set_servers_ports(*channel, &r->dns_server_addr);
@@ -272,41 +353,55 @@ void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
ares_strerror(status));
error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(error_msg);
gpr_free(error_msg);
+ gpr_free(r);
goto error_cleanup;
}
}
// An extra reference is put here to avoid destroying the request in
// on_done_cb before calling grpc_ares_ev_driver_start.
- gpr_ref_init(&r->pending_queries, 2);
+ gpr_ref_init(&r->pending_queries, 1);
if (grpc_ipv6_loopback_available()) {
- gpr_ref(&r->pending_queries);
- ares_gethostbyname(*channel, r->host, AF_INET6, on_done_cb, r);
+ grpc_ares_hostbyname_request *hr = create_hostbyname_request(
+ r, host, strhtons(port), false /* is_balancer */);
+ ares_gethostbyname(*channel, hr->host, AF_INET6, on_hostbyname_done_cb, hr);
+ }
+ grpc_ares_hostbyname_request *hr = create_hostbyname_request(
+ r, host, strhtons(port), false /* is_balancer */);
+ ares_gethostbyname(*channel, hr->host, AF_INET, on_hostbyname_done_cb, hr);
+ if (check_grpclb) {
+ /* Query the SRV record */
+ grpc_ares_request_ref(r);
+ char *service_name;
+ gpr_asprintf(&service_name, "_grpclb._tcp.%s", host);
+ ares_query(*channel, service_name, ns_c_in, ns_t_srv, on_srv_query_done_cb,
+ r);
+ gpr_free(service_name);
}
- ares_gethostbyname(*channel, r->host, AF_INET, on_done_cb, r);
/* TODO(zyc): Handle CNAME records here. */
grpc_ares_ev_driver_start(exec_ctx, r->ev_driver);
grpc_ares_request_unref(exec_ctx, r);
- return;
+ gpr_free(host);
+ gpr_free(port);
+ return r;
error_cleanup:
grpc_closure_sched(exec_ctx, on_done, error);
gpr_free(host);
gpr_free(port);
+ return NULL;
}
-void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx, const char *name,
- const char *default_port,
- grpc_pollset_set *interested_parties,
- grpc_closure *on_done,
- grpc_resolved_addresses **addrs) {
- grpc_dns_lookup_ares(exec_ctx, NULL /* dns_server */, name, default_port,
- interested_parties, on_done, addrs);
-}
+grpc_ares_request *(*grpc_dns_lookup_ares)(
+ grpc_exec_ctx *exec_ctx, 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) = grpc_dns_lookup_ares_impl;
-void (*grpc_resolve_address_ares)(
- grpc_exec_ctx *exec_ctx, const char *name, const char *default_port,
- grpc_pollset_set *interested_parties, grpc_closure *on_done,
- grpc_resolved_addresses **addrs) = grpc_resolve_address_ares_impl;
+void grpc_cancel_ares_request(grpc_exec_ctx *exec_ctx, grpc_ares_request *r) {
+ if (grpc_dns_lookup_ares == grpc_dns_lookup_ares_impl) {
+ grpc_ares_ev_driver_shutdown(exec_ctx, r->ev_driver);
+ }
+}
grpc_error *grpc_ares_init(void) {
gpr_once_init(&g_basic_init, do_basic_init);
@@ -331,4 +426,66 @@ void grpc_ares_cleanup(void) {
gpr_mu_unlock(&g_init_mu);
}
+/*
+ * grpc_resolve_address_ares related structs and functions
+ */
+
+typedef struct grpc_resolve_address_ares_request {
+ /** the pointer to receive the resolved addresses */
+ grpc_resolved_addresses **addrs_out;
+ /** currently resolving lb addresses */
+ grpc_lb_addresses *lb_addrs;
+ /** closure to call when the resolve_address_ares request completes */
+ grpc_closure *on_resolve_address_done;
+ /** a closure wrapping on_dns_lookup_done_cb, which should be invoked when the
+ grpc_dns_lookup_ares operation is done. */
+ grpc_closure on_dns_lookup_done;
+} grpc_resolve_address_ares_request;
+
+static void on_dns_lookup_done_cb(grpc_exec_ctx *exec_ctx, void *arg,
+ grpc_error *error) {
+ grpc_resolve_address_ares_request *r =
+ (grpc_resolve_address_ares_request *)arg;
+ grpc_resolved_addresses **resolved_addresses = r->addrs_out;
+ if (r->lb_addrs == NULL || r->lb_addrs->num_addresses == 0) {
+ *resolved_addresses = NULL;
+ } else {
+ *resolved_addresses = gpr_zalloc(sizeof(grpc_resolved_addresses));
+ (*resolved_addresses)->naddrs = r->lb_addrs->num_addresses;
+ (*resolved_addresses)->addrs = gpr_zalloc(sizeof(grpc_resolved_address) *
+ (*resolved_addresses)->naddrs);
+ for (size_t i = 0; i < (*resolved_addresses)->naddrs; i++) {
+ GPR_ASSERT(!r->lb_addrs->addresses[i].is_balancer);
+ memcpy(&(*resolved_addresses)->addrs[i],
+ &r->lb_addrs->addresses[i].address, sizeof(grpc_resolved_address));
+ }
+ }
+ grpc_closure_sched(exec_ctx, r->on_resolve_address_done,
+ GRPC_ERROR_REF(error));
+ grpc_lb_addresses_destroy(exec_ctx, r->lb_addrs);
+ gpr_free(r);
+}
+
+static void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx,
+ const char *name,
+ const char *default_port,
+ grpc_pollset_set *interested_parties,
+ grpc_closure *on_done,
+ grpc_resolved_addresses **addrs) {
+ grpc_resolve_address_ares_request *r =
+ gpr_zalloc(sizeof(grpc_resolve_address_ares_request));
+ r->addrs_out = addrs;
+ r->on_resolve_address_done = on_done;
+ grpc_closure_init(&r->on_dns_lookup_done, on_dns_lookup_done_cb, r,
+ grpc_schedule_on_exec_ctx);
+ grpc_dns_lookup_ares(exec_ctx, NULL /* dns_server */, name, default_port,
+ interested_parties, &r->on_dns_lookup_done, &r->lb_addrs,
+ false /* check_grpclb */);
+}
+
+void (*grpc_resolve_address_ares)(
+ grpc_exec_ctx *exec_ctx, const char *name, const char *default_port,
+ grpc_pollset_set *interested_parties, grpc_closure *on_done,
+ grpc_resolved_addresses **addrs) = grpc_resolve_address_ares_impl;
+
#endif /* GRPC_ARES == 1 && !defined(GRPC_UV) */
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
index 84fd7fcbd6..4a8374a192 100644
--- a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h
@@ -34,11 +34,14 @@
#ifndef GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H
#define GRPC_CORE_EXT_FILTERS_CLIENT_CHANNEL_RESOLVER_DNS_C_ARES_GRPC_ARES_WRAPPER_H
+#include "src/core/ext/filters/client_channel/lb_policy_factory.h"
#include "src/core/lib/iomgr/exec_ctx.h"
#include "src/core/lib/iomgr/iomgr.h"
#include "src/core/lib/iomgr/polling_entity.h"
#include "src/core/lib/iomgr/resolve_address.h"
+typedef struct grpc_ares_request grpc_ares_request;
+
/* Asynchronously resolve addr. Use \a default_port if a port isn't designated
in addr, otherwise use the port in addr. grpc_ares_init() must be called at
least once before this function. \a on_done may be called directly in this
@@ -51,11 +54,21 @@ extern void (*grpc_resolve_address_ares)(grpc_exec_ctx *exec_ctx,
grpc_closure *on_done,
grpc_resolved_addresses **addresses);
-void grpc_dns_lookup_ares(grpc_exec_ctx *exec_ctx, const char *dns_server,
- const char *addr, const char *default_port,
- grpc_pollset_set *interested_parties,
- grpc_closure *on_done,
- grpc_resolved_addresses **addresses);
+/* Asynchronously resolve addr. It will try to resolve grpclb SRV records in
+ addition to the normal address records. For normal address records, it uses
+ \a default_port if a port isn't designated in \a addr, otherwise it uses the
+ port in \a addr. grpc_ares_init() must be called at least once before this
+ function. \a on_done may be called directly in this function without being
+ scheduled with \a exec_ctx, it must not try to acquire locks that are being
+ held by the caller. */
+extern grpc_ares_request *(*grpc_dns_lookup_ares)(
+ grpc_exec_ctx *exec_ctx, const char *dns_server, const char *addr,
+ const char *default_port, grpc_pollset_set *interested_parties,
+ grpc_closure *on_done, grpc_lb_addresses **addresses, bool check_grpclb);
+
+/* Cancel the pending grpc_ares_request \a request */
+void grpc_cancel_ares_request(grpc_exec_ctx *exec_ctx,
+ grpc_ares_request *request);
/* Initialize gRPC ares wrapper. Must be called at least once before
grpc_resolve_address_ares(). */
diff --git a/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.c b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.c
new file mode 100644
index 0000000000..5c15e3bdf5
--- /dev/null
+++ b/src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.c
@@ -0,0 +1,74 @@
+/*
+ *
+ * Copyright 2017, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+#if GRPC_ARES != 1 || defined(GRPC_UV)
+
+#include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h"
+
+struct grpc_ares_request {
+ char val;
+};
+
+static grpc_ares_request *grpc_dns_lookup_ares_impl(
+ grpc_exec_ctx *exec_ctx, 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) {
+ return NULL;
+}
+
+grpc_ares_request *(*grpc_dns_lookup_ares)(
+ grpc_exec_ctx *exec_ctx, 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) = grpc_dns_lookup_ares_impl;
+
+void grpc_cancel_ares_request(grpc_exec_ctx *exec_ctx, grpc_ares_request *r) {}
+
+grpc_error *grpc_ares_init(void) { return GRPC_ERROR_NONE; }
+
+void grpc_ares_cleanup(void) {}
+
+static void grpc_resolve_address_ares_impl(grpc_exec_ctx *exec_ctx,
+ const char *name,
+ const char *default_port,
+ grpc_pollset_set *interested_parties,
+ grpc_closure *on_done,
+ grpc_resolved_addresses **addrs) {}
+
+void (*grpc_resolve_address_ares)(
+ grpc_exec_ctx *exec_ctx, const char *name, const char *default_port,
+ grpc_pollset_set *interested_parties, grpc_closure *on_done,
+ grpc_resolved_addresses **addrs) = grpc_resolve_address_ares_impl;
+
+#endif /* GRPC_ARES != 1 || defined(GRPC_UV) */
diff --git a/src/core/lib/iomgr/ev_epollsig_linux.c b/src/core/lib/iomgr/ev_epollsig_linux.c
index 92c555b7ea..d5534ec397 100644
--- a/src/core/lib/iomgr/ev_epollsig_linux.c
+++ b/src/core/lib/iomgr/ev_epollsig_linux.c
@@ -1047,7 +1047,10 @@ static void fd_orphan(grpc_exec_ctx *exec_ctx, grpc_fd *fd,
unhappy. */
PI_UNREF(exec_ctx, unref_pi, "fd_orphan");
}
- GRPC_LOG_IF_ERROR("fd_orphan", GRPC_ERROR_REF(error));
+ if (error != GRPC_ERROR_NONE) {
+ const char *msg = grpc_error_string(error);
+ gpr_log(GPR_DEBUG, "fd_orphan: %s", msg);
+ }
GRPC_ERROR_UNREF(error);
}
diff --git a/src/python/grpcio/grpc_core_dependencies.py b/src/python/grpcio/grpc_core_dependencies.py
index 5f8075467d..f6578dbd11 100644
--- a/src/python/grpcio/grpc_core_dependencies.py
+++ b/src/python/grpcio/grpc_core_dependencies.py
@@ -301,6 +301,7 @@ CORE_SOURCE_FILES = [
'src/core/ext/filters/client_channel/resolver/dns/c_ares/dns_resolver_ares.c',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c',
'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.c',
+ 'src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper_fallback.c',
'src/core/ext/filters/client_channel/resolver/dns/native/dns_resolver.c',
'src/core/ext/filters/client_channel/resolver/sockaddr/sockaddr_resolver.c',
'src/core/ext/filters/load_reporting/load_reporting.c',