Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 1 | /* |
| 2 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | * Copyright 2016 gRPC authors. |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 4 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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 |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 8 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 10 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 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. |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 16 | * |
| 17 | */ |
| 18 | #include <grpc/support/port_platform.h> |
Yuchen Zeng | 4e298e1 | 2016-10-28 16:08:19 -0700 | [diff] [blame] | 19 | #include "src/core/lib/iomgr/port.h" |
Yuchen Zeng | 9e4c8eb | 2016-11-18 01:06:57 -0800 | [diff] [blame] | 20 | #if GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 21 | |
Nicolas "Pixel" Noble | 00f2c93 | 2017-04-04 20:38:14 +0200 | [diff] [blame] | 22 | #include <ares.h> |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 23 | #include <sys/ioctl.h> |
Nicolas "Pixel" Noble | 00f2c93 | 2017-04-04 20:38:14 +0200 | [diff] [blame] | 24 | |
Craig Tiller | 9eb0fde | 2017-03-31 16:59:30 -0700 | [diff] [blame] | 25 | #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_ev_driver.h" |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 26 | |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 27 | #include <grpc/support/alloc.h> |
| 28 | #include <grpc/support/log.h> |
| 29 | #include <grpc/support/string_util.h> |
| 30 | #include <grpc/support/time.h> |
| 31 | #include <grpc/support/useful.h> |
Craig Tiller | 9eb0fde | 2017-03-31 16:59:30 -0700 | [diff] [blame] | 32 | #include "src/core/ext/filters/client_channel/resolver/dns/c_ares/grpc_ares_wrapper.h" |
Yuchen Zeng | 4e298e1 | 2016-10-28 16:08:19 -0700 | [diff] [blame] | 33 | #include "src/core/lib/iomgr/ev_posix.h" |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 34 | #include "src/core/lib/iomgr/iomgr_internal.h" |
| 35 | #include "src/core/lib/iomgr/sockaddr_utils.h" |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 36 | #include "src/core/lib/support/string.h" |
| 37 | |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 38 | typedef struct fd_node { |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 39 | /** the owner of this fd node */ |
| 40 | grpc_ares_ev_driver *ev_driver; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 41 | /** the grpc_fd owned by this fd node */ |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 42 | grpc_fd *fd; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 43 | /** a closure wrapping on_readable_cb, which should be invoked when the |
| 44 | grpc_fd in this node becomes readable. */ |
| 45 | grpc_closure read_closure; |
| 46 | /** a closure wrapping on_writable_cb, which should be invoked when the |
| 47 | grpc_fd in this node becomes writable. */ |
| 48 | grpc_closure write_closure; |
| 49 | /** next fd node in the list */ |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 50 | struct fd_node *next; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 51 | |
| 52 | /** mutex guarding the rest of the state */ |
| 53 | gpr_mu mu; |
| 54 | /** if the readable closure has been registered */ |
| 55 | bool readable_registered; |
| 56 | /** if the writable closure has been registered */ |
| 57 | bool writable_registered; |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 58 | /** if the fd is being shut down */ |
| 59 | bool shutting_down; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 60 | } fd_node; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 61 | |
| 62 | struct grpc_ares_ev_driver { |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 63 | /** the ares_channel owned by this event driver */ |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 64 | ares_channel channel; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 65 | /** pollset set for driving the IO events of the channel */ |
| 66 | grpc_pollset_set *pollset_set; |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 67 | /** refcount of the event driver */ |
| 68 | gpr_refcount refs; |
Yuchen Zeng | c87b77f | 2016-10-03 11:36:36 -0700 | [diff] [blame] | 69 | |
Yuchen Zeng | 43aa9a1 | 2016-10-25 10:44:39 -0700 | [diff] [blame] | 70 | /** mutex guarding the rest of the state */ |
Yuchen Zeng | c87b77f | 2016-10-03 11:36:36 -0700 | [diff] [blame] | 71 | gpr_mu mu; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 72 | /** a list of grpc_fd that this event driver is currently using. */ |
| 73 | fd_node *fds; |
Yuchen Zeng | c87b77f | 2016-10-03 11:36:36 -0700 | [diff] [blame] | 74 | /** is this event driver currently working? */ |
| 75 | bool working; |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 76 | /** is this event driver being shut down */ |
| 77 | bool shutting_down; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 78 | }; |
| 79 | |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 80 | static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, |
| 81 | grpc_ares_ev_driver *ev_driver); |
| 82 | |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 83 | static grpc_ares_ev_driver *grpc_ares_ev_driver_ref( |
| 84 | grpc_ares_ev_driver *ev_driver) { |
| 85 | gpr_log(GPR_DEBUG, "Ref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
| 86 | gpr_ref(&ev_driver->refs); |
| 87 | return ev_driver; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 88 | } |
| 89 | |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 90 | static void grpc_ares_ev_driver_unref(grpc_ares_ev_driver *ev_driver) { |
| 91 | gpr_log(GPR_DEBUG, "Unref ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
| 92 | if (gpr_unref(&ev_driver->refs)) { |
| 93 | gpr_log(GPR_DEBUG, "destroy ev_driver %" PRIuPTR, (uintptr_t)ev_driver); |
| 94 | GPR_ASSERT(ev_driver->fds == NULL); |
| 95 | gpr_mu_destroy(&ev_driver->mu); |
| 96 | ares_destroy(ev_driver->channel); |
| 97 | gpr_free(ev_driver); |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 98 | } |
| 99 | } |
Yuchen Zeng | 213d784 | 2016-08-26 19:28:16 -0700 | [diff] [blame] | 100 | |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 101 | static void fd_node_destroy(grpc_exec_ctx *exec_ctx, fd_node *fdn) { |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 102 | gpr_log(GPR_DEBUG, "delete fd: %d", grpc_fd_wrapped_fd(fdn->fd)); |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 103 | GPR_ASSERT(!fdn->readable_registered); |
| 104 | GPR_ASSERT(!fdn->writable_registered); |
| 105 | gpr_mu_destroy(&fdn->mu); |
Yuchen Zeng | 1f4b2a8 | 2017-06-05 15:24:31 -0700 | [diff] [blame] | 106 | /* c-ares library has closed the fd inside grpc_fd. This fd may be picked up |
| 107 | immediately by another thread, and should not be closed by the following |
Yuchen Zeng | d40a7ae | 2017-07-12 15:59:56 -0700 | [diff] [blame] | 108 | grpc_fd_orphan. */ |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 109 | grpc_fd_orphan(exec_ctx, fdn->fd, NULL, NULL, true /* already_closed */, |
Yuchen Zeng | d40a7ae | 2017-07-12 15:59:56 -0700 | [diff] [blame] | 110 | "c-ares query finished"); |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 111 | gpr_free(fdn); |
| 112 | } |
| 113 | |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 114 | static void fd_node_shutdown(grpc_exec_ctx *exec_ctx, fd_node *fdn) { |
| 115 | gpr_mu_lock(&fdn->mu); |
| 116 | fdn->shutting_down = true; |
| 117 | if (!fdn->readable_registered && !fdn->writable_registered) { |
| 118 | gpr_mu_unlock(&fdn->mu); |
| 119 | fd_node_destroy(exec_ctx, fdn); |
| 120 | } else { |
| 121 | grpc_fd_shutdown( |
| 122 | exec_ctx, fdn->fd, |
| 123 | GRPC_ERROR_CREATE_FROM_STATIC_STRING("c-ares fd shutdown")); |
| 124 | gpr_mu_unlock(&fdn->mu); |
| 125 | } |
| 126 | } |
| 127 | |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 128 | grpc_error *grpc_ares_ev_driver_create(grpc_ares_ev_driver **ev_driver, |
| 129 | grpc_pollset_set *pollset_set) { |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 130 | *ev_driver = (grpc_ares_ev_driver *)gpr_malloc(sizeof(grpc_ares_ev_driver)); |
Yuchen Zeng | 19d7bab | 2016-11-30 15:51:19 -0800 | [diff] [blame] | 131 | int status = ares_init(&(*ev_driver)->channel); |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 132 | gpr_log(GPR_DEBUG, "grpc_ares_ev_driver_create"); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 133 | if (status != ARES_SUCCESS) { |
Yuchen Zeng | 43aa9a1 | 2016-10-25 10:44:39 -0700 | [diff] [blame] | 134 | char *err_msg; |
| 135 | gpr_asprintf(&err_msg, "Failed to init ares channel. C-ares error: %s", |
| 136 | ares_strerror(status)); |
Yuchen Zeng | 0e8bc45 | 2017-03-23 14:44:14 -0700 | [diff] [blame] | 137 | grpc_error *err = GRPC_ERROR_CREATE_FROM_COPIED_STRING(err_msg); |
Yuchen Zeng | 43aa9a1 | 2016-10-25 10:44:39 -0700 | [diff] [blame] | 138 | gpr_free(err_msg); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 139 | gpr_free(*ev_driver); |
Yuchen Zeng | 43aa9a1 | 2016-10-25 10:44:39 -0700 | [diff] [blame] | 140 | return err; |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 141 | } |
Yuchen Zeng | 213d784 | 2016-08-26 19:28:16 -0700 | [diff] [blame] | 142 | gpr_mu_init(&(*ev_driver)->mu); |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 143 | gpr_ref_init(&(*ev_driver)->refs, 1); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 144 | (*ev_driver)->pollset_set = pollset_set; |
| 145 | (*ev_driver)->fds = NULL; |
Yuchen Zeng | ffbc167 | 2016-10-03 11:29:22 -0700 | [diff] [blame] | 146 | (*ev_driver)->working = false; |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 147 | (*ev_driver)->shutting_down = false; |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 148 | return GRPC_ERROR_NONE; |
| 149 | } |
| 150 | |
Yuchen Zeng | f47c963 | 2016-11-18 20:41:20 -0800 | [diff] [blame] | 151 | void grpc_ares_ev_driver_destroy(grpc_ares_ev_driver *ev_driver) { |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 152 | // It's not safe to shut down remaining fds here directly, becauses |
| 153 | // ares_host_callback does not provide an exec_ctx. We mark the event driver |
| 154 | // as being shut down. If the event driver is working, |
| 155 | // grpc_ares_notify_on_event_locked will shut down the fds; if it's not |
Yuchen Zeng | f47c963 | 2016-11-18 20:41:20 -0800 | [diff] [blame] | 156 | // working, there are no fds to shut down. |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 157 | gpr_mu_lock(&ev_driver->mu); |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 158 | ev_driver->shutting_down = true; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 159 | gpr_mu_unlock(&ev_driver->mu); |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 160 | grpc_ares_ev_driver_unref(ev_driver); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 161 | } |
| 162 | |
Yuchen Zeng | 3b4bed2 | 2017-06-04 01:41:15 -0700 | [diff] [blame] | 163 | void grpc_ares_ev_driver_shutdown(grpc_exec_ctx *exec_ctx, |
| 164 | grpc_ares_ev_driver *ev_driver) { |
| 165 | gpr_mu_lock(&ev_driver->mu); |
| 166 | ev_driver->shutting_down = true; |
| 167 | fd_node *fn = ev_driver->fds; |
| 168 | while (fn != NULL) { |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 169 | grpc_fd_shutdown(exec_ctx, fn->fd, GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
| 170 | "grpc_ares_ev_driver_shutdown")); |
Yuchen Zeng | 3b4bed2 | 2017-06-04 01:41:15 -0700 | [diff] [blame] | 171 | fn = fn->next; |
| 172 | } |
| 173 | gpr_mu_unlock(&ev_driver->mu); |
| 174 | } |
| 175 | |
Yuchen Zeng | 3026b6c | 2016-10-03 16:03:29 -0700 | [diff] [blame] | 176 | // Search fd in the fd_node list head. This is an O(n) search, the max possible |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 177 | // value of n is ARES_GETSOCK_MAXNUM (16). n is typically 1 - 2 in our tests. |
Yuchen Zeng | 3ae2663 | 2016-11-09 15:53:50 -0800 | [diff] [blame] | 178 | static fd_node *pop_fd_node(fd_node **head, int fd) { |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 179 | fd_node dummy_head; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 180 | dummy_head.next = *head; |
Yuchen Zeng | 3ae2663 | 2016-11-09 15:53:50 -0800 | [diff] [blame] | 181 | fd_node *node = &dummy_head; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 182 | while (node->next != NULL) { |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 183 | if (grpc_fd_wrapped_fd(node->next->fd) == fd) { |
Yuchen Zeng | 3ae2663 | 2016-11-09 15:53:50 -0800 | [diff] [blame] | 184 | fd_node *ret = node->next; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 185 | node->next = node->next->next; |
| 186 | *head = dummy_head.next; |
| 187 | return ret; |
| 188 | } |
Yuchen Zeng | c87b77f | 2016-10-03 11:36:36 -0700 | [diff] [blame] | 189 | node = node->next; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 190 | } |
| 191 | return NULL; |
| 192 | } |
| 193 | |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 194 | /* Check if \a fd is still readable */ |
| 195 | static bool grpc_ares_is_fd_still_readable(grpc_ares_ev_driver *ev_driver, |
| 196 | int fd) { |
| 197 | size_t bytes_available = 0; |
| 198 | return ioctl(fd, FIONREAD, &bytes_available) == 0 && bytes_available > 0; |
| 199 | } |
| 200 | |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 201 | static void on_readable_cb(grpc_exec_ctx *exec_ctx, void *arg, |
| 202 | grpc_error *error) { |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 203 | fd_node *fdn = (fd_node *)arg; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 204 | grpc_ares_ev_driver *ev_driver = fdn->ev_driver; |
| 205 | gpr_mu_lock(&fdn->mu); |
| 206 | fdn->readable_registered = false; |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 207 | if (fdn->shutting_down && !fdn->writable_registered) { |
| 208 | gpr_mu_unlock(&fdn->mu); |
| 209 | fd_node_destroy(exec_ctx, fdn); |
| 210 | grpc_ares_ev_driver_unref(ev_driver); |
| 211 | return; |
| 212 | } |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 213 | gpr_mu_unlock(&fdn->mu); |
Yuchen Zeng | 925b688 | 2016-08-24 18:42:25 -0700 | [diff] [blame] | 214 | |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 215 | gpr_log(GPR_DEBUG, "readable on %d", grpc_fd_wrapped_fd(fdn->fd)); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 216 | if (error == GRPC_ERROR_NONE) { |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 217 | do { |
| 218 | ares_process_fd(ev_driver->channel, grpc_fd_wrapped_fd(fdn->fd), |
| 219 | ARES_SOCKET_BAD); |
| 220 | } while ( |
| 221 | grpc_ares_is_fd_still_readable(ev_driver, grpc_fd_wrapped_fd(fdn->fd))); |
Yuchen Zeng | 4dd1891 | 2016-08-24 17:17:17 -0700 | [diff] [blame] | 222 | } else { |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 223 | // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or |
| 224 | // timed out. The pending lookups made on this ev_driver will be cancelled |
Yuchen Zeng | 3ae2663 | 2016-11-09 15:53:50 -0800 | [diff] [blame] | 225 | // by the following ares_cancel() and the on_done callbacks will be invoked |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 226 | // with a status of ARES_ECANCELLED. The remaining file descriptors in this |
| 227 | // ev_driver will be cleaned up in the follwing |
| 228 | // grpc_ares_notify_on_event_locked(). |
| 229 | ares_cancel(ev_driver->channel); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 230 | } |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 231 | gpr_mu_lock(&ev_driver->mu); |
| 232 | grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); |
| 233 | gpr_mu_unlock(&ev_driver->mu); |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 234 | grpc_ares_ev_driver_unref(ev_driver); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 235 | } |
| 236 | |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 237 | static void on_writable_cb(grpc_exec_ctx *exec_ctx, void *arg, |
| 238 | grpc_error *error) { |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 239 | fd_node *fdn = (fd_node *)arg; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 240 | grpc_ares_ev_driver *ev_driver = fdn->ev_driver; |
| 241 | gpr_mu_lock(&fdn->mu); |
| 242 | fdn->writable_registered = false; |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 243 | if (fdn->shutting_down && !fdn->readable_registered) { |
| 244 | gpr_mu_unlock(&fdn->mu); |
| 245 | fd_node_destroy(exec_ctx, fdn); |
| 246 | grpc_ares_ev_driver_unref(ev_driver); |
| 247 | return; |
| 248 | } |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 249 | gpr_mu_unlock(&fdn->mu); |
| 250 | |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 251 | gpr_log(GPR_DEBUG, "writable on %d", grpc_fd_wrapped_fd(fdn->fd)); |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 252 | if (error == GRPC_ERROR_NONE) { |
| 253 | ares_process_fd(ev_driver->channel, ARES_SOCKET_BAD, |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 254 | grpc_fd_wrapped_fd(fdn->fd)); |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 255 | } else { |
| 256 | // If error is not GRPC_ERROR_NONE, it means the fd has been shutdown or |
| 257 | // timed out. The pending lookups made on this ev_driver will be cancelled |
Yuchen Zeng | 3ae2663 | 2016-11-09 15:53:50 -0800 | [diff] [blame] | 258 | // by the following ares_cancel() and the on_done callbacks will be invoked |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 259 | // with a status of ARES_ECANCELLED. The remaining file descriptors in this |
| 260 | // ev_driver will be cleaned up in the follwing |
| 261 | // grpc_ares_notify_on_event_locked(). |
| 262 | ares_cancel(ev_driver->channel); |
| 263 | } |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 264 | gpr_mu_lock(&ev_driver->mu); |
| 265 | grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); |
| 266 | gpr_mu_unlock(&ev_driver->mu); |
Yuchen Zeng | 8a6cba2 | 2016-11-09 18:19:13 -0800 | [diff] [blame] | 267 | grpc_ares_ev_driver_unref(ev_driver); |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 268 | } |
| 269 | |
Yuchen Zeng | 9e4c8eb | 2016-11-18 01:06:57 -0800 | [diff] [blame] | 270 | ares_channel *grpc_ares_ev_driver_get_channel(grpc_ares_ev_driver *ev_driver) { |
Yuchen Zeng | 9248d35 | 2016-08-16 16:33:10 -0700 | [diff] [blame] | 271 | return &ev_driver->channel; |
| 272 | } |
| 273 | |
Yuchen Zeng | 3026b6c | 2016-10-03 16:03:29 -0700 | [diff] [blame] | 274 | // Get the file descriptors used by the ev_driver's ares channel, register |
| 275 | // driver_closure with these filedescriptors. |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 276 | static void grpc_ares_notify_on_event_locked(grpc_exec_ctx *exec_ctx, |
| 277 | grpc_ares_ev_driver *ev_driver) { |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 278 | fd_node *new_list = NULL; |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 279 | if (!ev_driver->shutting_down) { |
| 280 | ares_socket_t socks[ARES_GETSOCK_MAXNUM]; |
| 281 | int socks_bitmask = |
| 282 | ares_getsock(ev_driver->channel, socks, ARES_GETSOCK_MAXNUM); |
| 283 | for (size_t i = 0; i < ARES_GETSOCK_MAXNUM; i++) { |
| 284 | if (ARES_GETSOCK_READABLE(socks_bitmask, i) || |
| 285 | ARES_GETSOCK_WRITABLE(socks_bitmask, i)) { |
| 286 | fd_node *fdn = pop_fd_node(&ev_driver->fds, socks[i]); |
| 287 | // Create a new fd_node if sock[i] is not in the fd_node list. |
| 288 | if (fdn == NULL) { |
| 289 | char *fd_name; |
| 290 | gpr_asprintf(&fd_name, "ares_ev_driver-%" PRIuPTR, i); |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 291 | fdn = (fd_node *)gpr_malloc(sizeof(fd_node)); |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 292 | gpr_log(GPR_DEBUG, "new fd: %d", socks[i]); |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 293 | fdn->fd = grpc_fd_create(socks[i], fd_name); |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 294 | fdn->ev_driver = ev_driver; |
| 295 | fdn->readable_registered = false; |
| 296 | fdn->writable_registered = false; |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 297 | fdn->shutting_down = false; |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 298 | gpr_mu_init(&fdn->mu); |
ncteisen | 274bbbe | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 299 | GRPC_CLOSURE_INIT(&fdn->read_closure, on_readable_cb, fdn, |
Yuchen Zeng | 2ef172b | 2017-01-19 16:26:55 -0800 | [diff] [blame] | 300 | grpc_schedule_on_exec_ctx); |
ncteisen | 274bbbe | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 301 | GRPC_CLOSURE_INIT(&fdn->write_closure, on_writable_cb, fdn, |
Yuchen Zeng | 2ef172b | 2017-01-19 16:26:55 -0800 | [diff] [blame] | 302 | grpc_schedule_on_exec_ctx); |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 303 | grpc_pollset_set_add_fd(exec_ctx, ev_driver->pollset_set, fdn->fd); |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 304 | gpr_free(fd_name); |
| 305 | } |
| 306 | fdn->next = new_list; |
| 307 | new_list = fdn; |
| 308 | gpr_mu_lock(&fdn->mu); |
| 309 | // Register read_closure if the socket is readable and read_closure has |
| 310 | // not been registered with this socket. |
| 311 | if (ARES_GETSOCK_READABLE(socks_bitmask, i) && |
| 312 | !fdn->readable_registered) { |
| 313 | grpc_ares_ev_driver_ref(ev_driver); |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 314 | gpr_log(GPR_DEBUG, "notify read on: %d", grpc_fd_wrapped_fd(fdn->fd)); |
| 315 | grpc_fd_notify_on_read(exec_ctx, fdn->fd, &fdn->read_closure); |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 316 | fdn->readable_registered = true; |
| 317 | } |
| 318 | // Register write_closure if the socket is writable and write_closure |
Yuchen Zeng | f47c963 | 2016-11-18 20:41:20 -0800 | [diff] [blame] | 319 | // has not been registered with this socket. |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 320 | if (ARES_GETSOCK_WRITABLE(socks_bitmask, i) && |
| 321 | !fdn->writable_registered) { |
| 322 | gpr_log(GPR_DEBUG, "notify write on: %d", |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 323 | grpc_fd_wrapped_fd(fdn->fd)); |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 324 | grpc_ares_ev_driver_ref(ev_driver); |
Yash Tibrewal | bc130da | 2017-09-12 22:44:08 -0700 | [diff] [blame] | 325 | grpc_fd_notify_on_write(exec_ctx, fdn->fd, &fdn->write_closure); |
Yuchen Zeng | 117a300 | 2016-11-17 19:43:36 -0800 | [diff] [blame] | 326 | fdn->writable_registered = true; |
| 327 | } |
| 328 | gpr_mu_unlock(&fdn->mu); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 329 | } |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 330 | } |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 331 | } |
Yuchen Zeng | 3483cf5 | 2016-11-10 23:09:00 -0800 | [diff] [blame] | 332 | // Any remaining fds in ev_driver->fds were not returned by ares_getsock() and |
| 333 | // are therefore no longer in use, so they can be shut down and removed from |
Yuchen Zeng | 3ae2663 | 2016-11-09 15:53:50 -0800 | [diff] [blame] | 334 | // the list. |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 335 | while (ev_driver->fds != NULL) { |
Yuchen Zeng | 912327e | 2016-10-25 18:27:17 -0700 | [diff] [blame] | 336 | fd_node *cur = ev_driver->fds; |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 337 | ev_driver->fds = ev_driver->fds->next; |
Yuchen Zeng | 79c12b9 | 2017-09-18 22:02:52 -0700 | [diff] [blame^] | 338 | fd_node_shutdown(exec_ctx, cur); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 339 | } |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 340 | ev_driver->fds = new_list; |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 341 | // If the ev driver has no working fd, all the tasks are done. |
Yuchen Zeng | 3ae2663 | 2016-11-09 15:53:50 -0800 | [diff] [blame] | 342 | if (new_list == NULL) { |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 343 | ev_driver->working = false; |
Yuchen Zeng | e8d8309 | 2016-10-27 17:30:17 -0700 | [diff] [blame] | 344 | gpr_log(GPR_DEBUG, "ev driver stop working"); |
Yuchen Zeng | 8917aec | 2016-08-09 18:41:31 -0700 | [diff] [blame] | 345 | } |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 346 | } |
| 347 | |
| 348 | void grpc_ares_ev_driver_start(grpc_exec_ctx *exec_ctx, |
| 349 | grpc_ares_ev_driver *ev_driver) { |
| 350 | gpr_mu_lock(&ev_driver->mu); |
Yuchen Zeng | 3ae2663 | 2016-11-09 15:53:50 -0800 | [diff] [blame] | 351 | if (!ev_driver->working) { |
| 352 | ev_driver->working = true; |
| 353 | grpc_ares_notify_on_event_locked(exec_ctx, ev_driver); |
Yuchen Zeng | c1893dc | 2016-09-30 18:49:41 -0700 | [diff] [blame] | 354 | } |
Yuchen Zeng | 213d784 | 2016-08-26 19:28:16 -0700 | [diff] [blame] | 355 | gpr_mu_unlock(&ev_driver->mu); |
Yuchen Zeng | 85750b0 | 2016-08-08 14:16:34 -0700 | [diff] [blame] | 356 | } |
| 357 | |
Yuchen Zeng | 9e4c8eb | 2016-11-18 01:06:57 -0800 | [diff] [blame] | 358 | #endif /* GRPC_ARES == 1 && defined(GRPC_POSIX_SOCKET) */ |