From 9248d35d12a82effb997e8d0e30962fc8b27b9f4 Mon Sep 17 00:00:00 2001
From: Yuchen Zeng <zyc@google.com>
Date: Tue, 16 Aug 2016 16:33:10 -0700
Subject: [PATCH] Add dual stack support

---
 src/c-ares/gen_build_yaml.py                  |  1 -
 .../resolver/dns/c_ares/grpc_ares_ev_driver.h |  1 +
 .../dns/c_ares/grpc_ares_ev_driver_posix.c    |  4 ++
 .../resolver/dns/c_ares/grpc_ares_wrapper.c   | 57 ++++++++++++-------
 4 files changed, 42 insertions(+), 21 deletions(-)

diff --git a/src/c-ares/gen_build_yaml.py b/src/c-ares/gen_build_yaml.py
index 1081b4b311..33ad44eebf 100755
--- a/src/c-ares/gen_build_yaml.py
+++ b/src/c-ares/gen_build_yaml.py
@@ -136,7 +136,6 @@ try:
         "third_party/c-ares/ares_strdup.h",
         "third_party/c-ares/ares_version.h",
         "third_party/c-ares/bitncmp.h",
-        "third_party/c-ares/selectbridge.h",
         "third_party/c-ares/setup_once.h",
         "src/c-ares/ares_build.h",
         "src/c-ares/config_linux/ares_config.h",
diff --git a/src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h b/src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h
index e874853319..813d5aa6d7 100644
--- a/src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h
+++ b/src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h
@@ -45,6 +45,7 @@ void grpc_ares_notify_on_event(grpc_exec_ctx *exec_ctx,
                                grpc_ares_ev_driver *ev_driver);
 void grpc_ares_gethostbyname(grpc_ares_ev_driver *ev_driver, const char *host,
                              ares_host_callback on_done_cb, void *arg);
+ares_channel *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver);
 
 grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver,
                                        grpc_pollset_set *pollset_set);
diff --git a/src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c b/src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
index 5c57f067fb..eea346e575 100644
--- a/src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
+++ b/src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver_posix.c
@@ -126,6 +126,10 @@ void grpc_ares_gethostbyname(grpc_ares_ev_driver *ev_driver, const char *host,
   ares_gethostbyname(ev_driver->channel, host, AF_UNSPEC, on_done_cb, arg);
 }
 
