blob: 1439dfcd6edb0b6b773a19344ba0540a3d84ab08 [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
Craig Tiller06059952015-02-18 08:34:56 -08003 * 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
ctiller18b49ab2014-12-09 14:39:16 -080043#include "src/core/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>
Craig Tillerae7fe922015-02-13 23:16:32 -080055#include <sys/un.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056#include <unistd.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080057
ctiller58393c22015-01-07 14:03:30 -080058#include "src/core/iomgr/pollset_posix.h"
Craig Tillerae7fe922015-02-13 23:16:32 -080059#include "src/core/iomgr/resolve_address.h"
ctiller18b49ab2014-12-09 14:39:16 -080060#include "src/core/iomgr/sockaddr_utils.h"
61#include "src/core/iomgr/socket_utils_posix.h"
62#include "src/core/iomgr/tcp_posix.h"
Craig Tillerfa275a92015-06-01 13:55:54 -070063#include "src/core/support/string.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080064#include <grpc/support/alloc.h>
65#include <grpc/support/log.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070066#include <grpc/support/string_util.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080067#include <grpc/support/sync.h>
68#include <grpc/support/time.h>
69
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080070#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
71
72static gpr_once s_init_max_accept_queue_size;
73static int s_max_accept_queue_size;
74
75/* one listening port */
Nicolas Noble8f714622015-11-19 11:16:54 -080076struct grpc_tcp_listener {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080077 int fd;
ctiller18b49ab2014-12-09 14:39:16 -080078 grpc_fd *emfd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080079 grpc_tcp_server *server;
Craig Tillera82950e2015-09-22 12:33:20 -070080 union {
Craig Tiller772c97b2015-02-17 08:07:34 -080081 gpr_uint8 untyped[GRPC_MAX_SOCKADDR_SIZE];
82 struct sockaddr sockaddr;
83 struct sockaddr_un un;
84 } addr;
Craig Tillerf96dfc32015-09-10 14:43:18 -070085 size_t addr_len;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080086 int port;
Craig Tiller33825112015-09-18 07:44:19 -070087 grpc_closure read_closure;
88 grpc_closure destroyed_closure;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080089 gpr_refcount refs;
Nicolas Noble8f714622015-11-19 11:16:54 -080090 struct grpc_tcp_listener *next;
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +010091 /* When we add a listener, more than one can be created, mainly because of
92 IPv6. A sibling will still be in the normal list, but will be flagged
93 as such. Any action, such as ref or unref, will affect all of the
94 siblings in the list. */
95 struct grpc_tcp_listener *sibling;
96 int is_sibling;
Nicolas Noble8f714622015-11-19 11:16:54 -080097};
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080098
Craig Tillera82950e2015-09-22 12:33:20 -070099static void unlink_if_unix_domain_socket(const struct sockaddr_un *un) {
Craig Tilleraa31da42015-02-17 16:33:35 -0800100 struct stat st;
101
Craig Tillera82950e2015-09-22 12:33:20 -0700102 if (stat(un->sun_path, &st) == 0 && (st.st_mode & S_IFMT) == S_IFSOCK) {
103 unlink(un->sun_path);
104 }
Craig Tilleraa31da42015-02-17 16:33:35 -0800105}
106
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800107/* the overall server */
Craig Tillera82950e2015-09-22 12:33:20 -0700108struct grpc_tcp_server {
Robbie Shade3cd2d182015-08-28 14:30:35 -0400109 /* Called whenever accept() succeeds on a server port. */
110 grpc_tcp_server_cb on_accept_cb;
111 void *on_accept_cb_arg;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800112
113 gpr_mu mu;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800114
115 /* active port count: how many ports are actually still listening */
Craig Tilleraec96aa2015-04-07 14:32:15 -0700116 size_t active_ports;
117 /* destroyed port count: how many ports are completely destroyed */
118 size_t destroyed_ports;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800119
Craig Tiller6174b9a2015-06-18 08:13:05 -0700120 /* is this server shutting down? (boolean) */
Craig Tiller6f051402015-05-13 11:42:42 -0700121 int shutdown;
122
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800123 /* linked list of server ports */
Nicolas Noble8f714622015-11-19 11:16:54 -0800124 grpc_tcp_listener *head;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800125 unsigned nports;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700126
127 /* shutdown callback */
Craig Tillerd1bec032015-09-18 17:29:00 -0700128 grpc_closure *shutdown_complete;
Craig Tiller0189ac02015-05-11 14:59:19 -0700129
Craig Tiller6174b9a2015-06-18 08:13:05 -0700130 /* all pollsets interested in new connections */
Craig Tiller0189ac02015-05-11 14:59:19 -0700131 grpc_pollset **pollsets;
Craig Tiller6174b9a2015-06-18 08:13:05 -0700132 /* number of pollsets in the pollsets array */
Craig Tiller0189ac02015-05-11 14:59:19 -0700133 size_t pollset_count;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800134};
135
Craig Tillera82950e2015-09-22 12:33:20 -0700136grpc_tcp_server *grpc_tcp_server_create(void) {
137 grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
138 gpr_mu_init(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800139 s->active_ports = 0;
Craig Tilleraec96aa2015-04-07 14:32:15 -0700140 s->destroyed_ports = 0;
Craig Tiller6f051402015-05-13 11:42:42 -0700141 s->shutdown = 0;
Robbie Shade3cd2d182015-08-28 14:30:35 -0400142 s->on_accept_cb = NULL;
143 s->on_accept_cb_arg = NULL;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800144 s->head = NULL;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800145 s->nports = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800146 return s;
147}
148
Craig Tillera82950e2015-09-22 12:33:20 -0700149static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
150 grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, 1);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700151
Craig Tillera82950e2015-09-22 12:33:20 -0700152 gpr_mu_destroy(&s->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700153
Nicolas "Pixel" Noblec6a7c6e2015-11-19 21:55:44 +0100154 while (s->head) {
155 grpc_tcp_listener *sp = s->head;
156 s->head = sp->next;
Nicolas Noble8f714622015-11-19 11:16:54 -0800157 grpc_tcp_listener_unref(sp);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800158 }
159
Craig Tillera82950e2015-09-22 12:33:20 -0700160 gpr_free(s);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700161}
162
Craig Tillera82950e2015-09-22 12:33:20 -0700163static void destroyed_port(grpc_exec_ctx *exec_ctx, void *server, int success) {
Craig Tilleraec96aa2015-04-07 14:32:15 -0700164 grpc_tcp_server *s = server;
Craig Tillera82950e2015-09-22 12:33:20 -0700165 gpr_mu_lock(&s->mu);
Craig Tilleraec96aa2015-04-07 14:32:15 -0700166 s->destroyed_ports++;
Craig Tillera82950e2015-09-22 12:33:20 -0700167 if (s->destroyed_ports == s->nports) {
168 gpr_mu_unlock(&s->mu);
169 finish_shutdown(exec_ctx, s);
170 } else {
171 GPR_ASSERT(s->destroyed_ports < s->nports);
172 gpr_mu_unlock(&s->mu);
173 }
Craig Tilleraec96aa2015-04-07 14:32:15 -0700174}
175
Craig Tiller6174b9a2015-06-18 08:13:05 -0700176/* called when all listening endpoints have been shutdown, so no further
177 events will be received on them - at this point it's safe to destroy
178 things */
Craig Tillera82950e2015-09-22 12:33:20 -0700179static void deactivated_all_ports(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800180 /* delete ALL the things */
Craig Tillera82950e2015-09-22 12:33:20 -0700181 gpr_mu_lock(&s->mu);
Craig Tiller6f051402015-05-13 11:42:42 -0700182
Craig Tillera82950e2015-09-22 12:33:20 -0700183 if (!s->shutdown) {
184 gpr_mu_unlock(&s->mu);
185 return;
186 }
Craig Tiller45724b32015-09-22 10:42:19 -0700187
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800188 if (s->head) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800189 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800190 for (sp = s->head; sp; sp = sp->next) {
Craig Tillera82950e2015-09-22 12:33:20 -0700191 if (sp->addr.sockaddr.sa_family == AF_UNIX) {
192 unlink_if_unix_domain_socket(&sp->addr.un);
193 }
194 sp->destroyed_closure.cb = destroyed_port;
195 sp->destroyed_closure.cb_arg = s;
196 grpc_fd_orphan(exec_ctx, sp->emfd, &sp->destroyed_closure,
197 "tcp_listener_shutdown");
Craig Tiller45724b32015-09-22 10:42:19 -0700198 }
Craig Tillera82950e2015-09-22 12:33:20 -0700199 gpr_mu_unlock(&s->mu);
200 } else {
201 gpr_mu_unlock(&s->mu);
202 finish_shutdown(exec_ctx, s);
203 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800204}
205
Craig Tillera82950e2015-09-22 12:33:20 -0700206void grpc_tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
207 grpc_closure *closure) {
Craig Tillera82950e2015-09-22 12:33:20 -0700208 gpr_mu_lock(&s->mu);
Craig Tiller6f051402015-05-13 11:42:42 -0700209
Craig Tillera82950e2015-09-22 12:33:20 -0700210 GPR_ASSERT(!s->shutdown);
Craig Tiller6f051402015-05-13 11:42:42 -0700211 s->shutdown = 1;
212
Craig Tillerd1bec032015-09-18 17:29:00 -0700213 s->shutdown_complete = closure;
Craig Tiller6f051402015-05-13 11:42:42 -0700214
215 /* shutdown all fd's */
Craig Tillera82950e2015-09-22 12:33:20 -0700216 if (s->active_ports) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800217 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800218 for (sp = s->head; sp; sp = sp->next) {
219 grpc_fd_shutdown(exec_ctx, sp->emfd);
Craig Tiller6f051402015-05-13 11:42:42 -0700220 }
Craig Tillera82950e2015-09-22 12:33:20 -0700221 gpr_mu_unlock(&s->mu);
222 } else {
223 gpr_mu_unlock(&s->mu);
224 deactivated_all_ports(exec_ctx, s);
225 }
Craig Tiller6f051402015-05-13 11:42:42 -0700226}
227
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800228/* get max listen queue size on linux */
Craig Tillera82950e2015-09-22 12:33:20 -0700229static void init_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800230 int n = SOMAXCONN;
231 char buf[64];
Craig Tillera82950e2015-09-22 12:33:20 -0700232 FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
233 if (fp == NULL) {
234 /* 2.4 kernel. */
235 s_max_accept_queue_size = SOMAXCONN;
236 return;
237 }
238 if (fgets(buf, sizeof buf, fp)) {
239 char *end;
240 long i = strtol(buf, &end, 10);
241 if (i > 0 && i <= INT_MAX && end && *end == 0) {
242 n = (int)i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800243 }
Craig Tillera82950e2015-09-22 12:33:20 -0700244 }
245 fclose(fp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800246 s_max_accept_queue_size = n;
247
Craig Tillera82950e2015-09-22 12:33:20 -0700248 if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
249 gpr_log(GPR_INFO,
250 "Suspiciously small accept queue (%d) will probably lead to "
251 "connection drops",
252 s_max_accept_queue_size);
253 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800254}
255
Craig Tillera82950e2015-09-22 12:33:20 -0700256static int get_max_accept_queue_size(void) {
257 gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800258 return s_max_accept_queue_size;
259}
260
nnoble0c475f02014-12-05 15:37:39 -0800261/* Prepare a recently-created socket for listening. */
Craig Tillera82950e2015-09-22 12:33:20 -0700262static int prepare_socket(int fd, const struct sockaddr *addr,
263 size_t addr_len) {
ctiller570d1f42015-01-12 16:29:52 -0800264 struct sockaddr_storage sockname_temp;
265 socklen_t sockname_len;
266
Craig Tillera82950e2015-09-22 12:33:20 -0700267 if (fd < 0) {
268 goto error;
269 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800270
Craig Tillera82950e2015-09-22 12:33:20 -0700271 if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
272 (addr->sa_family != AF_UNIX && (!grpc_set_socket_low_latency(fd, 1) ||
273 !grpc_set_socket_reuse_addr(fd, 1))) ||
274 !grpc_set_socket_no_sigpipe_if_possible(fd)) {
275 gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
276 strerror(errno));
277 goto error;
278 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800279
Craig Tillera82950e2015-09-22 12:33:20 -0700280 GPR_ASSERT(addr_len < ~(socklen_t)0);
281 if (bind(fd, addr, (socklen_t)addr_len) < 0) {
282 char *addr_str;
283 grpc_sockaddr_to_string(&addr_str, addr, 0);
284 gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
285 gpr_free(addr_str);
286 goto error;
287 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800288
Craig Tillera82950e2015-09-22 12:33:20 -0700289 if (listen(fd, get_max_accept_queue_size()) < 0) {
290 gpr_log(GPR_ERROR, "listen: %s", strerror(errno));
291 goto error;
292 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800293
Craig Tillera82950e2015-09-22 12:33:20 -0700294 sockname_len = sizeof(sockname_temp);
295 if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
296 goto error;
297 }
ctiller570d1f42015-01-12 16:29:52 -0800298
Craig Tillera82950e2015-09-22 12:33:20 -0700299 return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800300
301error:
Craig Tillera82950e2015-09-22 12:33:20 -0700302 if (fd >= 0) {
303 close(fd);
304 }
ctiller570d1f42015-01-12 16:29:52 -0800305 return -1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800306}
307
308/* event manager callback when reads are ready */
Craig Tillera82950e2015-09-22 12:33:20 -0700309static void on_read(grpc_exec_ctx *exec_ctx, void *arg, int success) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800310 grpc_tcp_listener *sp = arg;
Craig Tiller0189ac02015-05-11 14:59:19 -0700311 grpc_fd *fdobj;
312 size_t i;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800313
Craig Tillera82950e2015-09-22 12:33:20 -0700314 if (!success) {
315 goto error;
316 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800317
318 /* loop until accept4 returns EAGAIN, and then re-arm notification */
Craig Tillera82950e2015-09-22 12:33:20 -0700319 for (;;) {
320 struct sockaddr_storage addr;
321 socklen_t addrlen = sizeof(addr);
322 char *addr_str;
323 char *name;
324 /* Note: If we ever decide to return this address to the user, remember to
325 strip off the ::ffff:0.0.0.0/96 prefix first. */
326 int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
327 if (fd < 0) {
328 switch (errno) {
329 case EINTR:
330 continue;
331 case EAGAIN:
332 grpc_fd_notify_on_read(exec_ctx, sp->emfd, &sp->read_closure);
333 return;
334 default:
335 gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
336 goto error;
337 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800338 }
339
Craig Tillera82950e2015-09-22 12:33:20 -0700340 grpc_set_socket_no_sigpipe_if_possible(fd);
341
342 addr_str = grpc_sockaddr_to_uri((struct sockaddr *)&addr);
343 gpr_asprintf(&name, "tcp-server-connection:%s", addr_str);
344
345 if (grpc_tcp_trace) {
346 gpr_log(GPR_DEBUG, "SERVER_CONNECT: incoming connection: %s", addr_str);
347 }
348
349 fdobj = grpc_fd_create(fd, name);
350 /* TODO(ctiller): revise this when we have server-side sharding
351 of channels -- we certainly should not be automatically adding every
352 incoming channel to every pollset owned by the server */
353 for (i = 0; i < sp->server->pollset_count; i++) {
354 grpc_pollset_add_fd(exec_ctx, sp->server->pollsets[i], fdobj);
355 }
356 sp->server->on_accept_cb(
357 exec_ctx, sp->server->on_accept_cb_arg,
358 grpc_tcp_create(fdobj, GRPC_TCP_DEFAULT_READ_SLICE_SIZE, addr_str));
359
360 gpr_free(name);
361 gpr_free(addr_str);
362 }
363
yang-gb063c872015-10-07 11:40:13 -0700364 GPR_UNREACHABLE_CODE(return );
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800365
366error:
Craig Tillera82950e2015-09-22 12:33:20 -0700367 gpr_mu_lock(&sp->server->mu);
368 if (0 == --sp->server->active_ports) {
369 gpr_mu_unlock(&sp->server->mu);
370 deactivated_all_ports(exec_ctx, sp->server);
371 } else {
372 gpr_mu_unlock(&sp->server->mu);
373 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800374}
375
Nicolas Noble8f714622015-11-19 11:16:54 -0800376static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, int fd,
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800377 const struct sockaddr *addr,
378 size_t addr_len) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800379 grpc_tcp_listener *sp = NULL;
ctiller570d1f42015-01-12 16:29:52 -0800380 int port;
Craig Tillerfa275a92015-06-01 13:55:54 -0700381 char *addr_str;
382 char *name;
nnoble0c475f02014-12-05 15:37:39 -0800383
Craig Tillera82950e2015-09-22 12:33:20 -0700384 port = prepare_socket(fd, addr, addr_len);
385 if (port >= 0) {
386 grpc_sockaddr_to_string(&addr_str, (struct sockaddr *)&addr, 1);
387 gpr_asprintf(&name, "tcp-server-listener:%s", addr_str);
388 gpr_mu_lock(&s->mu);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800389 s->nports++;
Craig Tillera82950e2015-09-22 12:33:20 -0700390 GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
Nicolas Noble8f714622015-11-19 11:16:54 -0800391 sp = gpr_malloc(sizeof(grpc_tcp_listener));
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800392 sp->next = s->head;
393 s->head = sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700394 sp->server = s;
395 sp->fd = fd;
396 sp->emfd = grpc_fd_create(fd, name);
397 memcpy(sp->addr.untyped, addr, addr_len);
398 sp->addr_len = addr_len;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800399 sp->port = port;
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +0100400 sp->is_sibling = 0;
401 sp->sibling = NULL;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800402 gpr_ref_init(&sp->refs, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700403 GPR_ASSERT(sp->emfd);
404 gpr_mu_unlock(&s->mu);
405 gpr_free(addr_str);
406 gpr_free(name);
407 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800408
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800409 return sp;
nnoble0c475f02014-12-05 15:37:39 -0800410}
411
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800412grpc_tcp_listener *grpc_tcp_server_add_port(grpc_tcp_server *s,
413 const void *addr,
414 size_t addr_len) {
415 int allocated_port = -1;
Nicolas Noble8f714622015-11-19 11:16:54 -0800416 grpc_tcp_listener *sp;
417 grpc_tcp_listener *sp2 = NULL;
nnoble0c475f02014-12-05 15:37:39 -0800418 int fd;
419 grpc_dualstack_mode dsmode;
420 struct sockaddr_in6 addr6_v4mapped;
421 struct sockaddr_in wild4;
422 struct sockaddr_in6 wild6;
423 struct sockaddr_in addr4_copy;
ctiller570d1f42015-01-12 16:29:52 -0800424 struct sockaddr *allocated_addr = NULL;
425 struct sockaddr_storage sockname_temp;
426 socklen_t sockname_len;
nnoble0c475f02014-12-05 15:37:39 -0800427 int port;
428
Craig Tillera82950e2015-09-22 12:33:20 -0700429 if (((struct sockaddr *)addr)->sa_family == AF_UNIX) {
430 unlink_if_unix_domain_socket(addr);
431 }
Craig Tilleraa31da42015-02-17 16:33:35 -0800432
ctiller570d1f42015-01-12 16:29:52 -0800433 /* Check if this is a wildcard port, and if so, try to keep the port the same
434 as some previously created listener. */
Craig Tillera82950e2015-09-22 12:33:20 -0700435 if (grpc_sockaddr_get_port(addr) == 0) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800436 for (sp = s->head; sp; sp = sp->next) {
Craig Tillera82950e2015-09-22 12:33:20 -0700437 sockname_len = sizeof(sockname_temp);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800438 if (0 == getsockname(sp->fd, (struct sockaddr *)&sockname_temp,
Craig Tillera82950e2015-09-22 12:33:20 -0700439 &sockname_len)) {
440 port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
441 if (port > 0) {
442 allocated_addr = malloc(addr_len);
443 memcpy(allocated_addr, addr, addr_len);
444 grpc_sockaddr_set_port(allocated_addr, port);
445 addr = allocated_addr;
446 break;
447 }
448 }
ctiller570d1f42015-01-12 16:29:52 -0800449 }
Craig Tillera82950e2015-09-22 12:33:20 -0700450 }
ctiller570d1f42015-01-12 16:29:52 -0800451
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800452 sp = NULL;
453
Craig Tillera82950e2015-09-22 12:33:20 -0700454 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
455 addr = (const struct sockaddr *)&addr6_v4mapped;
456 addr_len = sizeof(addr6_v4mapped);
457 }
nnoble0c475f02014-12-05 15:37:39 -0800458
459 /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
Craig Tillera82950e2015-09-22 12:33:20 -0700460 if (grpc_sockaddr_is_wildcard(addr, &port)) {
461 grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
nnoble0c475f02014-12-05 15:37:39 -0800462
Craig Tillera82950e2015-09-22 12:33:20 -0700463 /* Try listening on IPv6 first. */
464 addr = (struct sockaddr *)&wild6;
465 addr_len = sizeof(wild6);
466 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800467 sp = add_socket_to_server(s, fd, addr, addr_len);
468 allocated_port = sp->port;
Craig Tillera82950e2015-09-22 12:33:20 -0700469 if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
470 goto done;
nnoble0c475f02014-12-05 15:37:39 -0800471 }
472
Craig Tillera82950e2015-09-22 12:33:20 -0700473 /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800474 if (port == 0 && allocated_port > 0) {
475 grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port);
476 sp2 = sp;
ctiller570d1f42015-01-12 16:29:52 -0800477 }
Craig Tillera82950e2015-09-22 12:33:20 -0700478 addr = (struct sockaddr *)&wild4;
479 addr_len = sizeof(wild4);
480 }
481
482 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
483 if (fd < 0) {
484 gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
485 }
486 if (dsmode == GRPC_DSMODE_IPV4 &&
487 grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
488 addr = (struct sockaddr *)&addr4_copy;
489 addr_len = sizeof(addr4_copy);
490 }
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800491 sp = add_socket_to_server(s, fd, addr, addr_len);
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +0100492 sp->sibling = sp2;
493 if (sp2) sp2->is_sibling = 1;
ctiller570d1f42015-01-12 16:29:52 -0800494
495done:
Craig Tillera82950e2015-09-22 12:33:20 -0700496 gpr_free(allocated_addr);
Nicolas Noble8f714622015-11-19 11:16:54 -0800497 return sp;
nnoble0c475f02014-12-05 15:37:39 -0800498}
499
Vijay Pai7b080ba2015-09-29 22:22:36 +0000500int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned port_index) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800501 grpc_tcp_listener *sp;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800502 for (sp = s->head; sp && port_index != 0; sp = sp->next, port_index--);
503 if (port_index == 0 && sp) {
504 return sp->fd;
505 } else {
506 return -1;
507 }
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800508}
509
Craig Tillera82950e2015-09-22 12:33:20 -0700510void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
511 grpc_pollset **pollsets, size_t pollset_count,
512 grpc_tcp_server_cb on_accept_cb,
513 void *on_accept_cb_arg) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800514 size_t i;
Nicolas Noble8f714622015-11-19 11:16:54 -0800515 grpc_tcp_listener *sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700516 GPR_ASSERT(on_accept_cb);
517 gpr_mu_lock(&s->mu);
518 GPR_ASSERT(!s->on_accept_cb);
519 GPR_ASSERT(s->active_ports == 0);
Robbie Shade3cd2d182015-08-28 14:30:35 -0400520 s->on_accept_cb = on_accept_cb;
521 s->on_accept_cb_arg = on_accept_cb_arg;
Craig Tiller0189ac02015-05-11 14:59:19 -0700522 s->pollsets = pollsets;
523 s->pollset_count = pollset_count;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800524 for (sp = s->head; sp; sp = sp->next) {
525 for (i = 0; i < pollset_count; i++) {
526 grpc_pollset_add_fd(exec_ctx, pollsets[i], sp->emfd);
ctiller58393c22015-01-07 14:03:30 -0800527 }
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800528 sp->read_closure.cb = on_read;
529 sp->read_closure.cb_arg = sp;
530 grpc_fd_notify_on_read(exec_ctx, sp->emfd,
531 &sp->read_closure);
Craig Tillera82950e2015-09-22 12:33:20 -0700532 s->active_ports++;
533 }
534 gpr_mu_unlock(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800535}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800536
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800537int grpc_tcp_listener_get_port(grpc_tcp_listener *listener) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800538 grpc_tcp_listener *sp = listener;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800539 return sp->port;
540}
541
542void grpc_tcp_listener_ref(grpc_tcp_listener *listener) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800543 grpc_tcp_listener *sp = listener;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800544 gpr_ref(&sp->refs);
545}
546
547void grpc_tcp_listener_unref(grpc_tcp_listener *listener) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800548 grpc_tcp_listener *sp = listener;
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +0100549 if (sp->is_sibling) return;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800550 if (gpr_unref(&sp->refs)) {
Nicolas "Pixel" Nobled86115e2015-11-20 05:56:25 +0100551 grpc_tcp_listener *sibling = sp->sibling;
552 while (sibling) {
553 sp = sibling;
554 sibling = sp->sibling;
555 gpr_free(sp);
556 }
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800557 gpr_free(listener);
558 }
559}
560
Craig Tiller190d3602015-02-18 09:23:38 -0800561#endif