blob: 2d3f6cf9a7dc0da5f35a4e0f98ac2026ed36d9ca [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, Google Inc.
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08004 * 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
David Klempner78b79922015-02-04 10:18:59 -080034/* FIXME: "posix" files shouldn't be depending on _GNU_SOURCE */
35#ifndef _GNU_SOURCE
36#define _GNU_SOURCE
37#endif
38
Craig Tiller0c0b60c2015-01-21 15:49:28 -080039#include <grpc/support/port_platform.h>
40
Craig Tillera172ad72015-01-21 15:51:47 -080041#ifdef GPR_POSIX_SOCKET
Craig Tiller0c0b60c2015-01-21 15:49:28 -080042
Craig Tiller9533d042016-03-25 17:11:06 -070043#include "src/core/lib/iomgr/tcp_server.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080044
Craig Tilleraa31da42015-02-17 16:33:35 -080045#include <errno.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080046#include <fcntl.h>
Craig Tilleraa31da42015-02-17 16:33:35 -080047#include <limits.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080048#include <netinet/in.h>
49#include <netinet/tcp.h>
50#include <stdio.h>
Craig Tilleraa31da42015-02-17 16:33:35 -080051#include <string.h>
52#include <sys/socket.h>
53#include <sys/stat.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080054#include <sys/types.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055#include <unistd.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056
Craig Tillerf40df232016-03-25 13:38:14 -070057#include <grpc/support/alloc.h>
58#include <grpc/support/log.h>
59#include <grpc/support/string_util.h>
60#include <grpc/support/sync.h>
61#include <grpc/support/time.h>
Craig Tillerc027e772016-05-03 16:27:00 -070062#include <grpc/support/useful.h>
63
Craig Tiller9533d042016-03-25 17:11:06 -070064#include "src/core/lib/iomgr/resolve_address.h"
65#include "src/core/lib/iomgr/sockaddr_utils.h"
66#include "src/core/lib/iomgr/socket_utils_posix.h"
67#include "src/core/lib/iomgr/tcp_posix.h"
68#include "src/core/lib/iomgr/unix_sockets_posix.h"
69#include "src/core/lib/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080070
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080071#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
72
73static gpr_once s_init_max_accept_queue_size;
74static int s_max_accept_queue_size;
75
76/* one listening port */
Dan Bornfa6b6062016-01-08 21:01:59 -080077typedef struct grpc_tcp_listener grpc_tcp_listener;
Nicolas Noble8f714622015-11-19 11:16:54 -080078struct grpc_tcp_listener {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080079 int fd;
ctiller18b49ab2014-12-09 14:39:16 -080080 grpc_fd *emfd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080081 grpc_tcp_server *server;
Craig Tillera82950e2015-09-22 12:33:20 -070082 union {
Craig Tiller7536af02015-12-22 13:49:30 -080083 uint8_t untyped[GRPC_MAX_SOCKADDR_SIZE];
Craig Tiller772c97b2015-02-17 08:07:34 -080084 struct sockaddr sockaddr;
Craig Tiller772c97b2015-02-17 08:07:34 -080085 } addr;
Craig Tillerf96dfc32015-09-10 14:43:18 -070086 size_t addr_len;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080087 int port;
Dan Bornfa6b6062016-01-08 21:01:59 -080088 unsigned port_index;
89 unsigned fd_index;
Craig Tiller33825112015-09-18 07:44:19 -070090 grpc_closure read_closure;
91 grpc_closure destroyed_closure;
Nicolas Noble8f714622015-11-19 11:16:54 -080092 struct grpc_tcp_listener *next;
Dan Bornad1f31f2016-07-08 13:24:49 -070093 /* sibling is a linked list of all listeners for a given port. add_port and
94 clone_port place all new listeners in the same sibling list. A member of
95 the 'sibling' list is also a member of the 'next' list. The head of each
96 sibling list has is_sibling==0, and subsequent members of sibling lists
97 have is_sibling==1. is_sibling allows separate sibling lists to be
98 identified while iterating through 'next'. */
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +010099 struct grpc_tcp_listener *sibling;
100 int is_sibling;
Nicolas Noble8f714622015-11-19 11:16:54 -0800101};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800102
103/* the overall server */
Craig Tillera82950e2015-09-22 12:33:20 -0700104struct grpc_tcp_server {
Dan Bornfa6b6062016-01-08 21:01:59 -0800105 gpr_refcount refs;
Robbie Shade3cd2d182015-08-28 14:30:35 -0400106 /* Called whenever accept() succeeds on a server port. */
107 grpc_tcp_server_cb on_accept_cb;
108 void *on_accept_cb_arg;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109
110 gpr_mu mu;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800111
112 /* active port count: how many ports are actually still listening */
Craig Tilleraec96aa2015-04-07 14:32:15 -0700113 size_t active_ports;
114 /* destroyed port count: how many ports are completely destroyed */
115 size_t destroyed_ports;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800116
Craig Tilleref962642016-05-18 22:57:17 -0700117 /* is this server shutting down? */
118 bool shutdown;
119 /* use SO_REUSEPORT */
120 bool so_reuseport;
Craig Tiller6f051402015-05-13 11:42:42 -0700121
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800122 /* linked list of server ports */
Nicolas Noble8f714622015-11-19 11:16:54 -0800123 grpc_tcp_listener *head;
Dan Bornfa6b6062016-01-08 21:01:59 -0800124 grpc_tcp_listener *tail;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800125 unsigned nports;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700126
Dan Born9c12bc22016-01-13 16:52:20 -0800127 /* List of closures passed to shutdown_starting_add(). */
128 grpc_closure_list shutdown_starting;
129
Craig Tilleraec96aa2015-04-07 14:32:15 -0700130 /* shutdown callback */
Craig Tillerd1bec032015-09-18 17:29:00 -0700131 grpc_closure *shutdown_complete;
Craig Tiller0189ac02015-05-11 14:59:19 -0700132
Craig Tiller6174b9a2015-06-18 08:13:05 -0700133 /* all pollsets interested in new connections */
Craig Tiller0189ac02015-05-11 14:59:19 -0700134 grpc_pollset **pollsets;
Craig Tiller6174b9a2015-06-18 08:13:05 -0700135 /* number of pollsets in the pollsets array */
Craig Tiller0189ac02015-05-11 14:59:19 -0700136 size_t pollset_count;
Craig Tiller53dd6b92016-05-24 13:49:50 -0700137
138 /* next pollset to assign a channel to */
Craig Tillerb76471d2016-07-01 10:24:56 -0700139 gpr_atm next_pollset_to_assign;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800140};
141
Craig Tilleref962642016-05-18 22:57:17 -0700142static gpr_once check_init = GPR_ONCE_INIT;
Nicolas "Pixel" Noblebaa35fc2016-08-19 02:20:11 +0200143static bool has_so_reuseport = false;
Craig Tilleref962642016-05-18 22:57:17 -0700144
145static void init(void) {
Nicolas "Pixel" Noblebaa35fc2016-08-19 02:20:11 +0200146#ifndef GPR_MANYLINUX1
Craig Tilleref962642016-05-18 22:57:17 -0700147 int s = socket(AF_INET, SOCK_STREAM, 0);
148 if (s >= 0) {
149 has_so_reuseport = GRPC_LOG_IF_ERROR("check for SO_REUSEPORT",
150 grpc_set_socket_reuse_port(s, 1));
151 close(s);
152 }
Nicolas "Pixel" Noblebaa35fc2016-08-19 02:20:11 +0200153#endif
Craig Tilleref962642016-05-18 22:57:17 -0700154}
155
Craig Tiller0b5857f2016-05-04 10:58:06 -0700156grpc_error *grpc_tcp_server_create(grpc_closure *shutdown_complete,
Craig Tilleref962642016-05-18 22:57:17 -0700157 const grpc_channel_args *args,
Craig Tiller0b5857f2016-05-04 10:58:06 -0700158 grpc_tcp_server **server) {
Craig Tilleref962642016-05-18 22:57:17 -0700159 gpr_once_init(&check_init, init);
160
Craig Tillera82950e2015-09-22 12:33:20 -0700161 grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
Craig Tilleref962642016-05-18 22:57:17 -0700162 s->so_reuseport = has_so_reuseport;
163 for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
164 if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) {
165 if (args->args[i].type == GRPC_ARG_INTEGER) {
166 s->so_reuseport =
167 has_so_reuseport && (args->args[i].value.integer != 0);
168 } else {
169 gpr_free(s);
170 return GRPC_ERROR_CREATE(GRPC_ARG_ALLOW_REUSEPORT
171 " must be an integer");
172 }
173 }
174 }
Dan Bornfa6b6062016-01-08 21:01:59 -0800175 gpr_ref_init(&s->refs, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700176 gpr_mu_init(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800177 s->active_ports = 0;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700178 s->destroyed_ports = 0;
Craig Tilleref962642016-05-18 22:57:17 -0700179 s->shutdown = false;
Dan Born9c12bc22016-01-13 16:52:20 -0800180 s->shutdown_starting.head = NULL;
181 s->shutdown_starting.tail = NULL;
Dan Bornfa6b6062016-01-08 21:01:59 -0800182 s->shutdown_complete = shutdown_complete;
Robbie Shade3cd2d182015-08-28 14:30:35 -0400183 s->on_accept_cb = NULL;
184 s->on_accept_cb_arg = NULL;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800185 s->head = NULL;
Dan Bornfa6b6062016-01-08 21:01:59 -0800186 s->tail = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800187 s->nports = 0;
Craig Tillerb76471d2016-07-01 10:24:56 -0700188 gpr_atm_no_barrier_store(&s->next_pollset_to_assign, 0);
Craig Tiller0b5857f2016-05-04 10:58:06 -0700189 *server = s;
190 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800191}
192
Craig Tillera82950e2015-09-22 12:33:20 -0700193static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800194 if (s->shutdown_complete != NULL) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700195 grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
Dan Bornfa6b6062016-01-08 21:01:59 -0800196 }
Craig Tilleraec96aa2015-04-07 14:32:15 -0700197
Craig Tillera82950e2015-09-22 12:33:20 -0700198 gpr_mu_destroy(&s->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700199
Nicolas "Pixel" Noblec6a7c6e2015-11-19 21:55:44 +0100200 while (s->head) {
201 grpc_tcp_listener *sp = s->head;
202 s->head = sp->next;
Dan Bornfa6b6062016-01-08 21:01:59 -0800203 gpr_free(sp);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800204 }
205
Craig Tillera82950e2015-09-22 12:33:20 -0700206 gpr_free(s);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700207}
208
Craig Tiller6c396862016-01-28 13:53:40 -0800209static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
Craig Tillerc027e772016-05-03 16:27:00 -0700210 grpc_error *error) {
Craig Tilleraec96aa2015-04-07 14:32:15 -0700211 grpc_tcp_server *s = server;
Craig Tillera82950e2015-09-22 12:33:20 -0700212 gpr_mu_lock(&s->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700213 s->destroyed_ports++;
Craig Tillera82950e2015-09-22 12:33:20 -0700214 if (s->destroyed_ports == s->nports) {
215 gpr_mu_unlock(&s->mu);
216 finish_shutdown(exec_ctx, s);
217 } else {
218 GPR_ASSERT(s->destroyed_ports < s->nports);
219 gpr_mu_unlock(&s->mu);
220 }
Craig Tilleraec96aa2015-04-07 14:32:15 -0700221}
222
Craig Tiller6174b9a2015-06-18 08:13:05 -0700223/* called when all listening endpoints have been shutdown, so no further
224 events will be received on them - at this point it's safe to destroy
225 things */
Craig Tillera82950e2015-09-22 12:33:20 -0700226static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800227 /* delete ALL the things */
Craig Tillera82950e2015-09-22 12:33:20 -0700228 gpr_mu_lock(&s->mu);
Craig Tiller6f051402015-05-13 11:42:42 -0700229
Craig Tillera82950e2015-09-22 12:33:20 -0700230 if (!s->shutdown) {
231 gpr_mu_unlock(&s->mu);
232 return;
233 }
Craig Tiller45724b32015-09-22 10:42:19 -0700234
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800235 if (s->head) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800236 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800237 for (sp = s->head; sp; sp = sp->next) {
ahedbergfcbcbff2016-03-22 13:23:47 -0400238 grpc_unlink_if_unix_domain_socket(&sp->addr.sockaddr);
Craig Tillera82950e2015-09-22 12:33:20 -0700239 sp->destroyed_closure.cb = destroyed_port;
240 sp->destroyed_closure.cb_arg = s;
yang-g5d850372015-12-01 10:32:28 -0800241 grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
Craig Tillera82950e2015-09-22 12:33:20 -0700242 "tcp_listener_shutdown");
Craig Tiller45724b32015-09-22 10:42:19 -0700243 }
Craig Tillera82950e2015-09-22 12:33:20 -0700244 gpr_mu_unlock(&s->mu);
245 } else {
246 gpr_mu_unlock(&s->mu);
247 finish_shutdown(exec_ctx, s);
248 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800249}
250
Dan Born5d81d152016-01-12 20:29:29 -0800251static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Craig Tillera82950e2015-09-22 12:33:20 -0700252 gpr_mu_lock(&s->mu);
Craig Tiller6f051402015-05-13 11:42:42 -0700253
Craig Tillera82950e2015-09-22 12:33:20 -0700254 GPR_ASSERT(!s->shutdown);
Craig Tilleref962642016-05-18 22:57:17 -0700255 s->shutdown = true;
Craig Tiller6f051402015-05-13 11:42:42 -0700256
Craig Tiller6f051402015-05-13 11:42:42 -0700257 /* shutdown all fd's */
Craig Tillera82950e2015-09-22 12:33:20 -0700258 if (s->active_ports) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800259 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800260 for (sp = s->head; sp; sp = sp->next) {
261 grpc_fd_shutdown(exec_ctx, sp->emfd);
Craig Tiller6f051402015-05-13 11:42:42 -0700262 }
Craig Tillera82950e2015-09-22 12:33:20 -0700263 gpr_mu_unlock(&s->mu);
264 } else {
265 gpr_mu_unlock(&s->mu);
266 deactivated_all_ports(exec_ctx, s);
267 }
Craig Tiller6f051402015-05-13 11:42:42 -0700268}
269
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800270/* get max listen queue size on linux */
Craig Tillera82950e2015-09-22 12:33:20 -0700271static void init_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800272 int n = SOMAXCONN;
273 char buf[64];
Craig Tillera82950e2015-09-22 12:33:20 -0700274 FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
275 if (fp == NULL) {
276 /* 2.4 kernel. */
277 s_max_accept_queue_size = SOMAXCONN;
278 return;
279 }
280 if (fgets(buf, sizeof buf, fp)) {
281 char *end;
282 long i = strtol(buf, &end, 10);
283 if (i > 0 && i <= INT_MAX && end && *end == 0) {
284 n = (int)i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800285 }
Craig Tillera82950e2015-09-22 12:33:20 -0700286 }
287 fclose(fp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800288 s_max_accept_queue_size = n;
289
Craig Tillera82950e2015-09-22 12:33:20 -0700290 if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
291 gpr_log(GPR_INFO,
292 "Suspiciously small accept queue (%d) will probably lead to "
293 "connection drops",
294 s_max_accept_queue_size);
295 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800296}
297
Craig Tillera82950e2015-09-22 12:33:20 -0700298static int get_max_accept_queue_size(void) {
299 gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800300 return s_max_accept_queue_size;
301}
302
nnoble0c475f02014-12-05 15:37:39 -0800303/* Prepare a recently-created socket for listening. */
Craig Tiller80384bd2016-05-06 16:12:31 -0700304static grpc_error *prepare_socket(int fd, const struct sockaddr *addr,
Craig Tilleref962642016-05-18 22:57:17 -0700305 size_t addr_len, bool so_reuseport,
306 int *port) {
ctiller570d1f42015-01-12 16:29:52 -0800307 struct sockaddr_storage sockname_temp;
308 socklen_t sockname_len;
Craig Tiller80384bd2016-05-06 16:12:31 -0700309 grpc_error *err = GRPC_ERROR_NONE;
ctiller570d1f42015-01-12 16:29:52 -0800310
Craig Tiller80384bd2016-05-06 16:12:31 -0700311 GPR_ASSERT(fd >= 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800312
Yuchen Zeng2414bbb2016-08-08 21:22:54 -0700313 if (so_reuseport && !grpc_is_unix_socket(addr)) {
Craig Tilleref962642016-05-18 22:57:17 -0700314 err = grpc_set_socket_reuse_port(fd, 1);
315 if (err != GRPC_ERROR_NONE) goto error;
316 }
317
Craig Tiller80384bd2016-05-06 16:12:31 -0700318 err = grpc_set_socket_nonblocking(fd, 1);
319 if (err != GRPC_ERROR_NONE) goto error;
320 err = grpc_set_socket_cloexec(fd, 1);
321 if (err != GRPC_ERROR_NONE) goto error;
322 if (!grpc_is_unix_socket(addr)) {
323 err = grpc_set_socket_low_latency(fd, 1);
324 if (err != GRPC_ERROR_NONE) goto error;
325 err = grpc_set_socket_reuse_addr(fd, 1);
326 if (err != GRPC_ERROR_NONE) goto error;
Craig Tillera82950e2015-09-22 12:33:20 -0700327 }
Craig Tiller80384bd2016-05-06 16:12:31 -0700328 err = grpc_set_socket_no_sigpipe_if_possible(fd);
329 if (err != GRPC_ERROR_NONE) goto error;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800330
Craig Tillera82950e2015-09-22 12:33:20 -0700331 GPR_ASSERT(addr_len < ~(socklen_t)0);
332 if (bind(fd, addr, (socklen_t)addr_len) < 0) {
David Garcia Quintas03291c42016-05-10 18:28:56 -0700333 err = GRPC_OS_ERROR(errno, "bind");
Craig Tillera82950e2015-09-22 12:33:20 -0700334 goto error;
335 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800336
Craig Tillera82950e2015-09-22 12:33:20 -0700337 if (listen(fd, get_max_accept_queue_size()) < 0) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700338 err = GRPC_OS_ERROR(errno, "listen");
Craig Tillera82950e2015-09-22 12:33:20 -0700339 goto error;
340 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800341
Craig Tillera82950e2015-09-22 12:33:20 -0700342 sockname_len = sizeof(sockname_temp);
343 if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700344 err = GRPC_OS_ERROR(errno, "getsockname");
Craig Tillera82950e2015-09-22 12:33:20 -0700345 goto error;
346 }
ctiller570d1f42015-01-12 16:29:52 -0800347
Craig Tiller80384bd2016-05-06 16:12:31 -0700348 *port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
349 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800350
351error:
Craig Tiller94f84532016-05-06 21:03:29 -0700352 GPR_ASSERT(err != GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700353 if (fd >= 0) {
354 close(fd);
355 }
David Garcia Quintas32ec1332016-05-11 12:22:53 -0700356 grpc_error *ret = grpc_error_set_int(
Craig Tiller80384bd2016-05-06 16:12:31 -0700357 GRPC_ERROR_CREATE_REFERENCING("Unable to configure socket", &err, 1),
358 GRPC_ERROR_INT_FD, fd);
David Garcia Quintas32ec1332016-05-11 12:22:53 -0700359 GRPC_ERROR_UNREF(err);
360 return ret;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800361}
362
363/* event manager callback when reads are ready */
Craig Tillerc027e772016-05-03 16:27:00 -0700364static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800365 grpc_tcp_listener *sp = arg;
Dan Born5d81d152016-01-12 20:29:29 -0800366 grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index,
367 sp->fd_index};
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700368 grpc_pollset *read_notifier_pollset = NULL;
Craig Tiller0189ac02015-05-11 14:59:19 -0700369 grpc_fd *fdobj;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800370
Craig Tillerc027e772016-05-03 16:27:00 -0700371 if (err != GRPC_ERROR_NONE) {
Craig Tillera82950e2015-09-22 12:33:20 -0700372 goto error;
373 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800374
Craig Tiller53dd6b92016-05-24 13:49:50 -0700375 read_notifier_pollset =
Craig Tillerb76471d2016-07-01 10:24:56 -0700376 sp->server->pollsets[(size_t)gpr_atm_no_barrier_fetch_add(
377 &sp->server->next_pollset_to_assign, 1) %
Craig Tiller53dd6b92016-05-24 13:49:50 -0700378 sp->server->pollset_count];
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700379
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800380 /* loop until accept4 returns EAGAIN, and then re-arm notification */
Craig Tillera82950e2015-09-22 12:33:20 -0700381 for (;;) {
382 struct sockaddr_storage addr;
383 socklen_t addrlen = sizeof(addr);
384 char *addr_str;
385 char *name;
386 /* Note: If we ever decide to return this address to the user, remember to
387 strip off the ::ffff:0.0.0.0/96 prefix first. */
388 int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
389 if (fd < 0) {
390 switch (errno) {
391 case EINTR:
392 continue;
393 case EAGAIN:
394 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
395 return;
396 default:
397 gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
398 goto error;
399 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800400 }
401
Craig Tillera82950e2015-09-22 12:33:20 -0700402 grpc_set_socket_no_sigpipe_if_possible(fd);
403
404 addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr);
405 gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
406
407 if (grpc_tcp_trace) {
408 gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str);
409 }
410
411 fdobj = grpc_fd_create(fd, name);
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700412
413 if (read_notifier_pollset == NULL) {
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700414 gpr_log(GPR_ERROR, "Read notifier pollset is not set on the fd");
415 goto error;
Craig Tillera82950e2015-09-22 12:33:20 -0700416 }
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700417
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700418 grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj);
419
Craig Tillera82950e2015-09-22 12:33:20 -0700420 sp->server->on_accept_cb(
421 exec_ctx, sp->server->on_accept_cb_arg,
Dan Bornfa6b6062016-01-08 21:01:59 -0800422 grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str),
Craig Tiller418a8212016-05-16 16:27:51 -0700423 read_notifier_pollset, &acceptor);
Craig Tillera82950e2015-09-22 12:33:20 -0700424
425 gpr_free(name);
426 gpr_free(addr_str);
427 }
428
yang-gb063c872015-10-07 11:40:13 -0700429 GPR_UNREACHABLE_CODE(return );
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800430
431error:
Craig Tillera82950e2015-09-22 12:33:20 -0700432 gpr_mu_lock(&sp->server->mu);
433 if (0 == --sp->server->active_ports) {
434 gpr_mu_unlock(&sp->server->mu);
435 deactivated_all_ports(exec_ctx, sp->server);
436 } else {
437 gpr_mu_unlock(&sp->server->mu);
438 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800439}
440
Craig Tiller80384bd2016-05-06 16:12:31 -0700441static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
442 const struct sockaddr *addr,
443 size_t addr_len, unsigned port_index,
444 unsigned fd_index,
445 grpc_tcp_listener **listener) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800446 grpc_tcp_listener *sp = NULL;
Craig Tiller91472962016-05-09 11:01:15 -0700447 int port = -1;
Craig Tillerfa275a92015-06-01 13:55:54 -0700448 char *addr_str;
449 char *name;
nnoble0c475f02014-12-05 15:37:39 -0800450
Craig Tilleref962642016-05-18 22:57:17 -0700451 grpc_error *err = prepare_socket(fd, addr, addr_len, s->so_reuseport, &port);
Craig Tiller80384bd2016-05-06 16:12:31 -0700452 if (err == GRPC_ERROR_NONE) {
Craig Tiller91472962016-05-09 11:01:15 -0700453 GPR_ASSERT(port > 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700454 grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
455 gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
456 gpr_mu_lock(&s->mu);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800457 s->nports++;
Craig Tillera82950e2015-09-22 12:33:20 -0700458 GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
Nicolas Noble8f714622015-11-19 11:16:54 -0800459 sp = gpr_malloc(sizeof(grpc_tcp_listener));
Dan Bornfa6b6062016-01-08 21:01:59 -0800460 sp->next = NULL;
461 if (s->head == NULL) {
462 s->head = sp;
463 } else {
464 s->tail->next = sp;
465 }
466 s->tail = sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700467 sp->server = s;
468 sp->fd = fd;
469 sp->emfd = grpc_fd_create(fd, name);
470 memcpy(sp->addr.untyped, addr, addr_len);
471 sp->addr_len = addr_len;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800472 sp->port = port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800473 sp->port_index = port_index;
474 sp->fd_index = fd_index;
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +0100475 sp->is_sibling = 0;
476 sp->sibling = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700477 GPR_ASSERT(sp->emfd);
478 gpr_mu_unlock(&s->mu);
479 gpr_free(addr_str);
480 gpr_free(name);
481 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800482
Craig Tiller80384bd2016-05-06 16:12:31 -0700483 *listener = sp;
484 return err;
nnoble0c475f02014-12-05 15:37:39 -0800485}
486
Dan Bornad1f31f2016-07-08 13:24:49 -0700487/* Insert count new listeners after listener. Every new listener will have the
488 same listen address as listener (SO_REUSEPORT must be enabled). Every new
489 listener is a sibling of listener. */
Craig Tilleref962642016-05-18 22:57:17 -0700490static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
491 grpc_tcp_listener *sp = NULL;
492 char *addr_str;
493 char *name;
494 grpc_error *err;
495
496 for (grpc_tcp_listener *l = listener->next; l && l->is_sibling; l = l->next) {
497 l->fd_index += count;
498 }
499
500 for (unsigned i = 0; i < count; i++) {
Craig Tiller136698c2016-05-19 11:49:44 -0700501 int fd = -1;
502 int port = -1;
Craig Tilleref962642016-05-18 22:57:17 -0700503 grpc_dualstack_mode dsmode;
504 err = grpc_create_dualstack_socket(&listener->addr.sockaddr, SOCK_STREAM, 0,
505 &dsmode, &fd);
506 if (err != GRPC_ERROR_NONE) return err;
507 err = prepare_socket(fd, &listener->addr.sockaddr, listener->addr_len, true,
508 &port);
509 if (err != GRPC_ERROR_NONE) return err;
Craig Tiller644da982016-05-19 09:19:28 -0700510 listener->server->nports++;
Craig Tilleref962642016-05-18 22:57:17 -0700511 grpc_sockaddr_to_string(&addr_str, &listener->addr.sockaddr, 1);
512 gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str, i);
513 sp = gpr_malloc(sizeof(grpc_tcp_listener));
514 sp->next = listener->next;
515 listener->next = sp;
Dan Bornad1f31f2016-07-08 13:24:49 -0700516 /* sp (the new listener) is a sibling of 'listener' (the original
517 listener). */
518 sp->is_sibling = 1;
519 sp->sibling = listener->sibling;
520 listener->sibling = sp;
Craig Tilleref962642016-05-18 22:57:17 -0700521 sp->server = listener->server;
522 sp->fd = fd;
523 sp->emfd = grpc_fd_create(fd, name);
524 memcpy(sp->addr.untyped, listener->addr.untyped, listener->addr_len);
525 sp->addr_len = listener->addr_len;
526 sp->port = port;
527 sp->port_index = listener->port_index;
528 sp->fd_index = listener->fd_index + count - i;
Craig Tilleref962642016-05-18 22:57:17 -0700529 GPR_ASSERT(sp->emfd);
530 while (listener->server->tail->next != NULL) {
531 listener->server->tail = listener->server->tail->next;
532 }
533 gpr_free(addr_str);
534 gpr_free(name);
535 }
536
537 return GRPC_ERROR_NONE;
538}
539
Craig Tillerc027e772016-05-03 16:27:00 -0700540grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
541 size_t addr_len, int *out_port) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800542 grpc_tcp_listener *sp;
543 grpc_tcp_listener *sp2 = NULL;
nnoble0c475f02014-12-05 15:37:39 -0800544 int fd;
545 grpc_dualstack_mode dsmode;
546 struct sockaddr_in6 addr6_v4mapped;
547 struct sockaddr_in wild4;
548 struct sockaddr_in6 wild6;
549 struct sockaddr_in addr4_copy;
ctiller570d1f42015-01-12 16:29:52 -0800550 struct sockaddr *allocated_addr = NULL;
551 struct sockaddr_storage sockname_temp;
552 socklen_t sockname_len;
nnoble0c475f02014-12-05 15:37:39 -0800553 int port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800554 unsigned port_index = 0;
555 unsigned fd_index = 0;
Craig Tillerc027e772016-05-03 16:27:00 -0700556 grpc_error *errs[2] = {GRPC_ERROR_NONE, GRPC_ERROR_NONE};
Dan Bornfa6b6062016-01-08 21:01:59 -0800557 if (s->tail != NULL) {
558 port_index = s->tail->port_index + 1;
559 }
ahedbergfcbcbff2016-03-22 13:23:47 -0400560 grpc_unlink_if_unix_domain_socket((struct sockaddr *)addr);
Craig Tilleraa31da42015-02-17 16:33:35 -0800561
ctiller570d1f42015-01-12 16:29:52 -0800562 /* Check if this is a wildcard port, and if so, try to keep the port the same
563 as some previously created listener. */
Craig Tillera82950e2015-09-22 12:33:20 -0700564 if (grpc_sockaddr_get_port(addr) == 0) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800565 for (sp = s->head; sp; sp = sp->next) {
Craig Tillera82950e2015-09-22 12:33:20 -0700566 sockname_len = sizeof(sockname_temp);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800567 if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
Craig Tillera82950e2015-09-22 12:33:20 -0700568 &sockname_len)) {
569 port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
570 if (port > 0) {
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100571 allocated_addr = gpr_malloc(addr_len);
Craig Tillera82950e2015-09-22 12:33:20 -0700572 memcpy(allocated_addr, addr, addr_len);
573 grpc_sockaddr_set_port(allocated_addr, port);
574 addr = allocated_addr;
575 break;
576 }
577 }
ctiller570d1f42015-01-12 16:29:52 -0800578 }
Craig Tillera82950e2015-09-22 12:33:20 -0700579 }
ctiller570d1f42015-01-12 16:29:52 -0800580
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800581 sp = NULL;
582
Craig Tillera82950e2015-09-22 12:33:20 -0700583 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
584 addr = (const struct sockaddr *)&addr6_v4mapped;
585 addr_len = sizeof(addr6_v4mapped);
586 }
nnoble0c475f02014-12-05 15:37:39 -0800587
588 /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
Craig Tillera82950e2015-09-22 12:33:20 -0700589 if (grpc_sockaddr_is_wildcard(addr, &port)) {
590 grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
nnoble0c475f02014-12-05 15:37:39 -0800591
Craig Tillera82950e2015-09-22 12:33:20 -0700592 /* Try listening on IPv6 first. */
593 addr = (struct sockaddr *)&wild6;
594 addr_len = sizeof(wild6);
Craig Tillerc027e772016-05-03 16:27:00 -0700595 errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
596 if (errs[0] == GRPC_ERROR_NONE) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700597 errs[0] = add_socket_to_server(s, fd, addr, addr_len, port_index,
598 fd_index, &sp);
Craig Tillerc027e772016-05-03 16:27:00 -0700599 if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
600 goto done;
601 }
602 if (sp != NULL) {
603 ++fd_index;
604 }
605 /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
606 if (port == 0 && sp != NULL) {
607 grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
608 }
nnoble0c475f02014-12-05 15:37:39 -0800609 }
Craig Tiller161f7632016-06-09 15:46:53 -0700610 addr = (struct sockaddr *)&wild4;
611 addr_len = sizeof(wild4);
Craig Tillera82950e2015-09-22 12:33:20 -0700612 }
613
Craig Tillerc027e772016-05-03 16:27:00 -0700614 errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
615 if (errs[1] == GRPC_ERROR_NONE) {
yang-g63460412016-03-22 14:58:15 -0700616 if (dsmode == GRPC_DSMODE_IPV4 &&
617 grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
618 addr = (struct sockaddr *)&addr4_copy;
619 addr_len = sizeof(addr4_copy);
620 }
yang-gb7921c72016-03-23 10:16:45 -0700621 sp2 = sp;
Craig Tiller80384bd2016-05-06 16:12:31 -0700622 errs[1] =
623 add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index, &sp);
yang-g63460412016-03-22 14:58:15 -0700624 if (sp2 != NULL && sp != NULL) {
625 sp2->sibling = sp;
626 sp->is_sibling = 1;
627 }
Dan Bornfa6b6062016-01-08 21:01:59 -0800628 }
ctiller570d1f42015-01-12 16:29:52 -0800629
630done:
Craig Tillera82950e2015-09-22 12:33:20 -0700631 gpr_free(allocated_addr);
Dan Bornfa6b6062016-01-08 21:01:59 -0800632 if (sp != NULL) {
Craig Tillerc027e772016-05-03 16:27:00 -0700633 *out_port = sp->port;
Craig Tillerf707d622016-05-06 14:26:12 -0700634 GRPC_ERROR_UNREF(errs[0]);
635 GRPC_ERROR_UNREF(errs[1]);
Craig Tillerc027e772016-05-03 16:27:00 -0700636 return GRPC_ERROR_NONE;
Dan Bornfa6b6062016-01-08 21:01:59 -0800637 } else {
Craig Tillerc027e772016-05-03 16:27:00 -0700638 *out_port = -1;
639 char *addr_str = grpc_sockaddr_to_uri(addr);
640 grpc_error *err = grpc_error_set_str(
641 GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", errs,
642 GPR_ARRAY_SIZE(errs)),
643 GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
David Garcia Quintas32ec1332016-05-11 12:22:53 -0700644 GRPC_ERROR_UNREF(errs[0]);
645 GRPC_ERROR_UNREF(errs[1]);
Craig Tillerc027e772016-05-03 16:27:00 -0700646 gpr_free(addr_str);
647 return err;
Dan Bornfa6b6062016-01-08 21:01:59 -0800648 }
nnoble0c475f02014-12-05 15:37:39 -0800649}
650
Dan Born5d81d152016-01-12 20:29:29 -0800651unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
652 unsigned port_index) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800653 unsigned num_fds = 0;
Nicolas Noble8f714622015-11-19 11:16:54 -0800654 grpc_tcp_listener *sp;
Dan Bornfa6b6062016-01-08 21:01:59 -0800655 for (sp = s->head; sp && port_index != 0; sp = sp->next) {
656 if (!sp->is_sibling) {
657 --port_index;
658 }
659 }
660 for (; sp; sp = sp->sibling, ++num_fds)
yang-g3ff97272015-11-20 17:01:57 -0800661 ;
Dan Bornfa6b6062016-01-08 21:01:59 -0800662 return num_fds;
663}
664
Dan Born5d81d152016-01-12 20:29:29 -0800665int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
666 unsigned fd_index) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800667 grpc_tcp_listener *sp;
668 for (sp = s->head; sp && port_index != 0; sp = sp->next) {
669 if (!sp->is_sibling) {
670 --port_index;
671 }
672 }
673 for (; sp && fd_index != 0; sp = sp->sibling, --fd_index)
674 ;
675 if (sp) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800676 return sp->fd;
677 } else {
678 return -1;
679 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800680}
681
Craig Tillera82950e2015-09-22 12:33:20 -0700682void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
683 grpc_pollset **pollsets, size_t pollset_count,
684 grpc_tcp_server_cb on_accept_cb,
685 void *on_accept_cb_arg) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800686 size_t i;
Nicolas Noble8f714622015-11-19 11:16:54 -0800687 grpc_tcp_listener *sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700688 GPR_ASSERT(on_accept_cb);
689 gpr_mu_lock(&s->mu);
690 GPR_ASSERT(!s->on_accept_cb);
691 GPR_ASSERT(s->active_ports == 0);
Robbie Shade3cd2d182015-08-28 14:30:35 -0400692 s->on_accept_cb = on_accept_cb;
693 s->on_accept_cb_arg = on_accept_cb_arg;
Craig Tiller0189ac02015-05-11 14:59:19 -0700694 s->pollsets = pollsets;
695 s->pollset_count = pollset_count;
Craig Tilleref962642016-05-18 22:57:17 -0700696 sp = s->head;
697 while (sp != NULL) {
Yuchen Zengd745a6f2016-08-08 20:44:36 -0700698 if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr.sockaddr) &&
699 pollset_count > 1) {
Craig Tilleref962642016-05-18 22:57:17 -0700700 GPR_ASSERT(GRPC_LOG_IF_ERROR(
701 "clone_port", clone_port(sp, (unsigned)(pollset_count - 1))));
702 for (i = 0; i < pollset_count; i++) {
703 grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
704 sp->read_closure.cb = on_read;
705 sp->read_closure.cb_arg = sp;
706 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
707 s->active_ports++;
708 sp = sp->next;
709 }
710 } else {
711 for (i = 0; i < pollset_count; i++) {
712 grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
713 }
714 sp->read_closure.cb = on_read;
715 sp->read_closure.cb_arg = sp;
716 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
717 s->active_ports++;
718 sp = sp->next;
ctiller58393c22015-01-07 14:03:30 -0800719 }
Craig Tillera82950e2015-09-22 12:33:20 -0700720 }
721 gpr_mu_unlock(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800722}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800723
Dan Bornfa6b6062016-01-08 21:01:59 -0800724grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
725 gpr_ref(&s->refs);
726 return s;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800727}
728
Dan Born9c12bc22016-01-13 16:52:20 -0800729void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
730 grpc_closure *shutdown_starting) {
731 gpr_mu_lock(&s->mu);
Craig Tillerc027e772016-05-03 16:27:00 -0700732 grpc_closure_list_append(&s->shutdown_starting, shutdown_starting,
733 GRPC_ERROR_NONE);
Dan Born9c12bc22016-01-13 16:52:20 -0800734 gpr_mu_unlock(&s->mu);
735}
736
Dan Bornfa6b6062016-01-08 21:01:59 -0800737void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
738 if (gpr_unref(&s->refs)) {
Dan Born9c12bc22016-01-13 16:52:20 -0800739 /* Complete shutdown_starting work before destroying. */
740 grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT;
741 gpr_mu_lock(&s->mu);
Craig Tiller6c396862016-01-28 13:53:40 -0800742 grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL);
Dan Born9c12bc22016-01-13 16:52:20 -0800743 gpr_mu_unlock(&s->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800744 if (exec_ctx == NULL) {
Dan Born9c12bc22016-01-13 16:52:20 -0800745 grpc_exec_ctx_flush(&local_exec_ctx);
Dan Born5d81d152016-01-12 20:29:29 -0800746 tcp_server_destroy(&local_exec_ctx, s);
Dan Bornfa6b6062016-01-08 21:01:59 -0800747 grpc_exec_ctx_finish(&local_exec_ctx);
748 } else {
Dan Born9c12bc22016-01-13 16:52:20 -0800749 grpc_exec_ctx_finish(&local_exec_ctx);
Dan Born5d81d152016-01-12 20:29:29 -0800750 tcp_server_destroy(exec_ctx, s);
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +0100751 }
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800752 }
753}
754
yang-g9275d402016-07-11 16:51:39 -0700755void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
756 grpc_tcp_server *s) {
757 gpr_mu_lock(&s->mu);
758 /* shutdown all fd's */
759 if (s->active_ports) {
760 grpc_tcp_listener *sp;
761 for (sp = s->head; sp; sp = sp->next) {
762 grpc_fd_shutdown(exec_ctx, sp->emfd);
763 }
764 }
765 gpr_mu_unlock(&s->mu);
766}
767
Craig Tiller190d3602015-02-18 09:23:38 -0800768#endif