blob: 6a9616371885d43421af22c7e6b108b7d08282ea [file] [log] [blame]
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -08001/*
2 *
3 * Copyright 2014, Google Inc.
4 * 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
45#include <limits.h>
46#include <fcntl.h>
47#include <netinet/in.h>
48#include <netinet/tcp.h>
49#include <stdio.h>
50#include <sys/types.h>
Craig Tillerae7fe922015-02-13 23:16:32 -080051#include <sys/un.h>
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080052#include <sys/socket.h>
53#include <unistd.h>
54#include <string.h>
55#include <errno.h>
56
ctiller58393c22015-01-07 14:03:30 -080057#include "src/core/iomgr/pollset_posix.h"
Craig Tillerae7fe922015-02-13 23:16:32 -080058#include "src/core/iomgr/resolve_address.h"
ctiller18b49ab2014-12-09 14:39:16 -080059#include "src/core/iomgr/sockaddr_utils.h"
60#include "src/core/iomgr/socket_utils_posix.h"
61#include "src/core/iomgr/tcp_posix.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080062#include <grpc/support/alloc.h>
63#include <grpc/support/log.h>
64#include <grpc/support/sync.h>
65#include <grpc/support/time.h>
66
67#define INIT_PORT_CAP 2
68#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
69
70static gpr_once s_init_max_accept_queue_size;
71static int s_max_accept_queue_size;
72
73/* one listening port */
74typedef struct {
75 int fd;
ctiller18b49ab2014-12-09 14:39:16 -080076 grpc_fd *emfd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080077 grpc_tcp_server *server;
Craig Tiller772c97b2015-02-17 08:07:34 -080078 union {
79 gpr_uint8 untyped[GRPC_MAX_SOCKADDR_SIZE];
80 struct sockaddr sockaddr;
81 struct sockaddr_un un;
82 } addr;
Craig Tillerae7fe922015-02-13 23:16:32 -080083 int addr_len;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080084} server_port;
85
86/* the overall server */
87struct grpc_tcp_server {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080088 grpc_tcp_server_cb cb;
89 void *cb_arg;
90
91 gpr_mu mu;
92 gpr_cv cv;
93
94 /* active port count: how many ports are actually still listening */
95 int active_ports;
96
97 /* all listening ports */
98 server_port *ports;
99 size_t nports;
100 size_t port_capacity;
101};
102
Craig Tiller32946d32015-01-15 11:37:30 -0800103grpc_tcp_server *grpc_tcp_server_create(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800104 grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
105 gpr_mu_init(&s->mu);
106 gpr_cv_init(&s->cv);
107 s->active_ports = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800108 s->cb = NULL;
109 s->cb_arg = NULL;
110 s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
111 s->nports = 0;
112 s->port_capacity = INIT_PORT_CAP;
113 return s;
114}
115
116void grpc_tcp_server_destroy(grpc_tcp_server *s) {
117 size_t i;
118 gpr_mu_lock(&s->mu);
119 /* shutdown all fd's */
120 for (i = 0; i < s->nports; i++) {
ctiller18b49ab2014-12-09 14:39:16 -0800121 grpc_fd_shutdown(s->ports[i].emfd);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800122 }
123 /* wait while that happens */
124 while (s->active_ports) {
125 gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
126 }
127 gpr_mu_unlock(&s->mu);
128
129 /* delete ALL the things */
130 for (i = 0; i < s->nports; i++) {
131 server_port *sp = &s->ports[i];
Craig Tiller772c97b2015-02-17 08:07:34 -0800132 if (sp->addr.sockaddr.sa_family == AF_UNIX) {
133 unlink(sp->addr.un.sun_path);
Craig Tillerae7fe922015-02-13 23:16:32 -0800134 }
ctiller58393c22015-01-07 14:03:30 -0800135 grpc_fd_orphan(sp->emfd, NULL, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800136 }
137 gpr_free(s->ports);
138 gpr_free(s);
139}
140
141/* get max listen queue size on linux */
Craig Tiller32946d32015-01-15 11:37:30 -0800142static void init_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800143 int n = SOMAXCONN;
144 char buf[64];
145 FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
146 if (fp == NULL) {
147 /* 2.4 kernel. */
148 s_max_accept_queue_size = SOMAXCONN;
149 return;
150 }
151 if (fgets(buf, sizeof buf, fp)) {
152 char *end;
153 long i = strtol(buf, &end, 10);
154 if (i > 0 && i <= INT_MAX && end && *end == 0) {
155 n = i;
156 }
157 }
158 fclose(fp);
159 s_max_accept_queue_size = n;
160
161 if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
162 gpr_log(GPR_INFO,
163 "Suspiciously small accept queue (%d) will probably lead to "
164 "connection drops",
165 s_max_accept_queue_size);
166 }
167}
168
Craig Tiller32946d32015-01-15 11:37:30 -0800169static int get_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800170 gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
171 return s_max_accept_queue_size;
172}
173
nnoble0c475f02014-12-05 15:37:39 -0800174/* Prepare a recently-created socket for listening. */
175static int prepare_socket(int fd, const struct sockaddr *addr, int addr_len) {
ctiller570d1f42015-01-12 16:29:52 -0800176 struct sockaddr_storage sockname_temp;
177 socklen_t sockname_len;
178
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800179 if (fd < 0) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800180 goto error;
181 }
182
183 if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
Craig Tillerd209ed02015-02-13 23:18:15 -0800184 (addr->sa_family != AF_UNIX && (!grpc_set_socket_low_latency(fd, 1) ||
185 !grpc_set_socket_reuse_addr(fd, 1)))) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800186 gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
187 strerror(errno));
188 goto error;
189 }
190
nnoble0c475f02014-12-05 15:37:39 -0800191 if (bind(fd, addr, addr_len) < 0) {
192 char *addr_str;
193 grpc_sockaddr_to_string(&addr_str, addr, 0);
194 gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
195 gpr_free(addr_str);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800196 goto error;
197 }
198
199 if (listen(fd, get_max_accept_queue_size()) < 0) {
200 gpr_log(GPR_ERROR, "listen: %s", strerror(errno));
201 goto error;
202 }
203
ctiller570d1f42015-01-12 16:29:52 -0800204 sockname_len = sizeof(sockname_temp);
205 if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
206 goto error;
207 }
208
209 return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800210
211error:
212 if (fd >= 0) {
213 close(fd);
214 }
ctiller570d1f42015-01-12 16:29:52 -0800215 return -1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800216}
217
218/* event manager callback when reads are ready */
ctiller58393c22015-01-07 14:03:30 -0800219static void on_read(void *arg, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800220 server_port *sp = arg;
221
ctiller58393c22015-01-07 14:03:30 -0800222 if (!success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800223 goto error;
224 }
225
226 /* loop until accept4 returns EAGAIN, and then re-arm notification */
227 for (;;) {
228 struct sockaddr_storage addr;
229 socklen_t addrlen = sizeof(addr);
nnoble0c475f02014-12-05 15:37:39 -0800230 /* Note: If we ever decide to return this address to the user, remember to
231 strip off the ::ffff:0.0.0.0/96 prefix first. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800232 int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
233 if (fd < 0) {
234 switch (errno) {
235 case EINTR:
236 continue;
237 case EAGAIN:
ctiller58393c22015-01-07 14:03:30 -0800238 grpc_fd_notify_on_read(sp->emfd, on_read, sp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800239 return;
240 default:
241 gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
242 goto error;
243 }
244 }
245
ctiller18b49ab2014-12-09 14:39:16 -0800246 sp->server->cb(
247 sp->server->cb_arg,
248 grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800249 }
250
251 abort();
252
253error:
254 gpr_mu_lock(&sp->server->mu);
255 if (0 == --sp->server->active_ports) {
256 gpr_cv_broadcast(&sp->server->cv);
257 }
258 gpr_mu_unlock(&sp->server->mu);
259}
260
nnoble0c475f02014-12-05 15:37:39 -0800261static int add_socket_to_server(grpc_tcp_server *s, int fd,
262 const struct sockaddr *addr, int addr_len) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800263 server_port *sp;
ctiller570d1f42015-01-12 16:29:52 -0800264 int port;
nnoble0c475f02014-12-05 15:37:39 -0800265
ctiller570d1f42015-01-12 16:29:52 -0800266 port = prepare_socket(fd, addr, addr_len);
267 if (port >= 0) {
268 gpr_mu_lock(&s->mu);
269 GPR_ASSERT(!s->cb && "must add ports before starting server");
270 /* append it to the list under a lock */
271 if (s->nports == s->port_capacity) {
272 s->port_capacity *= 2;
Yang Gao5fd0d292015-01-26 00:19:48 -0800273 s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
ctiller570d1f42015-01-12 16:29:52 -0800274 }
275 sp = &s->ports[s->nports++];
276 sp->server = s;
277 sp->fd = fd;
278 sp->emfd = grpc_fd_create(fd);
Craig Tiller772c97b2015-02-17 08:07:34 -0800279 memcpy(sp->addr.untyped, addr, addr_len);
Craig Tillerae7fe922015-02-13 23:16:32 -0800280 sp->addr_len = addr_len;
ctiller570d1f42015-01-12 16:29:52 -0800281 GPR_ASSERT(sp->emfd);
282 gpr_mu_unlock(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800283 }
284
ctiller570d1f42015-01-12 16:29:52 -0800285 return port;
nnoble0c475f02014-12-05 15:37:39 -0800286}
287
Craig Tillera172ad72015-01-21 15:51:47 -0800288int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
nnoble0c475f02014-12-05 15:37:39 -0800289 int addr_len) {
ctiller570d1f42015-01-12 16:29:52 -0800290 int allocated_port1 = -1;
291 int allocated_port2 = -1;
Nicolas "Pixel" Noble213ed912015-01-30 02:11:35 +0100292 unsigned i;
nnoble0c475f02014-12-05 15:37:39 -0800293 int fd;
294 grpc_dualstack_mode dsmode;
295 struct sockaddr_in6 addr6_v4mapped;
296 struct sockaddr_in wild4;
297 struct sockaddr_in6 wild6;
298 struct sockaddr_in addr4_copy;
ctiller570d1f42015-01-12 16:29:52 -0800299 struct sockaddr *allocated_addr = NULL;
300 struct sockaddr_storage sockname_temp;
301 socklen_t sockname_len;
nnoble0c475f02014-12-05 15:37:39 -0800302 int port;
303
ctiller570d1f42015-01-12 16:29:52 -0800304 /* Check if this is a wildcard port, and if so, try to keep the port the same
305 as some previously created listener. */
306 if (grpc_sockaddr_get_port(addr) == 0) {
307 for (i = 0; i < s->nports; i++) {
308 sockname_len = sizeof(sockname_temp);
309 if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp,
310 &sockname_len)) {
311 port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
312 if (port > 0) {
313 allocated_addr = malloc(addr_len);
314 memcpy(allocated_addr, addr, addr_len);
315 grpc_sockaddr_set_port(allocated_addr, port);
316 addr = allocated_addr;
317 break;
318 }
319 }
320 }
321 }
322
nnoble0c475f02014-12-05 15:37:39 -0800323 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
324 addr = (const struct sockaddr *)&addr6_v4mapped;
325 addr_len = sizeof(addr6_v4mapped);
326 }
327
328 /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
329 if (grpc_sockaddr_is_wildcard(addr, &port)) {
330 grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
331
332 /* Try listening on IPv6 first. */
333 addr = (struct sockaddr *)&wild6;
334 addr_len = sizeof(wild6);
335 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
ctiller570d1f42015-01-12 16:29:52 -0800336 allocated_port1 = add_socket_to_server(s, fd, addr, addr_len);
nnoble0c475f02014-12-05 15:37:39 -0800337 if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
ctiller570d1f42015-01-12 16:29:52 -0800338 goto done;
nnoble0c475f02014-12-05 15:37:39 -0800339 }
340
341 /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
ctiller570d1f42015-01-12 16:29:52 -0800342 if (port == 0 && allocated_port1 > 0) {
343 grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1);
344 }
nnoble0c475f02014-12-05 15:37:39 -0800345 addr = (struct sockaddr *)&wild4;
346 addr_len = sizeof(wild4);
347 }
348
349 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
350 if (fd < 0) {
351 gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
352 }
353 if (dsmode == GRPC_DSMODE_IPV4 &&
354 grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
355 addr = (struct sockaddr *)&addr4_copy;
356 addr_len = sizeof(addr4_copy);
357 }
ctiller570d1f42015-01-12 16:29:52 -0800358 allocated_port2 = add_socket_to_server(s, fd, addr, addr_len);
359
360done:
361 gpr_free(allocated_addr);
362 return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
nnoble0c475f02014-12-05 15:37:39 -0800363}
364
Nicolas "Pixel" Noble213ed912015-01-30 02:11:35 +0100365int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index) {
366 return (index < s->nports) ? s->ports[index].fd : -1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800367}
368
ctiller58393c22015-01-07 14:03:30 -0800369void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset *pollset,
370 grpc_tcp_server_cb cb, void *cb_arg) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800371 size_t i;
372 GPR_ASSERT(cb);
373 gpr_mu_lock(&s->mu);
374 GPR_ASSERT(!s->cb);
375 GPR_ASSERT(s->active_ports == 0);
376 s->cb = cb;
377 s->cb_arg = cb_arg;
378 for (i = 0; i < s->nports; i++) {
ctiller58393c22015-01-07 14:03:30 -0800379 if (pollset) {
380 grpc_pollset_add_fd(pollset, s->ports[i].emfd);
381 }
382 grpc_fd_notify_on_read(s->ports[i].emfd, on_read, &s->ports[i]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800383 s->active_ports++;
384 }
385 gpr_mu_unlock(&s->mu);
386}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800387
388#endif