Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 1 | /* |
| 2 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 3 | * Copyright 2015 gRPC authors. |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [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 |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 8 | * |
Jan Tattermusch | 7897ae9 | 2017-06-07 22:57:36 +0200 | [diff] [blame] | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [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. |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 16 | * |
| 17 | */ |
| 18 | |
David Klempner | 78b7992 | 2015-02-04 10:18:59 -0800 | [diff] [blame] | 19 | /* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */ |
| 20 | #ifndef _GNU_SOURCE |
| 21 | #define _GNU_SOURCE |
| 22 | #endif |
| 23 | |
murgatroid99 | 5407089 | 2016-08-08 17:01:18 -0700 | [diff] [blame] | 24 | #include "src/core/lib/iomgr/port.h" |
Craig Tiller | 0c0b60c | 2015-01-21 15:49:28 -0800 | [diff] [blame] | 25 | |
murgatroid99 | 623dd4f | 2016-08-08 17:31:27 -0700 | [diff] [blame] | 26 | #ifdef GRPC_POSIX_SOCKET |
Craig Tiller | 0c0b60c | 2015-01-21 15:49:28 -0800 | [diff] [blame] | 27 | |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 28 | #include "src/core/lib/iomgr/tcp_server.h" |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 29 | |
Craig Tiller | aa31da4 | 2015-02-17 16:33:35 -0800 | [diff] [blame] | 30 | #include <errno.h> |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 31 | #include <fcntl.h> |
| 32 | #include <netinet/in.h> |
| 33 | #include <netinet/tcp.h> |
Craig Tiller | aa31da4 | 2015-02-17 16:33:35 -0800 | [diff] [blame] | 34 | #include <string.h> |
| 35 | #include <sys/socket.h> |
| 36 | #include <sys/stat.h> |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 37 | #include <sys/types.h> |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 38 | #include <unistd.h> |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 39 | |
Craig Tiller | f40df23 | 2016-03-25 13:38:14 -0700 | [diff] [blame] | 40 | #include <grpc/support/alloc.h> |
| 41 | #include <grpc/support/log.h> |
| 42 | #include <grpc/support/string_util.h> |
| 43 | #include <grpc/support/sync.h> |
| 44 | #include <grpc/support/time.h> |
Craig Tiller | c027e77 | 2016-05-03 16:27:00 -0700 | [diff] [blame] | 45 | #include <grpc/support/useful.h> |
| 46 | |
Craig Tiller | 547cb4b | 2017-03-28 09:50:33 -0700 | [diff] [blame] | 47 | #include "src/core/lib/channel/channel_args.h" |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 48 | #include "src/core/lib/iomgr/resolve_address.h" |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 49 | #include "src/core/lib/iomgr/sockaddr.h" |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 50 | #include "src/core/lib/iomgr/sockaddr_utils.h" |
| 51 | #include "src/core/lib/iomgr/socket_utils_posix.h" |
| 52 | #include "src/core/lib/iomgr/tcp_posix.h" |
Yuchen Zeng | 47155ed | 2017-03-13 17:18:07 -0700 | [diff] [blame] | 53 | #include "src/core/lib/iomgr/tcp_server_utils_posix.h" |
Craig Tiller | 9533d04 | 2016-03-25 17:11:06 -0700 | [diff] [blame] | 54 | #include "src/core/lib/iomgr/unix_sockets_posix.h" |
| 55 | #include "src/core/lib/support/string.h" |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 56 | |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 57 | static gpr_once check_init = GPR_ONCE_INIT; |
Nicolas "Pixel" Noble | baa35fc | 2016-08-19 02:20:11 +0200 | [diff] [blame] | 58 | static bool has_so_reuseport = false; |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 59 | |
| 60 | static void init(void) { |
Nicolas "Pixel" Noble | baa35fc | 2016-08-19 02:20:11 +0200 | [diff] [blame] | 61 | #ifndef GPR_MANYLINUX1 |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 62 | int s = socket(AF_INET, SOCK_STREAM, 0); |
| 63 | if (s >= 0) { |
| 64 | has_so_reuseport = GRPC_LOG_IF_ERROR("check for SO_REUSEPORT", |
| 65 | grpc_set_socket_reuse_port(s, 1)); |
| 66 | close(s); |
| 67 | } |
Nicolas "Pixel" Noble | baa35fc | 2016-08-19 02:20:11 +0200 | [diff] [blame] | 68 | #endif |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 69 | } |
| 70 | |
Craig Tiller | e34c285 | 2016-09-23 09:43:32 -0700 | [diff] [blame] | 71 | grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx, |
| 72 | grpc_closure *shutdown_complete, |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 73 | const grpc_channel_args *args, |
Craig Tiller | 0b5857f | 2016-05-04 10:58:06 -0700 | [diff] [blame] | 74 | grpc_tcp_server **server) { |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 75 | gpr_once_init(&check_init, init); |
| 76 | |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 77 | grpc_tcp_server *s = (grpc_tcp_server *)gpr_zalloc(sizeof(grpc_tcp_server)); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 78 | s->so_reuseport = has_so_reuseport; |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 79 | s->expand_wildcard_addrs = false; |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 80 | for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) { |
| 81 | if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) { |
| 82 | if (args->args[i].type == GRPC_ARG_INTEGER) { |
| 83 | s->so_reuseport = |
| 84 | has_so_reuseport && (args->args[i].value.integer != 0); |
| 85 | } else { |
| 86 | gpr_free(s); |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 87 | return GRPC_ERROR_CREATE_FROM_STATIC_STRING(GRPC_ARG_ALLOW_REUSEPORT |
| 88 | " must be an integer"); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 89 | } |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 90 | } else if (0 == strcmp(GRPC_ARG_EXPAND_WILDCARD_ADDRS, args->args[i].key)) { |
| 91 | if (args->args[i].type == GRPC_ARG_INTEGER) { |
| 92 | s->expand_wildcard_addrs = (args->args[i].value.integer != 0); |
| 93 | } else { |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 94 | gpr_free(s); |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 95 | return GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
| 96 | GRPC_ARG_EXPAND_WILDCARD_ADDRS " must be an integer"); |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 97 | } |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 98 | } |
| 99 | } |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 100 | gpr_ref_init(&s->refs, 1); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 101 | gpr_mu_init(&s->mu); |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 102 | s->active_ports = 0; |
Craig Tiller | aec96aa | 2015-04-07 14:32:15 -0700 | [diff] [blame] | 103 | s->destroyed_ports = 0; |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 104 | s->shutdown = false; |
Dan Born | 9c12bc2 | 2016-01-13 16:52:20 -0800 | [diff] [blame] | 105 | s->shutdown_starting.head = NULL; |
| 106 | s->shutdown_starting.tail = NULL; |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 107 | s->shutdown_complete = shutdown_complete; |
Robbie Shade | 3cd2d18 | 2015-08-28 14:30:35 -0400 | [diff] [blame] | 108 | s->on_accept_cb = NULL; |
| 109 | s->on_accept_cb_arg = NULL; |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 110 | s->head = NULL; |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 111 | s->tail = NULL; |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 112 | s->nports = 0; |
Craig Tiller | 547cb4b | 2017-03-28 09:50:33 -0700 | [diff] [blame] | 113 | s->channel_args = grpc_channel_args_copy(args); |
Craig Tiller | b76471d | 2016-07-01 10:24:56 -0700 | [diff] [blame] | 114 | gpr_atm_no_barrier_store(&s->next_pollset_to_assign, 0); |
Craig Tiller | 0b5857f | 2016-05-04 10:58:06 -0700 | [diff] [blame] | 115 | *server = s; |
| 116 | return GRPC_ERROR_NONE; |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 117 | } |
| 118 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 119 | static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { |
Dan Born | 930c298 | 2016-09-08 19:12:18 -0700 | [diff] [blame] | 120 | gpr_mu_lock(&s->mu); |
| 121 | GPR_ASSERT(s->shutdown); |
| 122 | gpr_mu_unlock(&s->mu); |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 123 | if (s->shutdown_complete != NULL) { |
ncteisen | 274bbbe | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 124 | GRPC_CLOSURE_SCHED(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE); |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 125 | } |
Craig Tiller | aec96aa | 2015-04-07 14:32:15 -0700 | [diff] [blame] | 126 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 127 | gpr_mu_destroy(&s->mu); |
Craig Tiller | aec96aa | 2015-04-07 14:32:15 -0700 | [diff] [blame] | 128 | |
Nicolas "Pixel" Noble | c6a7c6e | 2015-11-19 21:55:44 +0100 | [diff] [blame] | 129 | while (s->head) { |
| 130 | grpc_tcp_listener *sp = s->head; |
| 131 | s->head = sp->next; |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 132 | gpr_free(sp); |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 133 | } |
Craig Tiller | 547cb4b | 2017-03-28 09:50:33 -0700 | [diff] [blame] | 134 | grpc_channel_args_destroy(exec_ctx, s->channel_args); |
Craig Tiller | e34c285 | 2016-09-23 09:43:32 -0700 | [diff] [blame] | 135 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 136 | gpr_free(s); |
Craig Tiller | aec96aa | 2015-04-07 14:32:15 -0700 | [diff] [blame] | 137 | } |
| 138 | |
Craig Tiller | 6c39686 | 2016-01-28 13:53:40 -0800 | [diff] [blame] | 139 | static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, |
Craig Tiller | c027e77 | 2016-05-03 16:27:00 -0700 | [diff] [blame] | 140 | grpc_error *error) { |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 141 | grpc_tcp_server *s = (grpc_tcp_server *)server; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 142 | gpr_mu_lock(&s->mu); |
Craig Tiller | aec96aa | 2015-04-07 14:32:15 -0700 | [diff] [blame] | 143 | s->destroyed_ports++; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 144 | if (s->destroyed_ports == s->nports) { |
| 145 | gpr_mu_unlock(&s->mu); |
| 146 | finish_shutdown(exec_ctx, s); |
| 147 | } else { |
| 148 | GPR_ASSERT(s->destroyed_ports < s->nports); |
| 149 | gpr_mu_unlock(&s->mu); |
| 150 | } |
Craig Tiller | aec96aa | 2015-04-07 14:32:15 -0700 | [diff] [blame] | 151 | } |
| 152 | |
Craig Tiller | 6174b9a | 2015-06-18 08:13:05 -0700 | [diff] [blame] | 153 | /* called when all listening endpoints have been shutdown, so no further |
| 154 | events will be received on them - at this point it's safe to destroy |
| 155 | things */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 156 | static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 157 | /* delete ALL the things */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 158 | gpr_mu_lock(&s->mu); |
Craig Tiller | 6f05140 | 2015-05-13 11:42:42 -0700 | [diff] [blame] | 159 | |
yang-g | aef398b | 2017-03-07 15:43:53 -0800 | [diff] [blame] | 160 | GPR_ASSERT(s->shutdown); |
Craig Tiller | 45724b3 | 2015-09-22 10:42:19 -0700 | [diff] [blame] | 161 | |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 162 | if (s->head) { |
Nicolas Noble | 8f71462 | 2015-11-19 11:16:54 -0800 | [diff] [blame] | 163 | grpc_tcp_listener *sp; |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 164 | for (sp = s->head; sp; sp = sp->next) { |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 165 | grpc_unlink_if_unix_domain_socket(&sp->addr); |
ncteisen | 274bbbe | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 166 | GRPC_CLOSURE_INIT(&sp->destroyed_closure, destroyed_port, s, |
Craig Tiller | 3cb3447 | 2016-12-28 16:11:38 -0800 | [diff] [blame] | 167 | grpc_schedule_on_exec_ctx); |
yang-g | 5d85037 | 2015-12-01 10:32:28 -0800 | [diff] [blame] | 168 | grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL, |
Yuchen Zeng | d40a7ae | 2017-07-12 15:59:56 -0700 | [diff] [blame] | 169 | false /* already_closed */, "tcp_listener_shutdown"); |
Craig Tiller | 45724b3 | 2015-09-22 10:42:19 -0700 | [diff] [blame] | 170 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 171 | gpr_mu_unlock(&s->mu); |
| 172 | } else { |
| 173 | gpr_mu_unlock(&s->mu); |
| 174 | finish_shutdown(exec_ctx, s); |
| 175 | } |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 176 | } |
| 177 | |
Dan Born | 5d81d15 | 2016-01-12 20:29:29 -0800 | [diff] [blame] | 178 | static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 179 | gpr_mu_lock(&s->mu); |
Craig Tiller | 6f05140 | 2015-05-13 11:42:42 -0700 | [diff] [blame] | 180 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 181 | GPR_ASSERT(!s->shutdown); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 182 | s->shutdown = true; |
Craig Tiller | 6f05140 | 2015-05-13 11:42:42 -0700 | [diff] [blame] | 183 | |
Craig Tiller | 6f05140 | 2015-05-13 11:42:42 -0700 | [diff] [blame] | 184 | /* shutdown all fd's */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 185 | if (s->active_ports) { |
Nicolas Noble | 8f71462 | 2015-11-19 11:16:54 -0800 | [diff] [blame] | 186 | grpc_tcp_listener *sp; |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 187 | for (sp = s->head; sp; sp = sp->next) { |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 188 | grpc_fd_shutdown(exec_ctx, sp->emfd, GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
| 189 | "Server destroyed")); |
Craig Tiller | 6f05140 | 2015-05-13 11:42:42 -0700 | [diff] [blame] | 190 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 191 | gpr_mu_unlock(&s->mu); |
| 192 | } else { |
| 193 | gpr_mu_unlock(&s->mu); |
| 194 | deactivated_all_ports(exec_ctx, s); |
| 195 | } |
Craig Tiller | 6f05140 | 2015-05-13 11:42:42 -0700 | [diff] [blame] | 196 | } |
| 197 | |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 198 | /* event manager callback when reads are ready */ |
Craig Tiller | c027e77 | 2016-05-03 16:27:00 -0700 | [diff] [blame] | 199 | static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) { |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 200 | grpc_tcp_listener *sp = (grpc_tcp_listener *)arg; |
Yash Tibrewal | 533d118 | 2017-09-18 10:48:22 -0700 | [diff] [blame^] | 201 | grpc_pollset *read_notifier_pollset; |
Craig Tiller | c027e77 | 2016-05-03 16:27:00 -0700 | [diff] [blame] | 202 | if (err != GRPC_ERROR_NONE) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 203 | goto error; |
| 204 | } |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 205 | |
Yash Tibrewal | 533d118 | 2017-09-18 10:48:22 -0700 | [diff] [blame^] | 206 | read_notifier_pollset = |
Craig Tiller | b76471d | 2016-07-01 10:24:56 -0700 | [diff] [blame] | 207 | sp->server->pollsets[(size_t)gpr_atm_no_barrier_fetch_add( |
| 208 | &sp->server->next_pollset_to_assign, 1) % |
Craig Tiller | 53dd6b9 | 2016-05-24 13:49:50 -0700 | [diff] [blame] | 209 | sp->server->pollset_count]; |
Sree Kuchibhotla | 42b004a | 2016-04-08 14:41:49 -0700 | [diff] [blame] | 210 | |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 211 | /* loop until accept4 returns EAGAIN, and then re-arm notification */ |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 212 | for (;;) { |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 213 | grpc_resolved_address addr; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 214 | char *addr_str; |
| 215 | char *name; |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 216 | addr.len = sizeof(struct sockaddr_storage); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 217 | /* Note: If we ever decide to return this address to the user, remember to |
| 218 | strip off the ::ffff:0.0.0.0/96 prefix first. */ |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 219 | int fd = grpc_accept4(sp->fd, &addr, 1, 1); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 220 | if (fd < 0) { |
| 221 | switch (errno) { |
| 222 | case EINTR: |
| 223 | continue; |
| 224 | case EAGAIN: |
| 225 | grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); |
| 226 | return; |
| 227 | default: |
Craig Tiller | 1444464 | 2017-03-07 16:21:55 -0800 | [diff] [blame] | 228 | gpr_mu_lock(&sp->server->mu); |
Craig Tiller | f26236a | 2017-03-07 09:43:51 -0800 | [diff] [blame] | 229 | if (!sp->server->shutdown_listeners) { |
| 230 | gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno)); |
| 231 | } else { |
| 232 | /* if we have shutdown listeners, accept4 could fail, and we |
| 233 | needn't notify users */ |
| 234 | } |
Craig Tiller | 1444464 | 2017-03-07 16:21:55 -0800 | [diff] [blame] | 235 | gpr_mu_unlock(&sp->server->mu); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 236 | goto error; |
| 237 | } |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 238 | } |
| 239 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 240 | grpc_set_socket_no_sigpipe_if_possible(fd); |
| 241 | |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 242 | addr_str = grpc_sockaddr_to_uri(&addr); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 243 | gpr_asprintf(&name, "tcp-server-connection:%s", addr_str); |
| 244 | |
Craig Tiller | 84f75d4 | 2017-05-03 13:06:35 -0700 | [diff] [blame] | 245 | if (GRPC_TRACER_ON(grpc_tcp_trace)) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 246 | gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str); |
| 247 | } |
| 248 | |
Mark D. Roth | eed3815 | 2016-12-08 13:59:13 -0800 | [diff] [blame] | 249 | grpc_fd *fdobj = grpc_fd_create(fd, name); |
Sree Kuchibhotla | 42b004a | 2016-04-08 14:41:49 -0700 | [diff] [blame] | 250 | |
Sree Kuchibhotla | 42b004a | 2016-04-08 14:41:49 -0700 | [diff] [blame] | 251 | grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj); |
| 252 | |
Mark D. Roth | 6c07bf8 | 2016-12-09 08:38:38 -0800 | [diff] [blame] | 253 | // Create acceptor. |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 254 | grpc_tcp_server_acceptor *acceptor = |
| 255 | (grpc_tcp_server_acceptor *)gpr_malloc(sizeof(*acceptor)); |
Mark D. Roth | 6c07bf8 | 2016-12-09 08:38:38 -0800 | [diff] [blame] | 256 | acceptor->from_server = sp->server; |
| 257 | acceptor->port_index = sp->port_index; |
| 258 | acceptor->fd_index = sp->fd_index; |
| 259 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 260 | sp->server->on_accept_cb( |
| 261 | exec_ctx, sp->server->on_accept_cb_arg, |
Craig Tiller | 547cb4b | 2017-03-28 09:50:33 -0700 | [diff] [blame] | 262 | grpc_tcp_create(exec_ctx, fdobj, sp->server->channel_args, addr_str), |
Mark D. Roth | eed3815 | 2016-12-08 13:59:13 -0800 | [diff] [blame] | 263 | read_notifier_pollset, acceptor); |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 264 | |
| 265 | gpr_free(name); |
| 266 | gpr_free(addr_str); |
| 267 | } |
| 268 | |
yang-g | b063c87 | 2015-10-07 11:40:13 -0700 | [diff] [blame] | 269 | GPR_UNREACHABLE_CODE(return ); |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 270 | |
| 271 | error: |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 272 | gpr_mu_lock(&sp->server->mu); |
yang-g | aef398b | 2017-03-07 15:43:53 -0800 | [diff] [blame] | 273 | if (0 == --sp->server->active_ports && sp->server->shutdown) { |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 274 | gpr_mu_unlock(&sp->server->mu); |
| 275 | deactivated_all_ports(exec_ctx, sp->server); |
| 276 | } else { |
| 277 | gpr_mu_unlock(&sp->server->mu); |
| 278 | } |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 279 | } |
| 280 | |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 281 | /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */ |
| 282 | static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s, |
| 283 | unsigned port_index, |
| 284 | int requested_port, |
| 285 | int *out_port) { |
| 286 | grpc_resolved_address wild4; |
| 287 | grpc_resolved_address wild6; |
| 288 | unsigned fd_index = 0; |
| 289 | grpc_dualstack_mode dsmode; |
| 290 | grpc_tcp_listener *sp = NULL; |
| 291 | grpc_tcp_listener *sp2 = NULL; |
| 292 | grpc_error *v6_err = GRPC_ERROR_NONE; |
| 293 | grpc_error *v4_err = GRPC_ERROR_NONE; |
| 294 | *out_port = -1; |
Yuchen Zeng | ca29465 | 2017-03-13 14:50:34 -0700 | [diff] [blame] | 295 | |
Yuchen Zeng | 47155ed | 2017-03-13 17:18:07 -0700 | [diff] [blame] | 296 | if (grpc_tcp_server_have_ifaddrs() && s->expand_wildcard_addrs) { |
| 297 | return grpc_tcp_server_add_all_local_addrs(s, port_index, requested_port, |
| 298 | out_port); |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 299 | } |
Yuchen Zeng | ca29465 | 2017-03-13 14:50:34 -0700 | [diff] [blame] | 300 | |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 301 | grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6); |
| 302 | /* Try listening on IPv6 first. */ |
Yuchen Zeng | 47155ed | 2017-03-13 17:18:07 -0700 | [diff] [blame] | 303 | if ((v6_err = grpc_tcp_server_add_addr(s, &wild6, port_index, fd_index, |
| 304 | &dsmode, &sp)) == GRPC_ERROR_NONE) { |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 305 | ++fd_index; |
| 306 | requested_port = *out_port = sp->port; |
| 307 | if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) { |
| 308 | return GRPC_ERROR_NONE; |
| 309 | } |
| 310 | } |
| 311 | /* If we got a v6-only socket or nothing, try adding 0.0.0.0. */ |
| 312 | grpc_sockaddr_set_port(&wild4, requested_port); |
Yuchen Zeng | 47155ed | 2017-03-13 17:18:07 -0700 | [diff] [blame] | 313 | if ((v4_err = grpc_tcp_server_add_addr(s, &wild4, port_index, fd_index, |
| 314 | &dsmode, &sp2)) == GRPC_ERROR_NONE) { |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 315 | *out_port = sp2->port; |
| 316 | if (sp != NULL) { |
| 317 | sp2->is_sibling = 1; |
| 318 | sp->sibling = sp2; |
| 319 | } |
| 320 | } |
| 321 | if (*out_port > 0) { |
Yuchen Zeng | cb2f3f6 | 2017-03-17 14:30:09 -0700 | [diff] [blame] | 322 | if (v6_err != GRPC_ERROR_NONE) { |
| 323 | gpr_log(GPR_INFO, |
| 324 | "Failed to add :: listener, " |
| 325 | "the environment may not support IPv6: %s", |
| 326 | grpc_error_string(v6_err)); |
| 327 | GRPC_ERROR_UNREF(v6_err); |
| 328 | } |
| 329 | if (v4_err != GRPC_ERROR_NONE) { |
| 330 | gpr_log(GPR_INFO, |
| 331 | "Failed to add 0.0.0.0 listener, " |
| 332 | "the environment may not support IPv4: %s", |
| 333 | grpc_error_string(v4_err)); |
| 334 | GRPC_ERROR_UNREF(v4_err); |
| 335 | } |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 336 | return GRPC_ERROR_NONE; |
| 337 | } else { |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 338 | grpc_error *root_err = GRPC_ERROR_CREATE_FROM_STATIC_STRING( |
| 339 | "Failed to add any wildcard listeners"); |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 340 | GPR_ASSERT(v6_err != GRPC_ERROR_NONE && v4_err != GRPC_ERROR_NONE); |
| 341 | root_err = grpc_error_add_child(root_err, v6_err); |
| 342 | root_err = grpc_error_add_child(root_err, v4_err); |
| 343 | return root_err; |
| 344 | } |
| 345 | } |
| 346 | |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 347 | static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) { |
| 348 | grpc_tcp_listener *sp = NULL; |
| 349 | char *addr_str; |
| 350 | char *name; |
| 351 | grpc_error *err; |
| 352 | |
| 353 | for (grpc_tcp_listener *l = listener->next; l && l->is_sibling; l = l->next) { |
| 354 | l->fd_index += count; |
| 355 | } |
| 356 | |
| 357 | for (unsigned i = 0; i < count; i++) { |
Craig Tiller | 136698c | 2016-05-19 11:49:44 -0700 | [diff] [blame] | 358 | int fd = -1; |
| 359 | int port = -1; |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 360 | grpc_dualstack_mode dsmode; |
murgatroid99 | dedb923 | 2016-09-26 13:54:04 -0700 | [diff] [blame] | 361 | err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode, |
| 362 | &fd); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 363 | if (err != GRPC_ERROR_NONE) return err; |
Yuchen Zeng | 68745bb | 2017-03-14 17:51:07 -0700 | [diff] [blame] | 364 | err = grpc_tcp_server_prepare_socket(fd, &listener->addr, true, &port); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 365 | if (err != GRPC_ERROR_NONE) return err; |
Craig Tiller | 644da98 | 2016-05-19 09:19:28 -0700 | [diff] [blame] | 366 | listener->server->nports++; |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 367 | grpc_sockaddr_to_string(&addr_str, &listener->addr, 1); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 368 | gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str, i); |
Yash Tibrewal | ca3c1c0 | 2017-09-07 22:47:16 -0700 | [diff] [blame] | 369 | sp = (grpc_tcp_listener *)gpr_malloc(sizeof(grpc_tcp_listener)); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 370 | sp->next = listener->next; |
| 371 | listener->next = sp; |
Dan Born | ad1f31f | 2016-07-08 13:24:49 -0700 | [diff] [blame] | 372 | /* sp (the new listener) is a sibling of 'listener' (the original |
| 373 | listener). */ |
| 374 | sp->is_sibling = 1; |
| 375 | sp->sibling = listener->sibling; |
| 376 | listener->sibling = sp; |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 377 | sp->server = listener->server; |
| 378 | sp->fd = fd; |
| 379 | sp->emfd = grpc_fd_create(fd, name); |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 380 | memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address)); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 381 | sp->port = port; |
| 382 | sp->port_index = listener->port_index; |
| 383 | sp->fd_index = listener->fd_index + count - i; |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 384 | GPR_ASSERT(sp->emfd); |
| 385 | while (listener->server->tail->next != NULL) { |
| 386 | listener->server->tail = listener->server->tail->next; |
| 387 | } |
| 388 | gpr_free(addr_str); |
| 389 | gpr_free(name); |
| 390 | } |
| 391 | |
| 392 | return GRPC_ERROR_NONE; |
| 393 | } |
| 394 | |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 395 | grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, |
| 396 | const grpc_resolved_address *addr, |
| 397 | int *out_port) { |
Nicolas Noble | 8f71462 | 2015-11-19 11:16:54 -0800 | [diff] [blame] | 398 | grpc_tcp_listener *sp; |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 399 | grpc_resolved_address sockname_temp; |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 400 | grpc_resolved_address addr6_v4mapped; |
| 401 | int requested_port = grpc_sockaddr_get_port(addr); |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 402 | unsigned port_index = 0; |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 403 | grpc_dualstack_mode dsmode; |
| 404 | grpc_error *err; |
| 405 | *out_port = -1; |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 406 | if (s->tail != NULL) { |
| 407 | port_index = s->tail->port_index + 1; |
| 408 | } |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 409 | grpc_unlink_if_unix_domain_socket(addr); |
Craig Tiller | aa31da4 | 2015-02-17 16:33:35 -0800 | [diff] [blame] | 410 | |
ctiller | 570d1f4 | 2015-01-12 16:29:52 -0800 | [diff] [blame] | 411 | /* Check if this is a wildcard port, and if so, try to keep the port the same |
| 412 | as some previously created listener. */ |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 413 | if (requested_port == 0) { |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 414 | for (sp = s->head; sp; sp = sp->next) { |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 415 | sockname_temp.len = sizeof(struct sockaddr_storage); |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 416 | if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp.addr, |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 417 | (socklen_t *)&sockname_temp.len)) { |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 418 | int used_port = grpc_sockaddr_get_port(&sockname_temp); |
| 419 | if (used_port > 0) { |
| 420 | memcpy(&sockname_temp, addr, sizeof(grpc_resolved_address)); |
| 421 | grpc_sockaddr_set_port(&sockname_temp, used_port); |
| 422 | requested_port = used_port; |
| 423 | addr = &sockname_temp; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 424 | break; |
| 425 | } |
| 426 | } |
ctiller | 570d1f4 | 2015-01-12 16:29:52 -0800 | [diff] [blame] | 427 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 428 | } |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 429 | if (grpc_sockaddr_is_wildcard(addr, &requested_port)) { |
| 430 | return add_wildcard_addrs_to_server(s, port_index, requested_port, |
| 431 | out_port); |
| 432 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 433 | if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) { |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 434 | addr = &addr6_v4mapped; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 435 | } |
Yuchen Zeng | 47155ed | 2017-03-13 17:18:07 -0700 | [diff] [blame] | 436 | if ((err = grpc_tcp_server_add_addr(s, addr, port_index, 0, &dsmode, &sp)) == |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 437 | GRPC_ERROR_NONE) { |
Craig Tiller | c027e77 | 2016-05-03 16:27:00 -0700 | [diff] [blame] | 438 | *out_port = sp->port; |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 439 | } |
Dan Born | 8886a81 | 2016-07-08 16:06:07 -0700 | [diff] [blame] | 440 | return err; |
nnoble | 0c475f0 | 2014-12-05 15:37:39 -0800 | [diff] [blame] | 441 | } |
| 442 | |
Dan Born | 19e01fd | 2016-10-18 11:49:45 -0700 | [diff] [blame] | 443 | /* Return listener at port_index or NULL. Should only be called with s->mu |
| 444 | locked. */ |
Dan Born | 4e826be | 2016-10-03 20:33:25 -0700 | [diff] [blame] | 445 | static grpc_tcp_listener *get_port_index(grpc_tcp_server *s, |
| 446 | unsigned port_index) { |
| 447 | unsigned num_ports = 0; |
| 448 | grpc_tcp_listener *sp; |
| 449 | for (sp = s->head; sp; sp = sp->next) { |
| 450 | if (!sp->is_sibling) { |
| 451 | if (++num_ports > port_index) { |
| 452 | return sp; |
| 453 | } |
| 454 | } |
| 455 | } |
| 456 | return NULL; |
| 457 | } |
| 458 | |
Dan Born | 5d81d15 | 2016-01-12 20:29:29 -0800 | [diff] [blame] | 459 | unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s, |
| 460 | unsigned port_index) { |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 461 | unsigned num_fds = 0; |
Dan Born | 930c298 | 2016-09-08 19:12:18 -0700 | [diff] [blame] | 462 | gpr_mu_lock(&s->mu); |
Dan Born | 4e826be | 2016-10-03 20:33:25 -0700 | [diff] [blame] | 463 | grpc_tcp_listener *sp = get_port_index(s, port_index); |
| 464 | for (; sp; sp = sp->sibling) { |
| 465 | ++num_fds; |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 466 | } |
Dan Born | 930c298 | 2016-09-08 19:12:18 -0700 | [diff] [blame] | 467 | gpr_mu_unlock(&s->mu); |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 468 | return num_fds; |
| 469 | } |
| 470 | |
Dan Born | 5d81d15 | 2016-01-12 20:29:29 -0800 | [diff] [blame] | 471 | int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index, |
| 472 | unsigned fd_index) { |
Dan Born | 930c298 | 2016-09-08 19:12:18 -0700 | [diff] [blame] | 473 | gpr_mu_lock(&s->mu); |
Dan Born | 4e826be | 2016-10-03 20:33:25 -0700 | [diff] [blame] | 474 | grpc_tcp_listener *sp = get_port_index(s, port_index); |
| 475 | for (; sp; sp = sp->sibling, --fd_index) { |
| 476 | if (fd_index == 0) { |
Dan Born | d9b763b | 2016-10-17 15:00:20 -0700 | [diff] [blame] | 477 | gpr_mu_unlock(&s->mu); |
Dan Born | 4e826be | 2016-10-03 20:33:25 -0700 | [diff] [blame] | 478 | return sp->fd; |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 479 | } |
| 480 | } |
Dan Born | 930c298 | 2016-09-08 19:12:18 -0700 | [diff] [blame] | 481 | gpr_mu_unlock(&s->mu); |
Dan Born | 4e826be | 2016-10-03 20:33:25 -0700 | [diff] [blame] | 482 | return -1; |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 483 | } |
| 484 | |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 485 | void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s, |
| 486 | grpc_pollset **pollsets, size_t pollset_count, |
| 487 | grpc_tcp_server_cb on_accept_cb, |
| 488 | void *on_accept_cb_arg) { |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 489 | size_t i; |
Nicolas Noble | 8f71462 | 2015-11-19 11:16:54 -0800 | [diff] [blame] | 490 | grpc_tcp_listener *sp; |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 491 | GPR_ASSERT(on_accept_cb); |
| 492 | gpr_mu_lock(&s->mu); |
| 493 | GPR_ASSERT(!s->on_accept_cb); |
| 494 | GPR_ASSERT(s->active_ports == 0); |
Robbie Shade | 3cd2d18 | 2015-08-28 14:30:35 -0400 | [diff] [blame] | 495 | s->on_accept_cb = on_accept_cb; |
| 496 | s->on_accept_cb_arg = on_accept_cb_arg; |
Craig Tiller | 0189ac0 | 2015-05-11 14:59:19 -0700 | [diff] [blame] | 497 | s->pollsets = pollsets; |
| 498 | s->pollset_count = pollset_count; |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 499 | sp = s->head; |
| 500 | while (sp != NULL) { |
murgatroid99 | 7871f73 | 2016-09-23 13:49:05 -0700 | [diff] [blame] | 501 | if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr) && |
Yuchen Zeng | d745a6f | 2016-08-08 20:44:36 -0700 | [diff] [blame] | 502 | pollset_count > 1) { |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 503 | GPR_ASSERT(GRPC_LOG_IF_ERROR( |
| 504 | "clone_port", clone_port(sp, (unsigned)(pollset_count - 1)))); |
| 505 | for (i = 0; i < pollset_count; i++) { |
| 506 | grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd); |
ncteisen | 274bbbe | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 507 | GRPC_CLOSURE_INIT(&sp->read_closure, on_read, sp, |
Craig Tiller | 3cb3447 | 2016-12-28 16:11:38 -0800 | [diff] [blame] | 508 | grpc_schedule_on_exec_ctx); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 509 | grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); |
| 510 | s->active_ports++; |
| 511 | sp = sp->next; |
| 512 | } |
| 513 | } else { |
| 514 | for (i = 0; i < pollset_count; i++) { |
| 515 | grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd); |
| 516 | } |
ncteisen | 274bbbe | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 517 | GRPC_CLOSURE_INIT(&sp->read_closure, on_read, sp, |
Craig Tiller | 3cb3447 | 2016-12-28 16:11:38 -0800 | [diff] [blame] | 518 | grpc_schedule_on_exec_ctx); |
Craig Tiller | ef96264 | 2016-05-18 22:57:17 -0700 | [diff] [blame] | 519 | grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure); |
| 520 | s->active_ports++; |
| 521 | sp = sp->next; |
ctiller | 58393c2 | 2015-01-07 14:03:30 -0800 | [diff] [blame] | 522 | } |
Craig Tiller | a82950e | 2015-09-22 12:33:20 -0700 | [diff] [blame] | 523 | } |
| 524 | gpr_mu_unlock(&s->mu); |
Nicolas Noble | b7ebd3b | 2014-11-26 16:33:03 -0800 | [diff] [blame] | 525 | } |
Craig Tiller | 0c0b60c | 2015-01-21 15:49:28 -0800 | [diff] [blame] | 526 | |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 527 | grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) { |
Dan Born | 930c298 | 2016-09-08 19:12:18 -0700 | [diff] [blame] | 528 | gpr_ref_non_zero(&s->refs); |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 529 | return s; |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 530 | } |
| 531 | |
Dan Born | 9c12bc2 | 2016-01-13 16:52:20 -0800 | [diff] [blame] | 532 | void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s, |
| 533 | grpc_closure *shutdown_starting) { |
| 534 | gpr_mu_lock(&s->mu); |
Craig Tiller | c027e77 | 2016-05-03 16:27:00 -0700 | [diff] [blame] | 535 | grpc_closure_list_append(&s->shutdown_starting, shutdown_starting, |
| 536 | GRPC_ERROR_NONE); |
Dan Born | 9c12bc2 | 2016-01-13 16:52:20 -0800 | [diff] [blame] | 537 | gpr_mu_unlock(&s->mu); |
| 538 | } |
| 539 | |
Dan Born | fa6b606 | 2016-01-08 21:01:59 -0800 | [diff] [blame] | 540 | void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) { |
| 541 | if (gpr_unref(&s->refs)) { |
Dan Born | 930c298 | 2016-09-08 19:12:18 -0700 | [diff] [blame] | 542 | grpc_tcp_server_shutdown_listeners(exec_ctx, s); |
Dan Born | 9c12bc2 | 2016-01-13 16:52:20 -0800 | [diff] [blame] | 543 | gpr_mu_lock(&s->mu); |
ncteisen | 274bbbe | 2017-06-08 14:57:11 -0700 | [diff] [blame] | 544 | GRPC_CLOSURE_LIST_SCHED(exec_ctx, &s->shutdown_starting); |
Dan Born | 9c12bc2 | 2016-01-13 16:52:20 -0800 | [diff] [blame] | 545 | gpr_mu_unlock(&s->mu); |
Dan Born | 930c298 | 2016-09-08 19:12:18 -0700 | [diff] [blame] | 546 | tcp_server_destroy(exec_ctx, s); |
Nicolas Noble | 5eb4e1c | 2015-11-18 17:19:45 -0800 | [diff] [blame] | 547 | } |
| 548 | } |
| 549 | |
yang-g | 9275d40 | 2016-07-11 16:51:39 -0700 | [diff] [blame] | 550 | void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx, |
| 551 | grpc_tcp_server *s) { |
| 552 | gpr_mu_lock(&s->mu); |
Craig Tiller | f26236a | 2017-03-07 09:43:51 -0800 | [diff] [blame] | 553 | s->shutdown_listeners = true; |
yang-g | 9275d40 | 2016-07-11 16:51:39 -0700 | [diff] [blame] | 554 | /* shutdown all fd's */ |
| 555 | if (s->active_ports) { |
| 556 | grpc_tcp_listener *sp; |
| 557 | for (sp = s->head; sp; sp = sp->next) { |
Craig Tiller | cda759d | 2017-01-27 11:37:37 -0800 | [diff] [blame] | 558 | grpc_fd_shutdown(exec_ctx, sp->emfd, |
ncteisen | 4b36a3d | 2017-03-13 19:08:06 -0700 | [diff] [blame] | 559 | GRPC_ERROR_CREATE_FROM_STATIC_STRING("Server shutdown")); |
yang-g | 9275d40 | 2016-07-11 16:51:39 -0700 | [diff] [blame] | 560 | } |
| 561 | } |
| 562 | gpr_mu_unlock(&s->mu); |
| 563 | } |
| 564 | |
Craig Tiller | 190d360 | 2015-02-18 09:23:38 -0800 | [diff] [blame] | 565 | #endif |