+ares_channel *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver) {
+  return &ev_driver->channel;
+}
+
 void grpc_ares_notify_on_event(grpc_exec_ctx *exec_ctx,
                                grpc_ares_ev_driver *ev_driver) {
   size_t i;
diff --git a/src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c b/src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c
index ef9ec96dc6..203c98a50e 100644
--- a/src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c
+++ b/src/core/ext/resolver/dns/c_ares/grpc_ares_wrapper.c
@@ -77,6 +77,7 @@ struct grpc_ares_request {
   grpc_resolved_addresses **addrs_out;
   grpc_closure request_closure;
   void *arg;
+  int pending_quries;
   grpc_ares_ev_driver *ev_driver;
 };
 
@@ -101,30 +102,37 @@ static void on_done_cb(void *arg, int status, int timeouts,
   gpr_log(GPR_ERROR, "status: %s", r->name);
   grpc_resolved_addresses **addresses = r->addrs_out;
   size_t i;
+  size_t prev_naddr;
 
   if (status == ARES_SUCCESS) {
     gpr_log(GPR_ERROR, "status ARES_SUCCESS");
     err = GRPC_ERROR_NONE;
-    *addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
-    for ((*addresses)->naddrs = 0;
-         hostent->h_addr_list[(*addresses)->naddrs] != NULL;
-         (*addresses)->naddrs++) {
+    if (*addresses == NULL) {
+      *addresses = gpr_malloc(sizeof(grpc_resolved_addresses));
+      (*addresses)->naddrs = 0;
+      (*addresses)->addrs = NULL;
+    }
+
+    prev_naddr = (*addresses)->naddrs;
+    for (i = 0; hostent->h_addr_list[i] != NULL; i++) {
     }
+    (*addresses)->naddrs += i;
+
     gpr_log(GPR_ERROR, "naddr: %" PRIuPTR, (*addresses)->naddrs);
     (*addresses)->addrs =
-        gpr_malloc(sizeof(grpc_resolved_address) * (*addresses)->naddrs);
-    for (i = 0; i < (*addresses)->naddrs; i++) {
+        gpr_realloc((*addresses)->addrs,
+                    sizeof(grpc_resolved_address) * (*addresses)->naddrs);
+
+    for (i = prev_naddr; i < (*addresses)->naddrs; i++) {
       if (hostent->h_addrtype == AF_INET6) {
         char output[INET6_ADDRSTRLEN];
         gpr_log(GPR_ERROR, "AF_INET6");
         struct sockaddr_in6 *addr;
 
         (*addresses)->addrs[i].len = sizeof(struct sockaddr_in6);
-        // &(*addresses)->addrs[i].addr =
-        // gpr_malloc((*addresses)->addrs[i].len);
         addr = (struct sockaddr_in6 *)&(*addresses)->addrs[i].addr;
 
-        memcpy(&addr->sin6_addr, hostent->h_addr_list[i],
+        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_ERROR, "addr: %s", output);
@@ -132,13 +140,16 @@ static void on_done_cb(void *arg, int status, int timeouts,
         addr->sin6_family = (sa_family_t)hostent->h_addrtype;
         addr->sin6_port = htons((unsigned short)atoi(r->port));
       } else {
+        char output[INET_ADDRSTRLEN];
         gpr_log(GPR_ERROR, "AF_INET");
         struct sockaddr_in *addr;
+
         (*addresses)->addrs[i].len = sizeof(struct sockaddr_in);
-        // &(*addresses)->addrs[i].addr =
-        // gpr_malloc((*addresses)->addrs[i].len);
         addr = (struct sockaddr_in *)&(*addresses)->addrs[i].addr;
-        memcpy(&addr->sin_addr, hostent->h_addr_list[i],
+        ares_inet_ntop(AF_INET, &addr->sin_addr, output, INET_ADDRSTRLEN);
+        gpr_log(GPR_ERROR, "addr: %s", output);
+        gpr_log(GPR_ERROR, "port: %s", r->port);
+        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 = htons((unsigned short)atoi(r->port));
@@ -155,22 +166,27 @@ static void on_done_cb(void *arg, int status, int timeouts,
             GRPC_ERROR_STR_SYSCALL, "getaddrinfo"),
         GRPC_ERROR_STR_TARGET_ADDRESS, r->name);
   }
+  if (--r->pending_quries == 0) {
+    grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
+    grpc_exec_ctx_sched(&exec_ctx, r->on_done, err, NULL);
+    grpc_exec_ctx_flush(&exec_ctx);
+    grpc_exec_ctx_finish(&exec_ctx);
 
-  grpc_exec_ctx exec_ctx = GRPC_EXEC_CTX_INIT;
-  grpc_exec_ctx_sched(&exec_ctx, r->on_done, err, NULL);
-  grpc_exec_ctx_flush(&exec_ctx);
-  grpc_exec_ctx_finish(&exec_ctx);
-
-  destroy_request(r);
-  gpr_free(r);
+    destroy_request(r);
+    gpr_free(r);
+  }
 }
 
 static void request_resolving_address(grpc_exec_ctx *exec_ctx, void *arg,
                                       grpc_error *error) {
   grpc_ares_request *r = (grpc_ares_request *)arg;
   grpc_ares_ev_driver *ev_driver = r->ev_driver;
+  ares_channel *channel = grpc_ares_ev_driver_get_channel(ev_driver);
   gpr_log(GPR_ERROR, "before ares_gethostbyname %s", r->host);
-  grpc_ares_gethostbyname(r->ev_driver, r->host, on_done_cb, r);
+  r->pending_quries = 2;
+  ares_gethostbyname(*channel, r->host, AF_INET, on_done_cb, r);
+  ares_gethostbyname(*channel, r->host, AF_INET6, on_done_cb, r);
+  // grpc_ares_gethostbyname(r->ev_driver, r->host, on_dones_cb, r);
   gpr_log(GPR_ERROR, "before ares_getsock");
   grpc_ares_notify_on_event(exec_ctx, ev_driver);
   gpr_log(GPR_ERROR, "eof resolve_address_impl");
@@ -269,6 +285,7 @@ grpc_ares_request *grpc_resolve_address_ares_impl(
     r->default_port = gpr_strdup(default_port);
     r->port = gpr_strdup(port);
     r->host = gpr_strdup(host);
+    r->pending_quries = 0;
     grpc_closure_init(&r->request_closure, request_resolving_address, r);
     grpc_exec_ctx_sched(exec_ctx, &r->request_closure, GRPC_ERROR_NONE, NULL);
   }
-- 
GitLab