Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
| 3 | * Copyright 2016, Google Inc. |
| 4 | * All rights reserved. |
| 5 | * |
| 6 | * Redistribution and use in source and binary forms, with or without |
| 7 | * modification, are permitted provided that the following conditions are |
| 8 | * met: |
| 9 | * |
| 10 | * * Redistributions of source code must retain the above copyright |
| 11 | * notice, this list of conditions and the following disclaimer. |
| 12 | * * Redistributions in binary form must reproduce the above |
| 13 | * copyright notice, this list of conditions and the following disclaimer |
| 14 | * in the documentation and/or other materials provided with the |
| 15 | * distribution. |
| 16 | * * Neither the name of Google Inc. nor the names of its |
| 17 | * contributors may be used to endorse or promote products derived from |
| 18 | * this software without specific prior written permission. |
| 19 | * |
| 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| 23 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| 24 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| 25 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| 26 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 30 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 31 | * |
| 32 | */ |
| 33 | #include <grpc/support/port_platform.h> |
Yuchen Zeng | 299dd8d | 2016-08-16 21:40:13 -0700 | [diff] [blame] | 34 | #ifndef GRPC_NATIVE_ADDRESS_RESOLVE |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 35 | #ifdef GPR_POSIX_SOCKET |
| 36 | |
| 37 | #include "src/core/ext/resolver/dns/c_ares/grpc_ares_ev_driver.h" |
| 38 | |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 39 | #include "src/core/lib/iomgr/ev_posix.h" |
| 40 | #include "src/core/lib/iomgr/sockaddr.h" |
| 41 | |
| 42 | #include <ares.h> |
| 43 | #include <grpc/support/alloc.h> |
| 44 | #include <grpc/support/log.h> |
| 45 | #include <grpc/support/string_util.h> |
| 46 | #include <grpc/support/time.h> |
| 47 | #include <grpc/support/useful.h> |
| 48 | #include "src/core/lib/iomgr/iomgr_internal.h" |
| 49 | #include "src/core/lib/iomgr/sockaddr_utils.h" |
| 50 | #include "src/core/lib/iomgr/unix_sockets_posix.h" |
| 51 | #include "src/core/lib/support/block_annotate.h" |
| 52 | #include "src/core/lib/support/string.h" |
| 53 | |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 54 | typedef struct fd_node { |
Yuchen Zeng | a418ed2 | 2016-08-08 17:24:33 -0700 | [diff] [blame] | 55 | grpc_fd *grpc_fd; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 56 | struct fd_node *next; |
| 57 | } fd_node; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 58 | |
| 59 | struct grpc_ares_ev_driver { |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 60 | /** the ares_channel owned by this event driver */ |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 61 | ares_channel channel; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 62 | /** a closure wrapping the driver_cb, which should be invoked each time the ev |
| 63 | driver gets notified by fds. */ |
| 64 | grpc_closure driver_closure; |
| 65 | /** pollset set for driving the IO events of the channel */ |
| 66 | grpc_pollset_set *pollset_set; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 67 | /** has grpc_ares_ev_driver_destroy been called on this event driver? */ |
| 68 | bool closing; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 69 | /** an array of ares sockets that the ares channel owned by this event driver |
| 70 | is currently using */ |
| 71 | ares_socket_t socks[ARES_GETSOCK_MAXNUM]; |
| 72 | /** a bitmask that can tell if an ares socket in the socks array is readable |
| 73 | or/and writable */ |
| 74 | int socks_bitmask; |
| 75 | /** a list of grpc_fd that this event driver is currently using. */ |
| 76 | fd_node *fds; |
Yuchen Zeng | c87b77f | 2016-10-03 11:36:36 -0700 | [diff] [blame] | 77 | |
Yuchen Zeng | 43aa9a1 | 2016-10-25 10:44:39 -0700 | [diff] [blame] | 78 | /** mutex guarding the rest of the state */ |
Yuchen Zeng | c87b77f | 2016-10-03 11:36:36 -0700 | [diff] [blame] | 79 | gpr_mu mu; |
| 80 | /** is this event driver currently working? */ |
| 81 | bool working; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 82 | }; |
| 83 | |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 84 | static void grpc_ares_notify_on_event(grpc_exec_ctx *exec_ctx, |
| 85 | grpc_ares_ev_driver *ev_driver); |
Yuchen Zeng | 213d784 | 2016-08-26 19:28:16 -0700 | [diff] [blame] | 86 | |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 87 | grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver, |
| 88 | grpc_pollset_set *pollset_set) { |
| 89 | int status; |
| 90 | *ev_driver = gpr_malloc(sizeof(grpc_ares_ev_driver)); |
| 91 | status = ares_init(&(*ev_driver)->channel); |
| 92 | if (status != ARES_SUCCESS) { |
Yuchen Zeng | 43aa9a1 | 2016-10-25 10:44:39 -0700 | [diff] [blame] | 93 | char *err_msg; |
| 94 | gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s", |
| 95 | ares_strerror(status)); |
| 96 | grpc_error *err = GRPC_ERROR_CREATE(err_msg); |
| 97 | gpr_free(err_msg); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 98 | gpr_free(*ev_driver); |
Yuchen Zeng | 43aa9a1 | 2016-10-25 10:44:39 -0700 | [diff] [blame] | 99 | return err; |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 100 | } |
Yuchen Zeng | 213d784 | 2016-08-26 19:28:16 -0700 | [diff] [blame] | 101 | gpr_mu_init(&(*ev_driver)->mu); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 102 | (*ev_driver)->pollset_set = pollset_set; |
| 103 | (*ev_driver)->fds = NULL; |
| 104 | (*ev_driver)->closing = false; |
Yuchen Zeng | ffbc167 | 2016-10-03 11:29:22 -0700 | [diff] [blame] | 105 | (*ev_driver)->working = false; |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 106 | return GRPC_ERROR_NONE; |
| 107 | } |
| 108 | |
| 109 | void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver *ev_driver) { |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 110 | ev_driver->closing = true; |
| 111 | } |
| 112 | |
Yuchen Zeng | 3026b6c | 2016-10-03 16:03:29 -0700 | [diff] [blame] | 113 | // Search fd in the fd_node list head. This is an O(n) search, the max possible |
Yuchen Zeng | 4eedcde | 2016-10-11 11:23:37 -0700 | [diff] [blame] | 114 | // value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 3 in our tests. |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 115 | static fd_node *get_fd(fd_node **head, int fd) { |
| 116 | fd_node dummy_head; |
| 117 | fd_node *node; |
| 118 | fd_node *ret; |
Yuchen Zeng | 925b688 | 2016-08-24 18:42:25 -0700 | [diff] [blame] | 119 | |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 120 | dummy_head.next = *head; |
| 121 | node = &dummy_head; |
| 122 | while (node->next != NULL) { |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 123 | if (grpc_fd_wrapped_fd(node->next->grpc_fd) == fd) { |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 124 | ret = node->next; |
| 125 | node->next = node->next->next; |
| 126 | *head = dummy_head.next; |
| 127 | return ret; |
| 128 | } |
Yuchen Zeng | c87b77f | 2016-10-03 11:36:36 -0700 | [diff] [blame] | 129 | node = node->next; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 130 | } |
| 131 | return NULL; |
| 132 | } |
| 133 | |
Yuchen Zeng | 3026b6c | 2016-10-03 16:03:29 -0700 | [diff] [blame] | 134 | // Process each file descriptor that may wake this callback up. |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 135 | static void driver_cb(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { |
| 136 | grpc_ares_ev_driver *d = arg; |
| 137 | size_t i; |
Yuchen Zeng | 925b688 | 2016-08-24 18:42:25 -0700 | [diff] [blame] | 138 | |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 139 | if (error == GRPC_ERROR_NONE) { |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 140 | for (i = 0; i < ARES_GETSOCK_MAXNUM; i++) { |
Yuchen Zeng | 43aa9a1 | 2016-10-25 10:44:39 -0700 | [diff] [blame] | 141 | ares_socket_t read_fd = ARES_GETSOCK_READABLE(d->socks_bitmask, i) |
| 142 | ? d->socks[i] |
| 143 | : ARES_SOCKET_BAD; |
| 144 | ares_socket_t write_fd = ARES_GETSOCK_WRITABLE(d->socks_bitmask, i) |
| 145 | ? d->socks[i] |
| 146 | : ARES_SOCKET_BAD; |
| 147 | ares_process_fd(d->channel, read_fd, write_fd); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 148 | } |
Yuchen Zeng | 4dd1891 | 2016-08-24 17:17:17 -0700 | [diff] [blame] | 149 | } else { |
Yuchen Zeng | 912327e | 2016-10-25 18:27:17 -0700 | [diff] [blame^] | 150 | // error != GRPC_ERROR_NONE means the waiting timed out or the fd has been |
| 151 | // shutdown. In this case, the event driver cancels all the ongoing requests |
| 152 | // that are using its channel. The fds get cleaned up in the next |
| 153 | // grpc_ares_notify_on_event. |
Yuchen Zeng | 4dd1891 | 2016-08-24 17:17:17 -0700 | [diff] [blame] | 154 | ares_cancel(d->channel); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 155 | } |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 156 | grpc_ares_notify_on_event(exec_ctx, d); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 157 | } |
| 158 | |
Yuchen Zeng | 9248d35 | 2016-08-16 16:33:10 -0700 | [diff] [blame] | 159 | ares_channel *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver) { |
| 160 | return &ev_driver->channel; |
| 161 | } |
| 162 | |
Yuchen Zeng | 3026b6c | 2016-10-03 16:03:29 -0700 | [diff] [blame] | 163 | // Get the file descriptors used by the ev_driver's ares channel, register |
| 164 | // driver_closure with these filedescriptors. |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 165 | static void grpc_ares_notify_on_event(grpc_exec_ctx *exec_ctx, |
| 166 | grpc_ares_ev_driver *ev_driver) { |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 167 | size_t i; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 168 | fd_node *new_list = NULL; |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 169 | if (!ev_driver->closing) { |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 170 | ev_driver->socks_bitmask = |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 171 | ares_getsock(ev_driver->channel, ev_driver->socks, ARES_GETSOCK_MAXNUM); |
| 172 | grpc_closure_init(&ev_driver->driver_closure, driver_cb, ev_driver); |
| 173 | for (i = 0; i < ARES_GETSOCK_MAXNUM; i++) { |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 174 | if (ARES_GETSOCK_READABLE(ev_driver->socks_bitmask, i) || |
| 175 | ARES_GETSOCK_WRITABLE(ev_driver->socks_bitmask, i)) { |
| 176 | fd_node *fdn = get_fd(&ev_driver->fds, ev_driver->socks[i]); |
Yuchen Zeng | 912327e | 2016-10-25 18:27:17 -0700 | [diff] [blame^] | 177 | if (fdn == NULL) { |
Yuchen Zeng | d0725d7 | 2016-08-26 17:27:32 -0700 | [diff] [blame] | 178 | char *fd_name; |
| 179 | gpr_asprintf(&fd_name, "ares_ev_driver-%" PRIuPTR, i); |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 180 | fdn = gpr_malloc(sizeof(fd_node)); |
| 181 | fdn->grpc_fd = grpc_fd_create(ev_driver->socks[i], fd_name); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 182 | grpc_pollset_set_add_fd(exec_ctx, ev_driver->pollset_set, |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 183 | fdn->grpc_fd); |
Yuchen Zeng | d0725d7 | 2016-08-26 17:27:32 -0700 | [diff] [blame] | 184 | gpr_free(fd_name); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 185 | } |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 186 | fdn->next = new_list; |
| 187 | new_list = fdn; |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 188 | |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 189 | if (ARES_GETSOCK_READABLE(ev_driver->socks_bitmask, i)) { |
| 190 | grpc_fd_notify_on_read(exec_ctx, fdn->grpc_fd, |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 191 | &ev_driver->driver_closure); |
| 192 | } |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 193 | if (ARES_GETSOCK_WRITABLE(ev_driver->socks_bitmask, i)) { |
| 194 | grpc_fd_notify_on_write(exec_ctx, fdn->grpc_fd, |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 195 | &ev_driver->driver_closure); |
| 196 | } |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 197 | } |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 198 | } |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 199 | } |
| 200 | |
| 201 | while (ev_driver->fds != NULL) { |
Yuchen Zeng | 912327e | 2016-10-25 18:27:17 -0700 | [diff] [blame^] | 202 | fd_node *cur = ev_driver->fds; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 203 | ev_driver->fds = ev_driver->fds->next; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 204 | grpc_pollset_set_del_fd(exec_ctx, ev_driver->pollset_set, cur->grpc_fd); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 205 | grpc_fd_shutdown(exec_ctx, cur->grpc_fd); |
Yuchen Zeng | 0056531 | 2016-08-24 16:41:12 -0700 | [diff] [blame] | 206 | grpc_fd_orphan(exec_ctx, cur->grpc_fd, NULL, NULL, "c-ares query finished"); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 207 | gpr_free(cur); |
| 208 | } |
| 209 | |
| 210 | ev_driver->fds = new_list; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 211 | // If the ev driver has no working fd, all the tasks are done. |
| 212 | if (!new_list) { |
| 213 | gpr_mu_lock(&ev_driver->mu); |
| 214 | ev_driver->working = false; |
| 215 | gpr_mu_unlock(&ev_driver->mu); |
| 216 | } |
Yuchen Zeng | 213d784 | 2016-08-26 19:28:16 -0700 | [diff] [blame] | 217 | |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 218 | if (ev_driver->closing) { |
| 219 | ares_destroy(ev_driver->channel); |
| 220 | gpr_free(ev_driver); |
| 221 | } |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 222 | } |
| 223 | |
| 224 | void grpc_ares_ev_driver_start(grpc_exec_ctx *exec_ctx, |
| 225 | grpc_ares_ev_driver *ev_driver) { |
| 226 | gpr_mu_lock(&ev_driver->mu); |
| 227 | if (ev_driver->working) { |
| 228 | gpr_mu_unlock(&ev_driver->mu); |
| 229 | return; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 230 | } |
Yuchen Zeng | 912327e | 2016-10-25 18:27:17 -0700 | [diff] [blame^] | 231 | ev_driver->working = true; |
Yuchen Zeng | 213d784 | 2016-08-26 19:28:16 -0700 | [diff] [blame] | 232 | gpr_mu_unlock(&ev_driver->mu); |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 233 | grpc_ares_notify_on_event(exec_ctx, ev_driver); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 234 | } |
| 235 | |
Yuchen Zeng | 299dd8d | 2016-08-16 21:40:13 -0700 | [diff] [blame] | 236 | #endif /* GPR_POSIX_SOCKET */ |
| 237 | #endif /* GRPC_NATIVE_ADDRESS_RESOLVE */ |