blob: 5f286a6723ccf780f8f4e229f0d196f7a9d4e84a [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
murgatroid9954070892016-08-08 17:01:18 -070039#include "src/core/lib/iomgr/port.h"
Craig Tiller0c0b60c2015-01-21 15:49:28 -080040
murgatroid99623dd4f2016-08-08 17:31:27 -070041#ifdef GRPC_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>
Dan Born8886a812016-07-08 16:06:07 -070047#include <ifaddrs.h>
Craig Tilleraa31da42015-02-17 16:33:35 -080048#include <limits.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080049#include <netinet/in.h>
50#include <netinet/tcp.h>
51#include <stdio.h>
Craig Tilleraa31da42015-02-17 16:33:35 -080052#include <string.h>
53#include <sys/socket.h>
54#include <sys/stat.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080055#include <sys/types.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056#include <unistd.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080057
Craig Tillerf40df232016-03-25 13:38:14 -070058#include <grpc/support/alloc.h>
59#include <grpc/support/log.h>
60#include <grpc/support/string_util.h>
61#include <grpc/support/sync.h>
62#include <grpc/support/time.h>
Craig Tillerc027e772016-05-03 16:27:00 -070063#include <grpc/support/useful.h>
64
Craig Tiller9533d042016-03-25 17:11:06 -070065#include "src/core/lib/iomgr/resolve_address.h"
murgatroid997871f732016-09-23 13:49:05 -070066#include "src/core/lib/iomgr/sockaddr.h"
Craig Tiller9533d042016-03-25 17:11:06 -070067#include "src/core/lib/iomgr/sockaddr_utils.h"
68#include "src/core/lib/iomgr/socket_utils_posix.h"
69#include "src/core/lib/iomgr/tcp_posix.h"
70#include "src/core/lib/iomgr/unix_sockets_posix.h"
71#include "src/core/lib/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080072
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080073#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
74
75static gpr_once s_init_max_accept_queue_size;
76static int s_max_accept_queue_size;
77
78/* one listening port */
Dan Bornfa6b6062016-01-08 21:01:59 -080079typedef struct grpc_tcp_listener grpc_tcp_listener;
Nicolas Noble8f714622015-11-19 11:16:54 -080080struct grpc_tcp_listener {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080081 int fd;
ctiller18b49ab2014-12-09 14:39:16 -080082 grpc_fd *emfd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080083 grpc_tcp_server *server;
murgatroid997871f732016-09-23 13:49:05 -070084 grpc_resolved_address addr;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080085 int port;
Dan Bornfa6b6062016-01-08 21:01:59 -080086 unsigned port_index;
87 unsigned fd_index;
Craig Tiller33825112015-09-18 07:44:19 -070088 grpc_closure read_closure;
89 grpc_closure destroyed_closure;
Nicolas Noble8f714622015-11-19 11:16:54 -080090 struct grpc_tcp_listener *next;
Dan Bornad1f31f2016-07-08 13:24:49 -070091 /* sibling is a linked list of all listeners for a given port. add_port and
92 clone_port place all new listeners in the same sibling list. A member of
93 the 'sibling' list is also a member of the 'next' list. The head of each
94 sibling list has is_sibling==0, and subsequent members of sibling lists
95 have is_sibling==1. is_sibling allows separate sibling lists to be
96 identified while iterating through 'next'. */
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +010097 struct grpc_tcp_listener *sibling;
98 int is_sibling;
Nicolas Noble8f714622015-11-19 11:16:54 -080099};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800100
101/* the overall server */
Craig Tillera82950e2015-09-22 12:33:20 -0700102struct grpc_tcp_server {
Dan Bornfa6b6062016-01-08 21:01:59 -0800103 gpr_refcount refs;
Robbie Shade3cd2d182015-08-28 14:30:35 -0400104 /* Called whenever accept() succeeds on a server port. */
105 grpc_tcp_server_cb on_accept_cb;
106 void *on_accept_cb_arg;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800107
108 gpr_mu mu;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800109
110 /* active port count: how many ports are actually still listening */
Craig Tilleraec96aa2015-04-07 14:32:15 -0700111 size_t active_ports;
112 /* destroyed port count: how many ports are completely destroyed */
113 size_t destroyed_ports;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800114
Craig Tilleref962642016-05-18 22:57:17 -0700115 /* is this server shutting down? */
116 bool shutdown;
Craig Tillerf26236a2017-03-07 09:43:51 -0800117 /* have listeners been shutdown? */
118 bool shutdown_listeners;
Craig Tilleref962642016-05-18 22:57:17 -0700119 /* use SO_REUSEPORT */
120 bool so_reuseport;
Dan Born8886a812016-07-08 16:06:07 -0700121 /* expand wildcard addresses to a list of all local addresses */
122 bool expand_wildcard_addrs;
Craig Tiller6f051402015-05-13 11:42:42 -0700123
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800124 /* linked list of server ports */
Nicolas Noble8f714622015-11-19 11:16:54 -0800125 grpc_tcp_listener *head;
Dan Bornfa6b6062016-01-08 21:01:59 -0800126 grpc_tcp_listener *tail;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800127 unsigned nports;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700128
Dan Born9c12bc22016-01-13 16:52:20 -0800129 /* List of closures passed to shutdown_starting_add(). */
130 grpc_closure_list shutdown_starting;
131
Craig Tilleraec96aa2015-04-07 14:32:15 -0700132 /* shutdown callback */
Craig Tillerd1bec032015-09-18 17:29:00 -0700133 grpc_closure *shutdown_complete;
Craig Tiller0189ac02015-05-11 14:59:19 -0700134
Craig Tiller6174b9a2015-06-18 08:13:05 -0700135 /* all pollsets interested in new connections */
Craig Tiller0189ac02015-05-11 14:59:19 -0700136 grpc_pollset **pollsets;
Craig Tiller6174b9a2015-06-18 08:13:05 -0700137 /* number of pollsets in the pollsets array */
Craig Tiller0189ac02015-05-11 14:59:19 -0700138 size_t pollset_count;
Craig Tiller53dd6b92016-05-24 13:49:50 -0700139
140 /* next pollset to assign a channel to */
Craig Tillerb76471d2016-07-01 10:24:56 -0700141 gpr_atm next_pollset_to_assign;
Craig Tillere34c2852016-09-23 09:43:32 -0700142
Craig Tiller20afa3d2016-10-17 14:52:14 -0700143 grpc_resource_quota *resource_quota;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800144};
145
Craig Tilleref962642016-05-18 22:57:17 -0700146static gpr_once check_init = GPR_ONCE_INIT;
Nicolas "Pixel" Noblebaa35fc2016-08-19 02:20:11 +0200147static bool has_so_reuseport = false;
Craig Tilleref962642016-05-18 22:57:17 -0700148
149static void init(void) {
Nicolas "Pixel" Noblebaa35fc2016-08-19 02:20:11 +0200150#ifndef GPR_MANYLINUX1
Craig Tilleref962642016-05-18 22:57:17 -0700151 int s = socket(AF_INET, SOCK_STREAM, 0);
152 if (s >= 0) {
153 has_so_reuseport = GRPC_LOG_IF_ERROR("check for SO_REUSEPORT",
154 grpc_set_socket_reuse_port(s, 1));
155 close(s);
156 }
Nicolas "Pixel" Noblebaa35fc2016-08-19 02:20:11 +0200157#endif
Craig Tilleref962642016-05-18 22:57:17 -0700158}
159
Craig Tillere34c2852016-09-23 09:43:32 -0700160grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
161 grpc_closure *shutdown_complete,
Craig Tilleref962642016-05-18 22:57:17 -0700162 const grpc_channel_args *args,
Craig Tiller0b5857f2016-05-04 10:58:06 -0700163 grpc_tcp_server **server) {
Craig Tilleref962642016-05-18 22:57:17 -0700164 gpr_once_init(&check_init, init);
165
Craig Tiller702a4452017-03-07 09:53:00 -0800166 grpc_tcp_server *s = gpr_zalloc(sizeof(grpc_tcp_server));
Craig Tilleref962642016-05-18 22:57:17 -0700167 s->so_reuseport = has_so_reuseport;
Craig Tiller20afa3d2016-10-17 14:52:14 -0700168 s->resource_quota = grpc_resource_quota_create(NULL);
Dan Born8886a812016-07-08 16:06:07 -0700169 s->expand_wildcard_addrs = false;
Craig Tilleref962642016-05-18 22:57:17 -0700170 for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
171 if (0 == strcmp(GRPC_ARG_ALLOW_REUSEPORT, args->args[i].key)) {
172 if (args->args[i].type == GRPC_ARG_INTEGER) {
173 s->so_reuseport =
174 has_so_reuseport && (args->args[i].value.integer != 0);
175 } else {
Craig Tillera59c16c2016-10-31 07:25:01 -0700176 grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
Craig Tilleref962642016-05-18 22:57:17 -0700177 gpr_free(s);
178 return GRPC_ERROR_CREATE(GRPC_ARG_ALLOW_REUSEPORT
179 " must be an integer");
180 }
Craig Tiller153eaa72016-10-21 13:52:36 -0700181 } else if (0 == strcmp(GRPC_ARG_RESOURCE_QUOTA, args->args[i].key)) {
Craig Tillere34c2852016-09-23 09:43:32 -0700182 if (args->args[i].type == GRPC_ARG_POINTER) {
Craig Tillera59c16c2016-10-31 07:25:01 -0700183 grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
Craig Tiller20afa3d2016-10-17 14:52:14 -0700184 s->resource_quota =
Craig Tillera59c16c2016-10-31 07:25:01 -0700185 grpc_resource_quota_ref_internal(args->args[i].value.pointer.p);
Craig Tillere34c2852016-09-23 09:43:32 -0700186 } else {
Craig Tillera59c16c2016-10-31 07:25:01 -0700187 grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
Craig Tillere34c2852016-09-23 09:43:32 -0700188 gpr_free(s);
Craig Tiller153eaa72016-10-21 13:52:36 -0700189 return GRPC_ERROR_CREATE(GRPC_ARG_RESOURCE_QUOTA
Craig Tillere34c2852016-09-23 09:43:32 -0700190 " must be a pointer to a buffer pool");
191 }
Dan Born8886a812016-07-08 16:06:07 -0700192 } else if (0 == strcmp(GRPC_ARG_EXPAND_WILDCARD_ADDRS, args->args[i].key)) {
193 if (args->args[i].type == GRPC_ARG_INTEGER) {
194 s->expand_wildcard_addrs = (args->args[i].value.integer != 0);
195 } else {
Dan Born3158f7b2017-02-09 20:32:02 -0800196 grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
Dan Born8886a812016-07-08 16:06:07 -0700197 gpr_free(s);
198 return GRPC_ERROR_CREATE(GRPC_ARG_EXPAND_WILDCARD_ADDRS
199 " must be an integer");
200 }
Craig Tilleref962642016-05-18 22:57:17 -0700201 }
202 }
Dan Bornfa6b6062016-01-08 21:01:59 -0800203 gpr_ref_init(&s->refs, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700204 gpr_mu_init(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800205 s->active_ports = 0;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700206 s->destroyed_ports = 0;
Craig Tilleref962642016-05-18 22:57:17 -0700207 s->shutdown = false;
Dan Born9c12bc22016-01-13 16:52:20 -0800208 s->shutdown_starting.head = NULL;
209 s->shutdown_starting.tail = NULL;
Dan Bornfa6b6062016-01-08 21:01:59 -0800210 s->shutdown_complete = shutdown_complete;
Robbie Shade3cd2d182015-08-28 14:30:35 -0400211 s->on_accept_cb = NULL;
212 s->on_accept_cb_arg = NULL;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800213 s->head = NULL;
Dan Bornfa6b6062016-01-08 21:01:59 -0800214 s->tail = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800215 s->nports = 0;
Craig Tillerb76471d2016-07-01 10:24:56 -0700216 gpr_atm_no_barrier_store(&s->next_pollset_to_assign, 0);
Craig Tiller0b5857f2016-05-04 10:58:06 -0700217 *server = s;
218 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800219}
220
Craig Tillera82950e2015-09-22 12:33:20 -0700221static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Dan Born930c2982016-09-08 19:12:18 -0700222 gpr_mu_lock(&s->mu);
223 GPR_ASSERT(s->shutdown);
224 gpr_mu_unlock(&s->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800225 if (s->shutdown_complete != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800226 grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE);
Dan Bornfa6b6062016-01-08 21:01:59 -0800227 }
Craig Tilleraec96aa2015-04-07 14:32:15 -0700228
Craig Tillera82950e2015-09-22 12:33:20 -0700229 gpr_mu_destroy(&s->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700230
Nicolas "Pixel" Noblec6a7c6e2015-11-19 21:55:44 +0100231 while (s->head) {
232 grpc_tcp_listener *sp = s->head;
233 s->head = sp->next;
Dan Bornfa6b6062016-01-08 21:01:59 -0800234 gpr_free(sp);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800235 }
236
Craig Tillera59c16c2016-10-31 07:25:01 -0700237 grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
Craig Tillere34c2852016-09-23 09:43:32 -0700238
Craig Tillera82950e2015-09-22 12:33:20 -0700239 gpr_free(s);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700240}
241
Craig Tiller6c396862016-01-28 13:53:40 -0800242static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server,
Craig Tillerc027e772016-05-03 16:27:00 -0700243 grpc_error *error) {
Craig Tilleraec96aa2015-04-07 14:32:15 -0700244 grpc_tcp_server *s = server;
Craig Tillera82950e2015-09-22 12:33:20 -0700245 gpr_mu_lock(&s->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700246 s->destroyed_ports++;
Craig Tillera82950e2015-09-22 12:33:20 -0700247 if (s->destroyed_ports == s->nports) {
248 gpr_mu_unlock(&s->mu);
249 finish_shutdown(exec_ctx, s);
250 } else {
251 GPR_ASSERT(s->destroyed_ports < s->nports);
252 gpr_mu_unlock(&s->mu);
253 }
Craig Tilleraec96aa2015-04-07 14:32:15 -0700254}
255
Craig Tiller6174b9a2015-06-18 08:13:05 -0700256/* called when all listening endpoints have been shutdown, so no further
257 events will be received on them - at this point it's safe to destroy
258 things */
Craig Tillera82950e2015-09-22 12:33:20 -0700259static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800260 /* delete ALL the things */
Craig Tillera82950e2015-09-22 12:33:20 -0700261 gpr_mu_lock(&s->mu);
Craig Tiller6f051402015-05-13 11:42:42 -0700262
Craig Tillera82950e2015-09-22 12:33:20 -0700263 if (!s->shutdown) {
264 gpr_mu_unlock(&s->mu);
265 return;
266 }
Craig Tiller45724b32015-09-22 10:42:19 -0700267
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800268 if (s->head) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800269 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800270 for (sp = s->head; sp; sp = sp->next) {
murgatroid997871f732016-09-23 13:49:05 -0700271 grpc_unlink_if_unix_domain_socket(&sp->addr);
Craig Tiller3cb34472016-12-28 16:11:38 -0800272 grpc_closure_init(&sp->destroyed_closure, destroyed_port, s,
273 grpc_schedule_on_exec_ctx);
yang-g5d850372015-12-01 10:32:28 -0800274 grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure, NULL,
Craig Tillera82950e2015-09-22 12:33:20 -0700275 "tcp_listener_shutdown");
Craig Tiller45724b32015-09-22 10:42:19 -0700276 }
Craig Tillera82950e2015-09-22 12:33:20 -0700277 gpr_mu_unlock(&s->mu);
278 } else {
279 gpr_mu_unlock(&s->mu);
280 finish_shutdown(exec_ctx, s);
281 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800282}
283
Dan Born5d81d152016-01-12 20:29:29 -0800284static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Craig Tillera82950e2015-09-22 12:33:20 -0700285 gpr_mu_lock(&s->mu);
Craig Tiller6f051402015-05-13 11:42:42 -0700286
Craig Tillera82950e2015-09-22 12:33:20 -0700287 GPR_ASSERT(!s->shutdown);
Craig Tilleref962642016-05-18 22:57:17 -0700288 s->shutdown = true;
Craig Tiller6f051402015-05-13 11:42:42 -0700289
Craig Tiller6f051402015-05-13 11:42:42 -0700290 /* shutdown all fd's */
Craig Tillera82950e2015-09-22 12:33:20 -0700291 if (s->active_ports) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800292 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800293 for (sp = s->head; sp; sp = sp->next) {
Craig Tillercda759d2017-01-27 11:37:37 -0800294 grpc_fd_shutdown(exec_ctx, sp->emfd,
295 GRPC_ERROR_CREATE("Server destroyed"));
Craig Tiller6f051402015-05-13 11:42:42 -0700296 }
Craig Tillera82950e2015-09-22 12:33:20 -0700297 gpr_mu_unlock(&s->mu);
298 } else {
299 gpr_mu_unlock(&s->mu);
300 deactivated_all_ports(exec_ctx, s);
301 }
Craig Tiller6f051402015-05-13 11:42:42 -0700302}
303
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800304/* get max listen queue size on linux */
Craig Tillera82950e2015-09-22 12:33:20 -0700305static void init_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800306 int n = SOMAXCONN;
307 char buf[64];
Craig Tillera82950e2015-09-22 12:33:20 -0700308 FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
309 if (fp == NULL) {
310 /* 2.4 kernel. */
311 s_max_accept_queue_size = SOMAXCONN;
312 return;
313 }
314 if (fgets(buf, sizeof buf, fp)) {
315 char *end;
316 long i = strtol(buf, &end, 10);
317 if (i > 0 && i <= INT_MAX && end && *end == 0) {
318 n = (int)i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800319 }
Craig Tillera82950e2015-09-22 12:33:20 -0700320 }
321 fclose(fp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800322 s_max_accept_queue_size = n;
323
Craig Tillera82950e2015-09-22 12:33:20 -0700324 if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
325 gpr_log(GPR_INFO,
326 "Suspiciously small accept queue (%d) will probably lead to "
327 "connection drops",
328 s_max_accept_queue_size);
329 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800330}
331
Craig Tillera82950e2015-09-22 12:33:20 -0700332static int get_max_accept_queue_size(void) {
333 gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800334 return s_max_accept_queue_size;
335}
336
nnoble0c475f02014-12-05 15:37:39 -0800337/* Prepare a recently-created socket for listening. */
murgatroid997871f732016-09-23 13:49:05 -0700338static grpc_error *prepare_socket(int fd, const grpc_resolved_address *addr,
339 bool so_reuseport, int *port) {
340 grpc_resolved_address sockname_temp;
Craig Tiller80384bd2016-05-06 16:12:31 -0700341 grpc_error *err = GRPC_ERROR_NONE;
ctiller570d1f42015-01-12 16:29:52 -0800342
Craig Tiller80384bd2016-05-06 16:12:31 -0700343 GPR_ASSERT(fd >= 0);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800344
Yuchen Zeng2414bbb2016-08-08 21:22:54 -0700345 if (so_reuseport && !grpc_is_unix_socket(addr)) {
Craig Tilleref962642016-05-18 22:57:17 -0700346 err = grpc_set_socket_reuse_port(fd, 1);
347 if (err != GRPC_ERROR_NONE) goto error;
348 }
349
Craig Tiller80384bd2016-05-06 16:12:31 -0700350 err = grpc_set_socket_nonblocking(fd, 1);
351 if (err != GRPC_ERROR_NONE) goto error;
352 err = grpc_set_socket_cloexec(fd, 1);
353 if (err != GRPC_ERROR_NONE) goto error;
354 if (!grpc_is_unix_socket(addr)) {
355 err = grpc_set_socket_low_latency(fd, 1);
356 if (err != GRPC_ERROR_NONE) goto error;
357 err = grpc_set_socket_reuse_addr(fd, 1);
358 if (err != GRPC_ERROR_NONE) goto error;
Craig Tillera82950e2015-09-22 12:33:20 -0700359 }
Craig Tiller80384bd2016-05-06 16:12:31 -0700360 err = grpc_set_socket_no_sigpipe_if_possible(fd);
361 if (err != GRPC_ERROR_NONE) goto error;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800362
murgatroid997871f732016-09-23 13:49:05 -0700363 GPR_ASSERT(addr->len < ~(socklen_t)0);
364 if (bind(fd, (struct sockaddr *)addr->addr, (socklen_t)addr->len) < 0) {
David Garcia Quintas03291c42016-05-10 18:28:56 -0700365 err = GRPC_OS_ERROR(errno, "bind");
Craig Tillera82950e2015-09-22 12:33:20 -0700366 goto error;
367 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800368
Craig Tillera82950e2015-09-22 12:33:20 -0700369 if (listen(fd, get_max_accept_queue_size()) < 0) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700370 err = GRPC_OS_ERROR(errno, "listen");
Craig Tillera82950e2015-09-22 12:33:20 -0700371 goto error;
372 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800373
murgatroid997871f732016-09-23 13:49:05 -0700374 sockname_temp.len = sizeof(struct sockaddr_storage);
375
murgatroid99dedb9232016-09-26 13:54:04 -0700376 if (getsockname(fd, (struct sockaddr *)sockname_temp.addr,
377 (socklen_t *)&sockname_temp.len) < 0) {
Craig Tiller80384bd2016-05-06 16:12:31 -0700378 err = GRPC_OS_ERROR(errno, "getsockname");
Craig Tillera82950e2015-09-22 12:33:20 -0700379 goto error;
380 }
ctiller570d1f42015-01-12 16:29:52 -0800381
murgatroid997871f732016-09-23 13:49:05 -0700382 *port = grpc_sockaddr_get_port(&sockname_temp);
Craig Tiller80384bd2016-05-06 16:12:31 -0700383 return GRPC_ERROR_NONE;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800384
385error:
Craig Tiller94f84532016-05-06 21:03:29 -0700386 GPR_ASSERT(err != GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700387 if (fd >= 0) {
388 close(fd);
389 }
David Garcia Quintas32ec1332016-05-11 12:22:53 -0700390 grpc_error *ret = grpc_error_set_int(
Craig Tiller80384bd2016-05-06 16:12:31 -0700391 GRPC_ERROR_CREATE_REFERENCING("Unable to configure socket", &err, 1),
392 GRPC_ERROR_INT_FD, fd);
David Garcia Quintas32ec1332016-05-11 12:22:53 -0700393 GRPC_ERROR_UNREF(err);
394 return ret;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800395}
396
397/* event manager callback when reads are ready */
Craig Tillerc027e772016-05-03 16:27:00 -0700398static void on_read(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *err) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800399 grpc_tcp_listener *sp = arg;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800400
Craig Tillerc027e772016-05-03 16:27:00 -0700401 if (err != GRPC_ERROR_NONE) {
Craig Tillera82950e2015-09-22 12:33:20 -0700402 goto error;
403 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800404
Mark D. Rotheed38152016-12-08 13:59:13 -0800405 grpc_pollset *read_notifier_pollset =
Craig Tillerb76471d2016-07-01 10:24:56 -0700406 sp->server->pollsets[(size_t)gpr_atm_no_barrier_fetch_add(
407 &sp->server->next_pollset_to_assign, 1) %
Craig Tiller53dd6b92016-05-24 13:49:50 -0700408 sp->server->pollset_count];
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700409
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800410 /* loop until accept4 returns EAGAIN, and then re-arm notification */
Craig Tillera82950e2015-09-22 12:33:20 -0700411 for (;;) {
murgatroid997871f732016-09-23 13:49:05 -0700412 grpc_resolved_address addr;
Craig Tillera82950e2015-09-22 12:33:20 -0700413 char *addr_str;
414 char *name;
murgatroid997871f732016-09-23 13:49:05 -0700415 addr.len = sizeof(struct sockaddr_storage);
Craig Tillera82950e2015-09-22 12:33:20 -0700416 /* Note: If we ever decide to return this address to the user, remember to
417 strip off the ::ffff:0.0.0.0/96 prefix first. */
murgatroid997871f732016-09-23 13:49:05 -0700418 int fd = grpc_accept4(sp->fd, &addr, 1, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700419 if (fd < 0) {
420 switch (errno) {
421 case EINTR:
422 continue;
423 case EAGAIN:
424 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
425 return;
426 default:
Craig Tiller14444642017-03-07 16:21:55 -0800427 gpr_mu_lock(&sp->server->mu);
Craig Tillerf26236a2017-03-07 09:43:51 -0800428 if (!sp->server->shutdown_listeners) {
429 gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
430 } else {
431 /* if we have shutdown listeners, accept4 could fail, and we
432 needn't notify users */
433 }
Craig Tiller14444642017-03-07 16:21:55 -0800434 gpr_mu_unlock(&sp->server->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700435 goto error;
436 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800437 }
438
Craig Tillera82950e2015-09-22 12:33:20 -0700439 grpc_set_socket_no_sigpipe_if_possible(fd);
440
murgatroid997871f732016-09-23 13:49:05 -0700441 addr_str = grpc_sockaddr_to_uri(&addr);
Craig Tillera82950e2015-09-22 12:33:20 -0700442 gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
443
444 if (grpc_tcp_trace) {
445 gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str);
446 }
447
Mark D. Rotheed38152016-12-08 13:59:13 -0800448 grpc_fd *fdobj = grpc_fd_create(fd, name);
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700449
Sree Kuchibhotla42b004a2016-04-08 14:41:49 -0700450 grpc_pollset_add_fd(exec_ctx, read_notifier_pollset, fdobj);
451
Mark D. Roth6c07bf82016-12-09 08:38:38 -0800452 // Create acceptor.
453 grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor));
454 acceptor->from_server = sp->server;
455 acceptor->port_index = sp->port_index;
456 acceptor->fd_index = sp->fd_index;
457
Craig Tillera82950e2015-09-22 12:33:20 -0700458 sp->server->on_accept_cb(
459 exec_ctx, sp->server->on_accept_cb_arg,
Craig Tiller20afa3d2016-10-17 14:52:14 -0700460 grpc_tcp_create(fdobj, sp->server->resource_quota,
Craig Tillere34c2852016-09-23 09:43:32 -0700461 GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str),
Mark D. Rotheed38152016-12-08 13:59:13 -0800462 read_notifier_pollset, acceptor);
Craig Tillera82950e2015-09-22 12:33:20 -0700463
464 gpr_free(name);
465 gpr_free(addr_str);
466 }
467
yang-gb063c872015-10-07 11:40:13 -0700468 GPR_UNREACHABLE_CODE(return );
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800469
470error:
Craig Tillera82950e2015-09-22 12:33:20 -0700471 gpr_mu_lock(&sp->server->mu);
472 if (0 == --sp->server->active_ports) {
473 gpr_mu_unlock(&sp->server->mu);
474 deactivated_all_ports(exec_ctx, sp->server);
475 } else {
476 gpr_mu_unlock(&sp->server->mu);
477 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800478}
479
Craig Tiller80384bd2016-05-06 16:12:31 -0700480static grpc_error *add_socket_to_server(grpc_tcp_server *s, int fd,
murgatroid997871f732016-09-23 13:49:05 -0700481 const grpc_resolved_address *addr,
murgatroid99dedb9232016-09-26 13:54:04 -0700482 unsigned port_index, unsigned fd_index,
Craig Tiller80384bd2016-05-06 16:12:31 -0700483 grpc_tcp_listener **listener) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800484 grpc_tcp_listener *sp = NULL;
Craig Tiller91472962016-05-09 11:01:15 -0700485 int port = -1;
Craig Tillerfa275a92015-06-01 13:55:54 -0700486 char *addr_str;
487 char *name;
nnoble0c475f02014-12-05 15:37:39 -0800488
murgatroid997871f732016-09-23 13:49:05 -0700489 grpc_error *err = prepare_socket(fd, addr, s->so_reuseport, &port);
Craig Tiller80384bd2016-05-06 16:12:31 -0700490 if (err == GRPC_ERROR_NONE) {
Craig Tiller91472962016-05-09 11:01:15 -0700491 GPR_ASSERT(port > 0);
murgatroid997871f732016-09-23 13:49:05 -0700492 grpc_sockaddr_to_string(&addr_str, addr, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700493 gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
494 gpr_mu_lock(&s->mu);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800495 s->nports++;
Craig Tillera82950e2015-09-22 12:33:20 -0700496 GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
Nicolas Noble8f714622015-11-19 11:16:54 -0800497 sp = gpr_malloc(sizeof(grpc_tcp_listener));
Dan Bornfa6b6062016-01-08 21:01:59 -0800498 sp->next = NULL;
499 if (s->head == NULL) {
500 s->head = sp;
501 } else {
502 s->tail->next = sp;
503 }
504 s->tail = sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700505 sp->server = s;
506 sp->fd = fd;
507 sp->emfd = grpc_fd_create(fd, name);
murgatroid997871f732016-09-23 13:49:05 -0700508 memcpy(&sp->addr, addr, sizeof(grpc_resolved_address));
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800509 sp->port = port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800510 sp->port_index = port_index;
511 sp->fd_index = fd_index;
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +0100512 sp->is_sibling = 0;
513 sp->sibling = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700514 GPR_ASSERT(sp->emfd);
515 gpr_mu_unlock(&s->mu);
516 gpr_free(addr_str);
517 gpr_free(name);
518 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800519
Craig Tiller80384bd2016-05-06 16:12:31 -0700520 *listener = sp;
521 return err;
nnoble0c475f02014-12-05 15:37:39 -0800522}
523
Dan Born8886a812016-07-08 16:06:07 -0700524/* If successful, add a listener to s for addr, set *dsmode for the socket, and
525 return the *listener. */
526static grpc_error *add_addr_to_server(grpc_tcp_server *s,
527 const grpc_resolved_address *addr,
528 unsigned port_index, unsigned fd_index,
529 grpc_dualstack_mode *dsmode,
530 grpc_tcp_listener **listener) {
531 grpc_resolved_address addr4_copy;
532 int fd;
533 grpc_error *err =
534 grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, dsmode, &fd);
535 if (err != GRPC_ERROR_NONE) {
536 return err;
537 }
538 if (*dsmode == GRPC_DSMODE_IPV4 &&
539 grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
540 addr = &addr4_copy;
541 }
542 return add_socket_to_server(s, fd, addr, port_index, fd_index, listener);
543}
544
545/* Bind to "::" to get a port number not used by any address. */
546static grpc_error *get_unused_port(int *port) {
547 grpc_resolved_address wild;
548 grpc_sockaddr_make_wildcard6(0, &wild);
549 grpc_dualstack_mode dsmode;
550 int fd;
551 grpc_error *err =
552 grpc_create_dualstack_socket(&wild, SOCK_STREAM, 0, &dsmode, &fd);
553 if (err != GRPC_ERROR_NONE) {
554 return err;
555 }
556 if (dsmode == GRPC_DSMODE_IPV4) {
557 grpc_sockaddr_make_wildcard4(0, &wild);
558 }
559 if (bind(fd, (const struct sockaddr *)wild.addr, (socklen_t)wild.len) != 0) {
560 err = GRPC_OS_ERROR(errno, "bind");
561 close(fd);
562 return err;
563 }
564 if (getsockname(fd, (struct sockaddr *)wild.addr, (socklen_t *)&wild.len) !=
565 0) {
566 err = GRPC_OS_ERROR(errno, "getsockname");
567 close(fd);
568 return err;
569 }
570 close(fd);
571 *port = grpc_sockaddr_get_port(&wild);
572 return *port <= 0 ? GRPC_ERROR_CREATE("Bad port") : GRPC_ERROR_NONE;
573}
574
575/* Return the listener in s with address addr or NULL. */
576static grpc_tcp_listener *find_listener_with_addr(grpc_tcp_server *s,
577 grpc_resolved_address *addr) {
578 grpc_tcp_listener *l;
579 gpr_mu_lock(&s->mu);
580 for (l = s->head; l != NULL; l = l->next) {
581 if (l->addr.len != addr->len) {
582 continue;
583 }
584 if (memcmp(l->addr.addr, addr->addr, addr->len) == 0) {
585 break;
586 }
587 }
588 gpr_mu_unlock(&s->mu);
589 return l;
590}
591
592/* Get all addresses assigned to network interfaces on the machine and create a
593 listener for each. requested_port is the port to use for every listener, or 0
594 to select one random port that will be used for every listener. Set *out_port
595 to the port selected. Return GRPC_ERROR_NONE only if all listeners were
596 added. */
597static grpc_error *add_all_local_addrs_to_server(grpc_tcp_server *s,
598 unsigned port_index,
599 int requested_port,
600 int *out_port) {
601 struct ifaddrs *ifa = NULL;
602 struct ifaddrs *ifa_it;
603 unsigned fd_index = 0;
604 grpc_tcp_listener *sp = NULL;
605 grpc_error *err = GRPC_ERROR_NONE;
606 if (requested_port == 0) {
607 /* Note: There could be a race where some local addrs can listen on the
608 selected port and some can't. The sane way to handle this would be to
609 retry by recreating the whole grpc_tcp_server. Backing out individual
610 listeners and orphaning the FDs looks like too much trouble. */
611 if ((err = get_unused_port(&requested_port)) != GRPC_ERROR_NONE) {
612 return err;
613 } else if (requested_port <= 0) {
614 return GRPC_ERROR_CREATE("Bad get_unused_port()");
615 }
616 gpr_log(GPR_DEBUG, "Picked unused port %d", requested_port);
617 }
618 if (getifaddrs(&ifa) != 0 || ifa == NULL) {
619 return GRPC_OS_ERROR(errno, "getifaddrs");
620 }
621 for (ifa_it = ifa; ifa_it != NULL; ifa_it = ifa_it->ifa_next) {
622 grpc_resolved_address addr;
623 char *addr_str = NULL;
624 grpc_dualstack_mode dsmode;
625 grpc_tcp_listener *new_sp = NULL;
626 const char *ifa_name = (ifa_it->ifa_name ? ifa_it->ifa_name : "<unknown>");
627 if (ifa_it->ifa_addr == NULL) {
628 continue;
629 } else if (ifa_it->ifa_addr->sa_family == AF_INET) {
630 addr.len = sizeof(struct sockaddr_in);
631 } else if (ifa_it->ifa_addr->sa_family == AF_INET6) {
632 addr.len = sizeof(struct sockaddr_in6);
633 } else {
634 continue;
635 }
636 memcpy(addr.addr, ifa_it->ifa_addr, addr.len);
637 if (!grpc_sockaddr_set_port(&addr, requested_port)) {
638 /* Should never happen, because we check sa_family above. */
639 err = GRPC_ERROR_CREATE("Failed to set port");
640 break;
641 }
642 if (grpc_sockaddr_to_string(&addr_str, &addr, 0) < 0) {
643 addr_str = gpr_strdup("<error>");
644 }
645 gpr_log(GPR_DEBUG,
646 "Adding local addr from interface %s flags 0x%x to server: %s",
647 ifa_name, ifa_it->ifa_flags, addr_str);
648 /* We could have multiple interfaces with the same address (e.g., bonding),
649 so look for duplicates. */
650 if (find_listener_with_addr(s, &addr) != NULL) {
651 gpr_log(GPR_DEBUG, "Skipping duplicate addr %s on interface %s", addr_str,
652 ifa_name);
653 gpr_free(addr_str);
654 continue;
655 }
656 if ((err = add_addr_to_server(s, &addr, port_index, fd_index, &dsmode,
657 &new_sp)) != GRPC_ERROR_NONE) {
658 char *err_str = NULL;
659 grpc_error *root_err;
660 if (gpr_asprintf(&err_str, "Failed to add listener: %s", addr_str) < 0) {
661 err_str = gpr_strdup("Failed to add listener");
662 }
663 root_err = GRPC_ERROR_CREATE(err_str);
664 gpr_free(err_str);
665 gpr_free(addr_str);
666 err = grpc_error_add_child(root_err, err);
667 break;
668 } else {
669 GPR_ASSERT(requested_port == new_sp->port);
670 ++fd_index;
671 if (sp != NULL) {
672 new_sp->is_sibling = 1;
673 sp->sibling = new_sp;
674 }
675 sp = new_sp;
676 }
677 gpr_free(addr_str);
678 }
679 freeifaddrs(ifa);
680 if (err != GRPC_ERROR_NONE) {
681 return err;
682 } else if (sp == NULL) {
683 return GRPC_ERROR_CREATE("No local addresses");
684 } else {
685 *out_port = sp->port;
686 return GRPC_ERROR_NONE;
687 }
688}
689
690/* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
691static grpc_error *add_wildcard_addrs_to_server(grpc_tcp_server *s,
692 unsigned port_index,
693 int requested_port,
694 int *out_port) {
695 grpc_resolved_address wild4;
696 grpc_resolved_address wild6;
697 unsigned fd_index = 0;
698 grpc_dualstack_mode dsmode;
699 grpc_tcp_listener *sp = NULL;
700 grpc_tcp_listener *sp2 = NULL;
701 grpc_error *v6_err = GRPC_ERROR_NONE;
702 grpc_error *v4_err = GRPC_ERROR_NONE;
703 *out_port = -1;
704 if (s->expand_wildcard_addrs) {
705 return add_all_local_addrs_to_server(s, port_index, requested_port,
706 out_port);
707 }
708 grpc_sockaddr_make_wildcards(requested_port, &wild4, &wild6);
709 /* Try listening on IPv6 first. */
710 if ((v6_err = add_addr_to_server(s, &wild6, port_index, fd_index, &dsmode,
711 &sp)) == GRPC_ERROR_NONE) {
712 ++fd_index;
713 requested_port = *out_port = sp->port;
714 if (dsmode == GRPC_DSMODE_DUALSTACK || dsmode == GRPC_DSMODE_IPV4) {
715 return GRPC_ERROR_NONE;
716 }
717 }
718 /* If we got a v6-only socket or nothing, try adding 0.0.0.0. */
719 grpc_sockaddr_set_port(&wild4, requested_port);
720 if ((v4_err = add_addr_to_server(s, &wild4, port_index, fd_index, &dsmode,
721 &sp2)) == GRPC_ERROR_NONE) {
722 *out_port = sp2->port;
723 if (sp != NULL) {
724 sp2->is_sibling = 1;
725 sp->sibling = sp2;
726 }
727 }
728 if (*out_port > 0) {
729 GRPC_LOG_IF_ERROR("Failed to add :: listener", v6_err);
730 GRPC_LOG_IF_ERROR("Failed to add 0.0.0.0 listener", v4_err);
731 return GRPC_ERROR_NONE;
732 } else {
733 grpc_error *root_err =
734 GRPC_ERROR_CREATE("Failed to add any wildcard listeners");
735 GPR_ASSERT(v6_err != GRPC_ERROR_NONE && v4_err != GRPC_ERROR_NONE);
736 root_err = grpc_error_add_child(root_err, v6_err);
737 root_err = grpc_error_add_child(root_err, v4_err);
738 return root_err;
739 }
740}
741
Craig Tilleref962642016-05-18 22:57:17 -0700742static grpc_error *clone_port(grpc_tcp_listener *listener, unsigned count) {
743 grpc_tcp_listener *sp = NULL;
744 char *addr_str;
745 char *name;
746 grpc_error *err;
747
748 for (grpc_tcp_listener *l = listener->next; l && l->is_sibling; l = l->next) {
749 l->fd_index += count;
750 }
751
752 for (unsigned i = 0; i < count; i++) {
Craig Tiller136698c2016-05-19 11:49:44 -0700753 int fd = -1;
754 int port = -1;
Craig Tilleref962642016-05-18 22:57:17 -0700755 grpc_dualstack_mode dsmode;
murgatroid99dedb9232016-09-26 13:54:04 -0700756 err = grpc_create_dualstack_socket(&listener->addr, SOCK_STREAM, 0, &dsmode,
757 &fd);
Craig Tilleref962642016-05-18 22:57:17 -0700758 if (err != GRPC_ERROR_NONE) return err;
murgatroid997871f732016-09-23 13:49:05 -0700759 err = prepare_socket(fd, &listener->addr, true, &port);
Craig Tilleref962642016-05-18 22:57:17 -0700760 if (err != GRPC_ERROR_NONE) return err;
Craig Tiller644da982016-05-19 09:19:28 -0700761 listener->server->nports++;
murgatroid997871f732016-09-23 13:49:05 -0700762 grpc_sockaddr_to_string(&addr_str, &listener->addr, 1);
Craig Tilleref962642016-05-18 22:57:17 -0700763 gpr_asprintf(&name, "tcp-server-listener:%s/clone-%d", addr_str, i);
764 sp = gpr_malloc(sizeof(grpc_tcp_listener));
765 sp->next = listener->next;
766 listener->next = sp;
Dan Bornad1f31f2016-07-08 13:24:49 -0700767 /* sp (the new listener) is a sibling of 'listener' (the original
768 listener). */
769 sp->is_sibling = 1;
770 sp->sibling = listener->sibling;
771 listener->sibling = sp;
Craig Tilleref962642016-05-18 22:57:17 -0700772 sp->server = listener->server;
773 sp->fd = fd;
774 sp->emfd = grpc_fd_create(fd, name);
murgatroid997871f732016-09-23 13:49:05 -0700775 memcpy(&sp->addr, &listener->addr, sizeof(grpc_resolved_address));
Craig Tilleref962642016-05-18 22:57:17 -0700776 sp->port = port;
777 sp->port_index = listener->port_index;
778 sp->fd_index = listener->fd_index + count - i;
Craig Tilleref962642016-05-18 22:57:17 -0700779 GPR_ASSERT(sp->emfd);
780 while (listener->server->tail->next != NULL) {
781 listener->server->tail = listener->server->tail->next;
782 }
783 gpr_free(addr_str);
784 gpr_free(name);
785 }
786
787 return GRPC_ERROR_NONE;
788}
789
murgatroid997871f732016-09-23 13:49:05 -0700790grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
791 const grpc_resolved_address *addr,
792 int *out_port) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800793 grpc_tcp_listener *sp;
murgatroid997871f732016-09-23 13:49:05 -0700794 grpc_resolved_address sockname_temp;
Dan Born8886a812016-07-08 16:06:07 -0700795 grpc_resolved_address addr6_v4mapped;
796 int requested_port = grpc_sockaddr_get_port(addr);
Dan Bornfa6b6062016-01-08 21:01:59 -0800797 unsigned port_index = 0;
Dan Born8886a812016-07-08 16:06:07 -0700798 grpc_dualstack_mode dsmode;
799 grpc_error *err;
800 *out_port = -1;
Dan Bornfa6b6062016-01-08 21:01:59 -0800801 if (s->tail != NULL) {
802 port_index = s->tail->port_index + 1;
803 }
murgatroid997871f732016-09-23 13:49:05 -0700804 grpc_unlink_if_unix_domain_socket(addr);
Craig Tilleraa31da42015-02-17 16:33:35 -0800805
ctiller570d1f42015-01-12 16:29:52 -0800806 /* Check if this is a wildcard port, and if so, try to keep the port the same
807 as some previously created listener. */
Dan Born8886a812016-07-08 16:06:07 -0700808 if (requested_port == 0) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800809 for (sp = s->head; sp; sp = sp->next) {
murgatroid997871f732016-09-23 13:49:05 -0700810 sockname_temp.len = sizeof(struct sockaddr_storage);
Dan Born8886a812016-07-08 16:06:07 -0700811 if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp.addr,
murgatroid997871f732016-09-23 13:49:05 -0700812 (socklen_t *)&sockname_temp.len)) {
Dan Born8886a812016-07-08 16:06:07 -0700813 int used_port = grpc_sockaddr_get_port(&sockname_temp);
814 if (used_port > 0) {
815 memcpy(&sockname_temp, addr, sizeof(grpc_resolved_address));
816 grpc_sockaddr_set_port(&sockname_temp, used_port);
817 requested_port = used_port;
818 addr = &sockname_temp;
Craig Tillera82950e2015-09-22 12:33:20 -0700819 break;
820 }
821 }
ctiller570d1f42015-01-12 16:29:52 -0800822 }
Craig Tillera82950e2015-09-22 12:33:20 -0700823 }
Dan Born8886a812016-07-08 16:06:07 -0700824 if (grpc_sockaddr_is_wildcard(addr, &requested_port)) {
825 return add_wildcard_addrs_to_server(s, port_index, requested_port,
826 out_port);
827 }
Craig Tillera82950e2015-09-22 12:33:20 -0700828 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
murgatroid997871f732016-09-23 13:49:05 -0700829 addr = &addr6_v4mapped;
Craig Tillera82950e2015-09-22 12:33:20 -0700830 }
Dan Born8886a812016-07-08 16:06:07 -0700831 if ((err = add_addr_to_server(s, addr, port_index, 0, &dsmode, &sp)) ==
832 GRPC_ERROR_NONE) {
Craig Tillerc027e772016-05-03 16:27:00 -0700833 *out_port = sp->port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800834 }
Dan Born8886a812016-07-08 16:06:07 -0700835 return err;
nnoble0c475f02014-12-05 15:37:39 -0800836}
837
Dan Born19e01fd2016-10-18 11:49:45 -0700838/* Return listener at port_index or NULL. Should only be called with s->mu
839 locked. */
Dan Born4e826be2016-10-03 20:33:25 -0700840static grpc_tcp_listener *get_port_index(grpc_tcp_server *s,
841 unsigned port_index) {
842 unsigned num_ports = 0;
843 grpc_tcp_listener *sp;
844 for (sp = s->head; sp; sp = sp->next) {
845 if (!sp->is_sibling) {
846 if (++num_ports > port_index) {
847 return sp;
848 }
849 }
850 }
851 return NULL;
852}
853
Dan Born5d81d152016-01-12 20:29:29 -0800854unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
855 unsigned port_index) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800856 unsigned num_fds = 0;
Dan Born930c2982016-09-08 19:12:18 -0700857 gpr_mu_lock(&s->mu);
Dan Born4e826be2016-10-03 20:33:25 -0700858 grpc_tcp_listener *sp = get_port_index(s, port_index);
859 for (; sp; sp = sp->sibling) {
860 ++num_fds;
Dan Bornfa6b6062016-01-08 21:01:59 -0800861 }
Dan Born930c2982016-09-08 19:12:18 -0700862 gpr_mu_unlock(&s->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800863 return num_fds;
864}
865
Dan Born5d81d152016-01-12 20:29:29 -0800866int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
867 unsigned fd_index) {
Dan Born930c2982016-09-08 19:12:18 -0700868 gpr_mu_lock(&s->mu);
Dan Born4e826be2016-10-03 20:33:25 -0700869 grpc_tcp_listener *sp = get_port_index(s, port_index);
870 for (; sp; sp = sp->sibling, --fd_index) {
871 if (fd_index == 0) {
Dan Bornd9b763b2016-10-17 15:00:20 -0700872 gpr_mu_unlock(&s->mu);
Dan Born4e826be2016-10-03 20:33:25 -0700873 return sp->fd;
Dan Bornfa6b6062016-01-08 21:01:59 -0800874 }
875 }
Dan Born930c2982016-09-08 19:12:18 -0700876 gpr_mu_unlock(&s->mu);
Dan Born4e826be2016-10-03 20:33:25 -0700877 return -1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800878}
879
Craig Tillera82950e2015-09-22 12:33:20 -0700880void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
881 grpc_pollset **pollsets, size_t pollset_count,
882 grpc_tcp_server_cb on_accept_cb,
883 void *on_accept_cb_arg) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800884 size_t i;
Nicolas Noble8f714622015-11-19 11:16:54 -0800885 grpc_tcp_listener *sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700886 GPR_ASSERT(on_accept_cb);
887 gpr_mu_lock(&s->mu);
888 GPR_ASSERT(!s->on_accept_cb);
889 GPR_ASSERT(s->active_ports == 0);
Robbie Shade3cd2d182015-08-28 14:30:35 -0400890 s->on_accept_cb = on_accept_cb;
891 s->on_accept_cb_arg = on_accept_cb_arg;
Craig Tiller0189ac02015-05-11 14:59:19 -0700892 s->pollsets = pollsets;
893 s->pollset_count = pollset_count;
Craig Tilleref962642016-05-18 22:57:17 -0700894 sp = s->head;
895 while (sp != NULL) {
murgatroid997871f732016-09-23 13:49:05 -0700896 if (s->so_reuseport && !grpc_is_unix_socket(&sp->addr) &&
Yuchen Zengd745a6f2016-08-08 20:44:36 -0700897 pollset_count > 1) {
Craig Tilleref962642016-05-18 22:57:17 -0700898 GPR_ASSERT(GRPC_LOG_IF_ERROR(
899 "clone_port", clone_port(sp, (unsigned)(pollset_count - 1))));
900 for (i = 0; i < pollset_count; i++) {
901 grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
Craig Tiller3cb34472016-12-28 16:11:38 -0800902 grpc_closure_init(&sp->read_closure, on_read, sp,
903 grpc_schedule_on_exec_ctx);
Craig Tilleref962642016-05-18 22:57:17 -0700904 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
905 s->active_ports++;
906 sp = sp->next;
907 }
908 } else {
909 for (i = 0; i < pollset_count; i++) {
910 grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
911 }
Craig Tiller3cb34472016-12-28 16:11:38 -0800912 grpc_closure_init(&sp->read_closure, on_read, sp,
913 grpc_schedule_on_exec_ctx);
Craig Tilleref962642016-05-18 22:57:17 -0700914 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
915 s->active_ports++;
916 sp = sp->next;
ctiller58393c22015-01-07 14:03:30 -0800917 }
Craig Tillera82950e2015-09-22 12:33:20 -0700918 }
919 gpr_mu_unlock(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800920}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800921
Dan Bornfa6b6062016-01-08 21:01:59 -0800922grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
Dan Born930c2982016-09-08 19:12:18 -0700923 gpr_ref_non_zero(&s->refs);
Dan Bornfa6b6062016-01-08 21:01:59 -0800924 return s;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800925}
926
Dan Born9c12bc22016-01-13 16:52:20 -0800927void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
928 grpc_closure *shutdown_starting) {
929 gpr_mu_lock(&s->mu);
Craig Tillerc027e772016-05-03 16:27:00 -0700930 grpc_closure_list_append(&s->shutdown_starting, shutdown_starting,
931 GRPC_ERROR_NONE);
Dan Born9c12bc22016-01-13 16:52:20 -0800932 gpr_mu_unlock(&s->mu);
933}
934
Dan Bornfa6b6062016-01-08 21:01:59 -0800935void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
936 if (gpr_unref(&s->refs)) {
Dan Born930c2982016-09-08 19:12:18 -0700937 grpc_tcp_server_shutdown_listeners(exec_ctx, s);
Dan Born9c12bc22016-01-13 16:52:20 -0800938 gpr_mu_lock(&s->mu);
Craig Tiller91031da2016-12-28 15:44:25 -0800939 grpc_closure_list_sched(exec_ctx, &s->shutdown_starting);
Dan Born9c12bc22016-01-13 16:52:20 -0800940 gpr_mu_unlock(&s->mu);
Dan Born930c2982016-09-08 19:12:18 -0700941 tcp_server_destroy(exec_ctx, s);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800942 }
943}
944
yang-g9275d402016-07-11 16:51:39 -0700945void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
946 grpc_tcp_server *s) {
947 gpr_mu_lock(&s->mu);
Craig Tillerf26236a2017-03-07 09:43:51 -0800948 s->shutdown_listeners = true;
yang-g9275d402016-07-11 16:51:39 -0700949 /* shutdown all fd's */
950 if (s->active_ports) {
951 grpc_tcp_listener *sp;
952 for (sp = s->head; sp; sp = sp->next) {
Craig Tillercda759d2017-01-27 11:37:37 -0800953 grpc_fd_shutdown(exec_ctx, sp->emfd,
954 GRPC_ERROR_CREATE("Server shutdown"));
yang-g9275d402016-07-11 16:51:39 -0700955 }
956 }
957 gpr_mu_unlock(&s->mu);
958}
959
Craig Tiller190d3602015-02-18 09:23:38 -0800960#endif