blob: 73df5477e6680c2696982771ee76943e15c5dac9 [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 Born930c2982016-09-08 19:12:18 -0700194 gpr_mu_lock(&s->mu);
195 GPR_ASSERT(s->shutdown);
196 gpr_mu_unlock(&s->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800197 if (s->shutdown_complete != NULL) {
Craig Tiller332f1b32016-05-24 13:21:21 -0700198 grpc_exec_ctx_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE, NULL);
Dan Bornfa6b6062016-01-08 21:01:59 -0800199 }
Craig Tilleraec96aa2015-04-07 14:32:15 -0700200
Craig Tillera82950e2015-09-22 12:33:20 -0700201 gpr_mu_destroy(&s->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700202
Nicolas "Pixel" Noblec6a7c6e2015-11-19 21:55:44 +0100203 while (s->head) {
204 grpc_tcp_listener *sp = s->head;
205 s->head = sp->next;
Dan Bornfa6b6062016-01-08 21:01:59 -0800206 gpr_free(sp);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800207 }
208
Craig Tillera82950e2015-09-22 12:33:20 -0700209 gpr_free(s);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700210}
211
Craig Tiller6c396862016-01-28 13:53:40 -0800212static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
Craig Tillerc027e772016-05-03 16:27:00 -0700213 grpc_error *error) {
Craig Tilleraec96aa2015-04-07 14:32:15 -0700214 grpc_tcp_server *s = server;
Craig Tillera82950e2015-09-22 12:33:20 -0700215 gpr_mu_lock(&s->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700216 s->destroyed_ports++;
Craig Tillera82950e2015-09-22 12:33:20 -0700217 if (s->destroyed_ports == s->nports) {
218 gpr_mu_unlock(&s->mu);
219 finish_shutdown(exec_ctx, s);
220 } else {
221 GPR_ASSERT(s->destroyed_ports < s->nports);
222 gpr_mu_unlock(&s->mu);
223 }
Craig Tilleraec96aa2015-04-07 14:32:15 -0700224}
225
Craig Tiller6174b9a2015-06-18 08:13:05 -0700226/* called when all listening endpoints have been shutdown, so no further
227 events will be received on them - at this point it's safe to destroy
228 things */
Craig Tillera82950e2015-09-22 12:33:20 -0700229static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800230 /* delete ALL the things */
Craig Tillera82950e2015-09-22 12:33:20 -0700231 gpr_mu_lock(&s->mu);
Craig Tiller6f051402015-05-13 11:42:42 -0700232
Craig Tillera82950e2015-09-22 12:33:20 -0700233 if (!s->shutdown) {
234 gpr_mu_unlock(&s->mu);
235 return;
236 }
Craig Tiller45724b32015-09-22 10:42:19 -0700237
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800238 if (s->head) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800239 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800240 for (sp = s->head; sp; sp = sp->next) {
ahedbergfcbcbff2016-03-22 13:23:47 -0400241 grpc_unlink_if_unix_domain_socket(&sp->addr.sockaddr);
Craig Tillera82950e2015-09-22 12:33:20 -0700242 sp->destroyed_closure.cb = destroyed_port;
243 sp->destroyed_closure.cb_arg = s;
yang-g5d850372015-12-01 10:32:28 -0800244 grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
Craig Tillera82950e2015-09-22 12:33:20 -0700245 "tcp_listener_shutdown");
Craig Tiller45724b32015-09-22 10:42:19 -0700246 }
Craig Tillera82950e2015-09-22 12:33:20 -0700247 gpr_mu_unlock(&s->mu);
248 } else {
249 gpr_mu_unlock(&s->mu);
250 finish_shutdown(exec_ctx, s);
251 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800252}
253
Dan Born5d81d152016-01-12 20:29:29 -0800254static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Craig Tillera82950e2015-09-22 12:33:20 -0700255 gpr_mu_lock(&s->mu);
Craig Tiller6f051402015-05-13 11:42:42 -0700256
Craig Tillera82950e2015-09-22 12:33:20 -0700257 GPR_ASSERT(!s->shutdown);
Craig Tilleref962642016-05-18 22:57:17 -0700258 s->shutdown = true;
Craig Tiller6f051402015-05-13 11:42:42 -0700259
Craig Tiller6f051402015-05-13 11:42:42 -0700260 /* shutdown all fd's */
Craig Tillera82950e2015-09-22 12:33:20 -0700261 if (s->active_ports) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800262 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800263 for (sp = s->head; sp; sp = sp->next) {
264 grpc_fd_shutdown(exec_ctx, sp->emfd);
Craig Tiller6f051402015-05-13 11:42:42 -0700265 }
Craig Tillera82950e2015-09-22 12:33:20 -0700266 gpr_mu_unlock(&s->mu);
267 } else {
268 gpr_mu_unlock(&s->mu);
269 deactivated_all_ports(exec_ctx, s);
270 }
Craig Tiller6f051402015-05-13 11:42:42 -0700271}
272
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800273/* get max listen queue size on linux */
Craig Tillera82950e2015-09-22 12:33:20 -0700274static void init_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800275 int n = SOMAXCONN;
276 char buf[64];
Craig Tillera82950e2015-09-22 12:33:20 -0700277 FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
278 if (fp == NULL) {
279 /* 2.4 kernel. */
280 s_max_accept_queue_size = SOMAXCONN;
281 return;
282 }
283 if (fgets(buf, sizeof buf, fp)) {
284 char *end;
285 long i = strtol(buf, &end, 10);
286 if (i > 0 && i <= INT_MAX && end && *end == 0) {
287 n = (int)i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800288 }
Craig Tillera82950e2015-09-22 12:33:20 -0700289 }
290 fclose(fp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800291 s_max_accept_queue_size = n;
292
Craig Tillera82950e2015-09-22 12:33:20 -0700293 if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
294 gpr_log(GPR_INFO,
295 "Suspiciously small accept queue (%d) will probably lead to "
296 "connection drops",
297 s_max_accept_queue_size);
298 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800299}
300
Craig Tillera82950e2015-09-22 12:33:20 -0700301static int get_max_accept_queue_size(void) {
302 gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800303 return s_max_accept_queue_size;
304}
305
nnoble0c475f02014-12-05 15:37:39 -0800306/* Prepare a recently-created socket for listening. */
Craig Tiller80384bd2016-05-06 16:12:31 -0700307static grpc_error *prepare_socket(int fd, const struct sockaddr *addr,
Craig Tilleref962642016-05-18 22:57:17 -0700308 size_t addr_len, bool so_reuseport,
309 int *port) {
ctiller570d1f42015-01-12 16:29:52 -0800310 struct sockaddr_storage sockname_temp;
311 socklen_t sockname_len;
Craig Tiller80384bd2016-05-06 16:12:31 -0700312 grpc_error *err = GRPC_ERROR_NONE;
ctiller570d1f42015-01-12 16:29:52 -0800313
Craig Tiller80384bd2016-05-06 16:12:31 -0700314 GPR_ASSERT(fd >= 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800315
Yuchen Zeng2414bbb2016-08-08 21:22:54 -0700316 if (so_reuseport && !grpc_is_unix_socket(addr)) {
Craig Tilleref962642016-05-18 22:57:17 -0700317 err = grpc_set_socket_reuse_port(fd, 1);
318 if (err != GRPC_ERROR_NONE) goto error;
319 }
320
Craig Tiller80384bd2016-05-06 16:12:31 -0700321 err = grpc_set_socket_nonblocking(fd, 1);
322 if (err != GRPC_ERROR_NONE) goto error;
323 err = grpc_set_socket_cloexec(fd, 1);
324 if (err != GRPC_ERROR_NONE) goto error;
325 if (!grpc_is_unix_socket(addr)) {
326 err = grpc_set_socket_low_latency(fd, 1);
327 if (err != GRPC_ERROR_NONE) goto error;
328 err = grpc_set_socket_reuse_addr(fd, 1);
329 if (err != GRPC_ERROR_NONE) goto error;
Craig Tillera82950e2015-09-22 12:33:20 -0700330 }
Craig Tiller80384bd2016-05-06 16:12:31 -0700331 err = grpc_set_socket_no_sigpipe_if_possible(fd);
332 if (err != GRPC_ERROR_NONE) goto error;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800333
Craig Tillera82950e2015-09-22 12:33:20 -0700334 GPR_ASSERT(addr_len < ~(socklen_t)0);
335 if (bind(fd, addr, (socklen_t)addr_len) < 0) {
David Garcia Quintas03291c42016-05-10 18:28:56 -0700336 err = GRPC_OS_ERROR(errno, "bind");
Craig Tillera82950e2015-09-22 12:33:20 -0700337 goto error;
338 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800339
Craig Tillera82950e2015-09-22 12:33:20 -0700340 if (listen(fd, get_max_accept_queue_size()) < 0) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700341 err = GRPC_OS_ERROR(errno, "listen");
Craig Tillera82950e2015-09-22 12:33:20 -0700342 goto error;
343 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800344
Craig Tillera82950e2015-09-22 12:33:20 -0700345 sockname_len = sizeof(sockname_temp);
346 if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700347 err = GRPC_OS_ERROR(errno, "getsockname");
Craig Tillera82950e2015-09-22 12:33:20 -0700348 goto error;
349 }
ctiller570d1f42015-01-12 16:29:52 -0800350
Craig Tiller80384bd2016-05-06 16:12:31 -0700351 *port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
352 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800353
354error:
Craig Tiller94f84532016-05-06 21:03:29 -0700355 GPR_ASSERT(err != GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700356 if (fd >= 0) {
357 close(fd);
358 }
David Garcia Quintas32ec1332016-05-11 12:22:53 -0700359 grpc_error *ret = grpc_error_set_int(
Craig Tiller80384bd2016-05-06 16:12:31 -0700360 GRPC_ERROR_CREATE_REFERENCING("Unable to configure socket", &err, 1),
361 GRPC_ERROR_INT_FD, fd);
David Garcia Quintas32ec1332016-05-11 12:22:53 -0700362 GRPC_ERROR_UNREF(err);
363 return ret;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800364}
365
366/* event manager callback when reads are ready */
Craig Tillerc027e772016-05-03 16:27:00 -0700367static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800368 grpc_tcp_listener *sp = arg;
Dan Born5d81d152016-01-12 20:29:29 -0800369 grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index,
370 sp->fd_index};
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700371 grpc_pollset *read_notifier_pollset = NULL;
Craig Tiller0189ac02015-05-11 14:59:19 -0700372 grpc_fd *fdobj;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800373
Craig Tillerc027e772016-05-03 16:27:00 -0700374 if (err != GRPC_ERROR_NONE) {
Craig Tillera82950e2015-09-22 12:33:20 -0700375 goto error;
376 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800377
Craig Tiller53dd6b92016-05-24 13:49:50 -0700378 read_notifier_pollset =
Craig Tillerb76471d2016-07-01 10:24:56 -0700379 sp->server->pollsets[(size_t)gpr_atm_no_barrier_fetch_add(
380 &sp->server->next_pollset_to_assign, 1) %
Craig Tiller53dd6b92016-05-24 13:49:50 -0700381 sp->server->pollset_count];
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700382
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800383 /* loop until accept4 returns EAGAIN, and then re-arm notification */
Craig Tillera82950e2015-09-22 12:33:20 -0700384 for (;;) {
385 struct sockaddr_storage addr;
386 socklen_t addrlen = sizeof(addr);
387 char *addr_str;
388 char *name;
389 /* Note: If we ever decide to return this address to the user, remember to
390 strip off the ::ffff:0.0.0.0/96 prefix first. */
391 int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
392 if (fd < 0) {
393 switch (errno) {
394 case EINTR:
395 continue;
396 case EAGAIN:
397 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
398 return;
399 default:
400 gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
401 goto error;
402 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800403 }
404
Craig Tillera82950e2015-09-22 12:33:20 -0700405 grpc_set_socket_no_sigpipe_if_possible(fd);
406
407 addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr);
408 gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
409
410 if (grpc_tcp_trace) {
411 gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str);
412 }
413
414 fdobj = grpc_fd_create(fd, name);
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700415
416 if (read_notifier_pollset == NULL) {
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700417 gpr_log(GPR_ERROR, "Read notifier pollset is not set on the fd");
418 goto error;
Craig Tillera82950e2015-09-22 12:33:20 -0700419 }
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700420
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700421 grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj);
422
Craig Tillera82950e2015-09-22 12:33:20 -0700423 sp->server->on_accept_cb(
424 exec_ctx, sp->server->on_accept_cb_arg,
Dan Bornfa6b6062016-01-08 21:01:59 -0800425 grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str),
Craig Tiller418a8212016-05-16 16:27:51 -0700426 read_notifier_pollset, &acceptor);
Craig Tillera82950e2015-09-22 12:33:20 -0700427
428 gpr_free(name);
429 gpr_free(addr_str);
430 }
431
yang-gb063c872015-10-07 11:40:13 -0700432 GPR_UNREACHABLE_CODE(return );
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800433
434error:
Craig Tillera82950e2015-09-22 12:33:20 -0700435 gpr_mu_lock(&sp->server->mu);
436 if (0 == --sp->server->active_ports) {
437 gpr_mu_unlock(&sp->server->mu);
438 deactivated_all_ports(exec_ctx, sp->server);
439 } else {
440 gpr_mu_unlock(&sp->server->mu);
441 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800442}
443
Craig Tiller80384bd2016-05-06 16:12:31 -0700444static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
445 const struct sockaddr *addr,
446 size_t addr_len, unsigned port_index,
447 unsigned fd_index,
448 grpc_tcp_listener **listener) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800449 grpc_tcp_listener *sp = NULL;
Craig Tiller91472962016-05-09 11:01:15 -0700450 int port = -1;
Craig Tillerfa275a92015-06-01 13:55:54 -0700451 char *addr_str;
452 char *name;
nnoble0c475f02014-12-05 15:37:39 -0800453
Craig Tilleref962642016-05-18 22:57:17 -0700454 grpc_error *err = prepare_socket(fd, addr, addr_len, s->so_reuseport, &port);
Craig Tiller80384bd2016-05-06 16:12:31 -0700455 if (err == GRPC_ERROR_NONE) {
Craig Tiller91472962016-05-09 11:01:15 -0700456 GPR_ASSERT(port > 0);
Craig Tillera82950e2015-09-22 12:33:20 -0700457 grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
458 gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
459 gpr_mu_lock(&s->mu);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800460 s->nports++;
Craig Tillera82950e2015-09-22 12:33:20 -0700461 GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
Nicolas Noble8f714622015-11-19 11:16:54 -0800462 sp = gpr_malloc(sizeof(grpc_tcp_listener));
Dan Bornfa6b6062016-01-08 21:01:59 -0800463 sp->next = NULL;
464 if (s->head == NULL) {
465 s->head = sp;
466 } else {
467 s->tail->next = sp;
468 }
469 s->tail = sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700470 sp->server = s;
471 sp->fd = fd;
472 sp->emfd = grpc_fd_create(fd, name);
473 memcpy(sp->addr.untyped, addr, addr_len);
474 sp->addr_len = addr_len;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800475 sp->port = port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800476 sp->port_index = port_index;
477 sp->fd_index = fd_index;
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +0100478 sp->is_sibling = 0;
479 sp->sibling = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700480 GPR_ASSERT(sp->emfd);
481 gpr_mu_unlock(&s->mu);
482 gpr_free(addr_str);
483 gpr_free(name);
484 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800485
Craig Tiller80384bd2016-05-06 16:12:31 -0700486 *listener = sp;
487 return err;
nnoble0c475f02014-12-05 15:37:39 -0800488}
489
Dan Bornad1f31f2016-07-08 13:24:49 -0700490/* Insert count new listeners after listener. Every new listener will have the
491 same listen address as listener (SO_REUSEPORT must be enabled). Every new
492 listener is a sibling of listener. */
Craig Tilleref962642016-05-18 22:57:17 -0700493static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
494 grpc_tcp_listener *sp = NULL;
495 char *addr_str;
496 char *name;
497 grpc_error *err;
498
499 for (grpc_tcp_listener *l = listener->next; l && l->is_sibling; l = l->next) {
500 l->fd_index += count;
501 }
502
503 for (unsigned i = 0; i < count; i++) {
Craig Tiller136698c2016-05-19 11:49:44 -0700504 int fd = -1;
505 int port = -1;
Craig Tilleref962642016-05-18 22:57:17 -0700506 grpc_dualstack_mode dsmode;
507 err = grpc_create_dualstack_socket(&listener->addr.sockaddr, SOCK_STREAM, 0,
508 &dsmode, &fd);
509 if (err != GRPC_ERROR_NONE) return err;
510 err = prepare_socket(fd, &listener->addr.sockaddr, listener->addr_len, true,
511 &port);
512 if (err != GRPC_ERROR_NONE) return err;
Craig Tiller644da982016-05-19 09:19:28 -0700513 listener->server->nports++;
Craig Tilleref962642016-05-18 22:57:17 -0700514 grpc_sockaddr_to_string(&addr_str, &listener->addr.sockaddr, 1);
515 gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str, i);
516 sp = gpr_malloc(sizeof(grpc_tcp_listener));
517 sp->next = listener->next;
518 listener->next = sp;
Dan Bornad1f31f2016-07-08 13:24:49 -0700519 /* sp (the new listener) is a sibling of 'listener' (the original
520 listener). */
521 sp->is_sibling = 1;
522 sp->sibling = listener->sibling;
523 listener->sibling = sp;
Craig Tilleref962642016-05-18 22:57:17 -0700524 sp->server = listener->server;
525 sp->fd = fd;
526 sp->emfd = grpc_fd_create(fd, name);
527 memcpy(sp->addr.untyped, listener->addr.untyped, listener->addr_len);
528 sp->addr_len = listener->addr_len;
529 sp->port = port;
530 sp->port_index = listener->port_index;
531 sp->fd_index = listener->fd_index + count - i;
Craig Tilleref962642016-05-18 22:57:17 -0700532 GPR_ASSERT(sp->emfd);
533 while (listener->server->tail->next != NULL) {
534 listener->server->tail = listener->server->tail->next;
535 }
536 gpr_free(addr_str);
537 gpr_free(name);
538 }
539
540 return GRPC_ERROR_NONE;
541}
542
Craig Tillerc027e772016-05-03 16:27:00 -0700543grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
544 size_t addr_len, int *out_port) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800545 grpc_tcp_listener *sp;
546 grpc_tcp_listener *sp2 = NULL;
nnoble0c475f02014-12-05 15:37:39 -0800547 int fd;
548 grpc_dualstack_mode dsmode;
549 struct sockaddr_in6 addr6_v4mapped;
550 struct sockaddr_in wild4;
551 struct sockaddr_in6 wild6;
552 struct sockaddr_in addr4_copy;
ctiller570d1f42015-01-12 16:29:52 -0800553 struct sockaddr *allocated_addr = NULL;
554 struct sockaddr_storage sockname_temp;
555 socklen_t sockname_len;
nnoble0c475f02014-12-05 15:37:39 -0800556 int port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800557 unsigned port_index = 0;
558 unsigned fd_index = 0;
Craig Tillerc027e772016-05-03 16:27:00 -0700559 grpc_error *errs[2] = {GRPC_ERROR_NONE, GRPC_ERROR_NONE};
Dan Bornfa6b6062016-01-08 21:01:59 -0800560 if (s->tail != NULL) {
561 port_index = s->tail->port_index + 1;
562 }
ahedbergfcbcbff2016-03-22 13:23:47 -0400563 grpc_unlink_if_unix_domain_socket((struct sockaddr *)addr);
Craig Tilleraa31da42015-02-17 16:33:35 -0800564
ctiller570d1f42015-01-12 16:29:52 -0800565 /* Check if this is a wildcard port, and if so, try to keep the port the same
566 as some previously created listener. */
Craig Tillera82950e2015-09-22 12:33:20 -0700567 if (grpc_sockaddr_get_port(addr) == 0) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800568 for (sp = s->head; sp; sp = sp->next) {
Craig Tillera82950e2015-09-22 12:33:20 -0700569 sockname_len = sizeof(sockname_temp);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800570 if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
Craig Tillera82950e2015-09-22 12:33:20 -0700571 &sockname_len)) {
572 port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
573 if (port > 0) {
Nicolas "Pixel" Noble7c9a1542016-03-26 01:33:34 +0100574 allocated_addr = gpr_malloc(addr_len);
Craig Tillera82950e2015-09-22 12:33:20 -0700575 memcpy(allocated_addr, addr, addr_len);
576 grpc_sockaddr_set_port(allocated_addr, port);
577 addr = allocated_addr;
578 break;
579 }
580 }
ctiller570d1f42015-01-12 16:29:52 -0800581 }
Craig Tillera82950e2015-09-22 12:33:20 -0700582 }
ctiller570d1f42015-01-12 16:29:52 -0800583
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800584 sp = NULL;
585
Craig Tillera82950e2015-09-22 12:33:20 -0700586 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
587 addr = (const struct sockaddr *)&addr6_v4mapped;
588 addr_len = sizeof(addr6_v4mapped);
589 }
nnoble0c475f02014-12-05 15:37:39 -0800590
591 /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
Craig Tillera82950e2015-09-22 12:33:20 -0700592 if (grpc_sockaddr_is_wildcard(addr, &port)) {
593 grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
nnoble0c475f02014-12-05 15:37:39 -0800594
Craig Tillera82950e2015-09-22 12:33:20 -0700595 /* Try listening on IPv6 first. */
596 addr = (struct sockaddr *)&wild6;
597 addr_len = sizeof(wild6);
Craig Tillerc027e772016-05-03 16:27:00 -0700598 errs[0] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
599 if (errs[0] == GRPC_ERROR_NONE) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700600 errs[0] = add_socket_to_server(s, fd, addr, addr_len, port_index,
601 fd_index, &sp);
Craig Tillerc027e772016-05-03 16:27:00 -0700602 if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
603 goto done;
604 }
605 if (sp != NULL) {
606 ++fd_index;
607 }
608 /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
609 if (port == 0 && sp != NULL) {
610 grpc_sockaddr_set_port((struct sockaddr *)&wild4, sp->port);
611 }
nnoble0c475f02014-12-05 15:37:39 -0800612 }
Craig Tiller161f7632016-06-09 15:46:53 -0700613 addr = (struct sockaddr *)&wild4;
614 addr_len = sizeof(wild4);
Craig Tillera82950e2015-09-22 12:33:20 -0700615 }
616
Craig Tillerc027e772016-05-03 16:27:00 -0700617 errs[1] = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode, &fd);
618 if (errs[1] == GRPC_ERROR_NONE) {
yang-g63460412016-03-22 14:58:15 -0700619 if (dsmode == GRPC_DSMODE_IPV4 &&
620 grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
621 addr = (struct sockaddr *)&addr4_copy;
622 addr_len = sizeof(addr4_copy);
623 }
yang-gb7921c72016-03-23 10:16:45 -0700624 sp2 = sp;
Craig Tiller80384bd2016-05-06 16:12:31 -0700625 errs[1] =
626 add_socket_to_server(s, fd, addr, addr_len, port_index, fd_index, &sp);
yang-g63460412016-03-22 14:58:15 -0700627 if (sp2 != NULL && sp != NULL) {
628 sp2->sibling = sp;
629 sp->is_sibling = 1;
630 }
Dan Bornfa6b6062016-01-08 21:01:59 -0800631 }
ctiller570d1f42015-01-12 16:29:52 -0800632
633done:
Craig Tillera82950e2015-09-22 12:33:20 -0700634 gpr_free(allocated_addr);
Dan Bornfa6b6062016-01-08 21:01:59 -0800635 if (sp != NULL) {
Craig Tillerc027e772016-05-03 16:27:00 -0700636 *out_port = sp->port;
Craig Tillerf707d622016-05-06 14:26:12 -0700637 GRPC_ERROR_UNREF(errs[0]);
638 GRPC_ERROR_UNREF(errs[1]);
Craig Tillerc027e772016-05-03 16:27:00 -0700639 return GRPC_ERROR_NONE;
Dan Bornfa6b6062016-01-08 21:01:59 -0800640 } else {
Craig Tillerc027e772016-05-03 16:27:00 -0700641 *out_port = -1;
642 char *addr_str = grpc_sockaddr_to_uri(addr);
643 grpc_error *err = grpc_error_set_str(
644 GRPC_ERROR_CREATE_REFERENCING("Failed to add port to server", errs,
645 GPR_ARRAY_SIZE(errs)),
646 GRPC_ERROR_STR_TARGET_ADDRESS, addr_str);
David Garcia Quintas32ec1332016-05-11 12:22:53 -0700647 GRPC_ERROR_UNREF(errs[0]);
648 GRPC_ERROR_UNREF(errs[1]);
Craig Tillerc027e772016-05-03 16:27:00 -0700649 gpr_free(addr_str);
650 return err;
Dan Bornfa6b6062016-01-08 21:01:59 -0800651 }
nnoble0c475f02014-12-05 15:37:39 -0800652}
653
Dan Born5d81d152016-01-12 20:29:29 -0800654unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
655 unsigned port_index) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800656 unsigned num_fds = 0;
Nicolas Noble8f714622015-11-19 11:16:54 -0800657 grpc_tcp_listener *sp;
Dan Born930c2982016-09-08 19:12:18 -0700658 gpr_mu_lock(&s->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800659 for (sp = s->head; sp && port_index != 0; sp = sp->next) {
660 if (!sp->is_sibling) {
661 --port_index;
662 }
663 }
664 for (; sp; sp = sp->sibling, ++num_fds)
yang-g3ff97272015-11-20 17:01:57 -0800665 ;
Dan Born930c2982016-09-08 19:12:18 -0700666 gpr_mu_unlock(&s->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800667 return num_fds;
668}
669
Dan Born5d81d152016-01-12 20:29:29 -0800670int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
671 unsigned fd_index) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800672 grpc_tcp_listener *sp;
Dan Born930c2982016-09-08 19:12:18 -0700673 int fd;
674 gpr_mu_lock(&s->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800675 for (sp = s->head; sp && port_index != 0; sp = sp->next) {
676 if (!sp->is_sibling) {
677 --port_index;
678 }
679 }
680 for (; sp && fd_index != 0; sp = sp->sibling, --fd_index)
681 ;
682 if (sp) {
Dan Born930c2982016-09-08 19:12:18 -0700683 fd = sp->fd;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800684 } else {
Dan Born930c2982016-09-08 19:12:18 -0700685 fd = -1;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800686 }
Dan Born930c2982016-09-08 19:12:18 -0700687 gpr_mu_unlock(&s->mu);
688 return fd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800689}
690
Craig Tillera82950e2015-09-22 12:33:20 -0700691void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
692 grpc_pollset **pollsets, size_t pollset_count,
693 grpc_tcp_server_cb on_accept_cb,
694 void *on_accept_cb_arg) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800695 size_t i;
Nicolas Noble8f714622015-11-19 11:16:54 -0800696 grpc_tcp_listener *sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700697 GPR_ASSERT(on_accept_cb);
698 gpr_mu_lock(&s->mu);
699 GPR_ASSERT(!s->on_accept_cb);
700 GPR_ASSERT(s->active_ports == 0);
Robbie Shade3cd2d182015-08-28 14:30:35 -0400701 s->on_accept_cb = on_accept_cb;
702 s->on_accept_cb_arg = on_accept_cb_arg;
Craig Tiller0189ac02015-05-11 14:59:19 -0700703 s->pollsets = pollsets;
704 s->pollset_count = pollset_count;
Craig Tilleref962642016-05-18 22:57:17 -0700705 sp = s->head;
706 while (sp != NULL) {
Yuchen Zengd745a6f2016-08-08 20:44:36 -0700707 if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr.sockaddr) &&
708 pollset_count > 1) {
Craig Tilleref962642016-05-18 22:57:17 -0700709 GPR_ASSERT(GRPC_LOG_IF_ERROR(
710 "clone_port", clone_port(sp, (unsigned)(pollset_count - 1))));
711 for (i = 0; i < pollset_count; i++) {
712 grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
713 sp->read_closure.cb = on_read;
714 sp->read_closure.cb_arg = sp;
715 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
716 s->active_ports++;
717 sp = sp->next;
718 }
719 } else {
720 for (i = 0; i < pollset_count; i++) {
721 grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
722 }
723 sp->read_closure.cb = on_read;
724 sp->read_closure.cb_arg = sp;
725 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
726 s->active_ports++;
727 sp = sp->next;
ctiller58393c22015-01-07 14:03:30 -0800728 }
Craig Tillera82950e2015-09-22 12:33:20 -0700729 }
730 gpr_mu_unlock(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800731}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800732
Dan Bornfa6b6062016-01-08 21:01:59 -0800733grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
Dan Born930c2982016-09-08 19:12:18 -0700734 gpr_ref_non_zero(&s->refs);
Dan Bornfa6b6062016-01-08 21:01:59 -0800735 return s;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800736}
737
Dan Born9c12bc22016-01-13 16:52:20 -0800738void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
739 grpc_closure *shutdown_starting) {
740 gpr_mu_lock(&s->mu);
Craig Tillerc027e772016-05-03 16:27:00 -0700741 grpc_closure_list_append(&s->shutdown_starting, shutdown_starting,
742 GRPC_ERROR_NONE);
Dan Born9c12bc22016-01-13 16:52:20 -0800743 gpr_mu_unlock(&s->mu);
744}
745
Dan Bornfa6b6062016-01-08 21:01:59 -0800746void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
747 if (gpr_unref(&s->refs)) {
Dan Born930c2982016-09-08 19:12:18 -0700748 grpc_tcp_server_shutdown_listeners(exec_ctx, s);
749 gpr_mu_lock(&s->mu);
750 grpc_exec_ctx_enqueue_list(exec_ctx, &s->shutdown_starting, NULL);
751 gpr_mu_unlock(&s->mu);
752 tcp_server_destroy(exec_ctx, s);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800753 }
754}
755
yang-g9275d402016-07-11 16:51:39 -0700756void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
757 grpc_tcp_server *s) {
758 gpr_mu_lock(&s->mu);
759 /* shutdown all fd's */
760 if (s->active_ports) {
761 grpc_tcp_listener *sp;
762 for (sp = s->head; sp; sp = sp->next) {
763 grpc_fd_shutdown(exec_ctx, sp->emfd);
764 }
765 }
766 gpr_mu_unlock(&s->mu);
767}
768
Craig Tiller190d3602015-02-18 09:23:38 -0800769#endif