blob: b69dbd923b58897d944e2f45ad0b435679f6bf0c [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 Tillerae7fe922015-02-13 23:16:32 -080078 gpr_uint8 addr[GRPC_MAX_SOCKADDR_SIZE];
79 int addr_len;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080080} server_port;
81
82/* the overall server */
83struct grpc_tcp_server {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080084 grpc_tcp_server_cb cb;
85 void *cb_arg;
86
87 gpr_mu mu;
88 gpr_cv cv;
89
90 /* active port count: how many ports are actually still listening */
91 int active_ports;
92
93 /* all listening ports */
94 server_port *ports;
95 size_t nports;
96 size_t port_capacity;
97};
98
Craig Tiller32946d32015-01-15 11:37:30 -080099grpc_tcp_server *grpc_tcp_server_create(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800100 grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
101 gpr_mu_init(&s->mu);
102 gpr_cv_init(&s->cv);
103 s->active_ports = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800104 s->cb = NULL;
105 s->cb_arg = NULL;
106 s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
107 s->nports = 0;
108 s->port_capacity = INIT_PORT_CAP;
109 return s;
110}
111
112void grpc_tcp_server_destroy(grpc_tcp_server *s) {
113 size_t i;
114 gpr_mu_lock(&s->mu);
115 /* shutdown all fd's */
116 for (i = 0; i < s->nports; i++) {
ctiller18b49ab2014-12-09 14:39:16 -0800117 grpc_fd_shutdown(s->ports[i].emfd);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800118 }
119 /* wait while that happens */
120 while (s->active_ports) {
121 gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
122 }
123 gpr_mu_unlock(&s->mu);
124
125 /* delete ALL the things */
126 for (i = 0; i < s->nports; i++) {
127 server_port *sp = &s->ports[i];
Craig Tillerae7fe922015-02-13 23:16:32 -0800128 if (((struct sockaddr *)sp->addr)->sa_family == AF_UNIX) {
129 struct sockaddr_un *un = (struct sockaddr_un *)sp->addr;
130 unlink(un->sun_path);
131 }
ctiller58393c22015-01-07 14:03:30 -0800132 grpc_fd_orphan(sp->emfd, NULL, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800133 }
134 gpr_free(s->ports);
135 gpr_free(s);
136}
137
138/* get max listen queue size on linux */
Craig Tiller32946d32015-01-15 11:37:30 -0800139static void init_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800140 int n = SOMAXCONN;
141 char buf[64];
142 FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
143 if (fp == NULL) {
144 /* 2.4 kernel. */
145 s_max_accept_queue_size = SOMAXCONN;
146 return;
147 }
148 if (fgets(buf, sizeof buf, fp)) {
149 char *end;
150 long i = strtol(buf, &end, 10);
151 if (i > 0 && i <= INT_MAX && end && *end == 0) {
152 n = i;
153 }
154 }
155 fclose(fp);
156 s_max_accept_queue_size = n;
157
158 if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
159 gpr_log(GPR_INFO,
160 "Suspiciously small accept queue (%d) will probably lead to "
161 "connection drops",
162 s_max_accept_queue_size);
163 }
164}
165
Craig Tiller32946d32015-01-15 11:37:30 -0800166static int get_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800167 gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
168 return s_max_accept_queue_size;
169}
170
nnoble0c475f02014-12-05 15:37:39 -0800171/* Prepare a recently-created socket for listening. */
172static int prepare_socket(int fd, const struct sockaddr *addr, int addr_len) {
ctiller570d1f42015-01-12 16:29:52 -0800173 struct sockaddr_storage sockname_temp;
174 socklen_t sockname_len;
175
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800176 if (fd < 0) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800177 goto error;
178 }
179
180 if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
Craig Tillerae7fe922015-02-13 23:16:32 -0800181 (addr->sa_family != AF_UNIX && (!grpc_set_socket_low_latency(fd, 1) || !grpc_set_socket_reuse_addr(fd, 1)))) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800182 gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
183 strerror(errno));
184 goto error;
185 }
186
nnoble0c475f02014-12-05 15:37:39 -0800187 if (bind(fd, addr, addr_len) < 0) {
188 char *addr_str;
189 grpc_sockaddr_to_string(&addr_str, addr, 0);
190 gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
191 gpr_free(addr_str);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800192 goto error;
193 }
194
195 if (listen(fd, get_max_accept_queue_size()) < 0) {
196 gpr_log(GPR_ERROR, "listen: %s", strerror(errno));
197 goto error;
198 }
199
ctiller570d1f42015-01-12 16:29:52 -0800200 sockname_len = sizeof(sockname_temp);
201 if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
202 goto error;
203 }
204
205 return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800206
207error:
208 if (fd >= 0) {
209 close(fd);
210 }
ctiller570d1f42015-01-12 16:29:52 -0800211 return -1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800212}
213
214/* event manager callback when reads are ready */
ctiller58393c22015-01-07 14:03:30 -0800215static void on_read(void *arg, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800216 server_port *sp = arg;
217
ctiller58393c22015-01-07 14:03:30 -0800218 if (!success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800219 goto error;
220 }
221
222 /* loop until accept4 returns EAGAIN, and then re-arm notification */
223 for (;;) {
224 struct sockaddr_storage addr;
225 socklen_t addrlen = sizeof(addr);
nnoble0c475f02014-12-05 15:37:39 -0800226 /* Note: If we ever decide to return this address to the user, remember to
227 strip off the ::ffff:0.0.0.0/96 prefix first. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800228 int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
229 if (fd < 0) {
230 switch (errno) {
231 case EINTR:
232 continue;
233 case EAGAIN:
ctiller58393c22015-01-07 14:03:30 -0800234 grpc_fd_notify_on_read(sp->emfd, on_read, sp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800235 return;
236 default:
237 gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
238 goto error;
239 }
240 }
241
ctiller18b49ab2014-12-09 14:39:16 -0800242 sp->server->cb(
243 sp->server->cb_arg,
244 grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800245 }
246
247 abort();
248
249error:
250 gpr_mu_lock(&sp->server->mu);
251 if (0 == --sp->server->active_ports) {
252 gpr_cv_broadcast(&sp->server->cv);
253 }
254 gpr_mu_unlock(&sp->server->mu);
255}
256
nnoble0c475f02014-12-05 15:37:39 -0800257static int add_socket_to_server(grpc_tcp_server *s, int fd,
258 const struct sockaddr *addr, int addr_len) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800259 server_port *sp;
ctiller570d1f42015-01-12 16:29:52 -0800260 int port;
nnoble0c475f02014-12-05 15:37:39 -0800261
ctiller570d1f42015-01-12 16:29:52 -0800262 port = prepare_socket(fd, addr, addr_len);
263 if (port >= 0) {
264 gpr_mu_lock(&s->mu);
265 GPR_ASSERT(!s->cb && "must add ports before starting server");
266 /* append it to the list under a lock */
267 if (s->nports == s->port_capacity) {
268 s->port_capacity *= 2;
Yang Gao5fd0d292015-01-26 00:19:48 -0800269 s->ports = gpr_realloc(s->ports, sizeof(server_port) * s->port_capacity);
ctiller570d1f42015-01-12 16:29:52 -0800270 }
271 sp = &s->ports[s->nports++];
272 sp->server = s;
273 sp->fd = fd;
274 sp->emfd = grpc_fd_create(fd);
Craig Tillerae7fe922015-02-13 23:16:32 -0800275 memcpy(sp->addr, addr, addr_len);
276 sp->addr_len = addr_len;
ctiller570d1f42015-01-12 16:29:52 -0800277 GPR_ASSERT(sp->emfd);
278 gpr_mu_unlock(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800279 }
280
ctiller570d1f42015-01-12 16:29:52 -0800281 return port;
nnoble0c475f02014-12-05 15:37:39 -0800282}
283
Craig Tillera172ad72015-01-21 15:51:47 -0800284int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
nnoble0c475f02014-12-05 15:37:39 -0800285 int addr_len) {
ctiller570d1f42015-01-12 16:29:52 -0800286 int allocated_port1 = -1;
287 int allocated_port2 = -1;
Nicolas "Pixel" Noble213ed912015-01-30 02:11:35 +0100288 unsigned i;
nnoble0c475f02014-12-05 15:37:39 -0800289 int fd;
290 grpc_dualstack_mode dsmode;
291 struct sockaddr_in6 addr6_v4mapped;
292 struct sockaddr_in wild4;
293 struct sockaddr_in6 wild6;
294 struct sockaddr_in addr4_copy;
ctiller570d1f42015-01-12 16:29:52 -0800295 struct sockaddr *allocated_addr = NULL;
296 struct sockaddr_storage sockname_temp;
297 socklen_t sockname_len;
nnoble0c475f02014-12-05 15:37:39 -0800298 int port;
299
ctiller570d1f42015-01-12 16:29:52 -0800300 /* Check if this is a wildcard port, and if so, try to keep the port the same
301 as some previously created listener. */
302 if (grpc_sockaddr_get_port(addr) == 0) {
303 for (i = 0; i < s->nports; i++) {
304 sockname_len = sizeof(sockname_temp);
305 if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp,
306 &sockname_len)) {
307 port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
308 if (port > 0) {
309 allocated_addr = malloc(addr_len);
310 memcpy(allocated_addr, addr, addr_len);
311 grpc_sockaddr_set_port(allocated_addr, port);
312 addr = allocated_addr;
313 break;
314 }
315 }
316 }
317 }
318
nnoble0c475f02014-12-05 15:37:39 -0800319 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
320 addr = (const struct sockaddr *)&addr6_v4mapped;
321 addr_len = sizeof(addr6_v4mapped);
322 }
323
324 /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
325 if (grpc_sockaddr_is_wildcard(addr, &port)) {
326 grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
327
328 /* Try listening on IPv6 first. */
329 addr = (struct sockaddr *)&wild6;
330 addr_len = sizeof(wild6);
331 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
ctiller570d1f42015-01-12 16:29:52 -0800332 allocated_port1 = add_socket_to_server(s, fd, addr, addr_len);
nnoble0c475f02014-12-05 15:37:39 -0800333 if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
ctiller570d1f42015-01-12 16:29:52 -0800334 goto done;
nnoble0c475f02014-12-05 15:37:39 -0800335 }
336
337 /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
ctiller570d1f42015-01-12 16:29:52 -0800338 if (port == 0 && allocated_port1 > 0) {
339 grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1);
340 }
nnoble0c475f02014-12-05 15:37:39 -0800341 addr = (struct sockaddr *)&wild4;
342 addr_len = sizeof(wild4);
343 }
344
345 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
346 if (fd < 0) {
347 gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
348 }
349 if (dsmode == GRPC_DSMODE_IPV4 &&
350 grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
351 addr = (struct sockaddr *)&addr4_copy;
352 addr_len = sizeof(addr4_copy);
353 }
ctiller570d1f42015-01-12 16:29:52 -0800354 allocated_port2 = add_socket_to_server(s, fd, addr, addr_len);
355
356done:
357 gpr_free(allocated_addr);
358 return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
nnoble0c475f02014-12-05 15:37:39 -0800359}
360
Nicolas "Pixel" Noble213ed912015-01-30 02:11:35 +0100361int grpc_tcp_server_get_fd(grpc_tcp_server *s, unsigned index) {
362 return (index < s->nports) ? s->ports[index].fd : -1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800363}
364
ctiller58393c22015-01-07 14:03:30 -0800365void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset *pollset,
366 grpc_tcp_server_cb cb, void *cb_arg) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800367 size_t i;
368 GPR_ASSERT(cb);
369 gpr_mu_lock(&s->mu);
370 GPR_ASSERT(!s->cb);
371 GPR_ASSERT(s->active_ports == 0);
372 s->cb = cb;
373 s->cb_arg = cb_arg;
374 for (i = 0; i < s->nports; i++) {
ctiller58393c22015-01-07 14:03:30 -0800375 if (pollset) {
376 grpc_pollset_add_fd(pollset, s->ports[i].emfd);
377 }
378 grpc_fd_notify_on_read(s->ports[i].emfd, on_read, &s->ports[i]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800379 s->active_ports++;
380 }
381 gpr_mu_unlock(&s->mu);
382}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800383
384#endif