blob: f1e5a6a8cd2ed72e7691e4ac24f8fb30b015ff2c [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
Craig Tiller0c0b60c2015-01-21 15:49:28 -080034#include <grpc/support/port_platform.h>
35
Craig Tillera172ad72015-01-21 15:51:47 -080036#ifdef GPR_POSIX_SOCKET
Craig Tiller0c0b60c2015-01-21 15:49:28 -080037
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080038#define _GNU_SOURCE
ctiller18b49ab2014-12-09 14:39:16 -080039#include "src/core/iomgr/tcp_server.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080040
41#include <limits.h>
42#include <fcntl.h>
43#include <netinet/in.h>
44#include <netinet/tcp.h>
45#include <stdio.h>
46#include <sys/types.h>
47#include <sys/socket.h>
48#include <unistd.h>
49#include <string.h>
50#include <errno.h>
51
ctiller58393c22015-01-07 14:03:30 -080052#include "src/core/iomgr/pollset_posix.h"
ctiller18b49ab2014-12-09 14:39:16 -080053#include "src/core/iomgr/sockaddr_utils.h"
54#include "src/core/iomgr/socket_utils_posix.h"
55#include "src/core/iomgr/tcp_posix.h"
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080056#include <grpc/support/alloc.h>
57#include <grpc/support/log.h>
58#include <grpc/support/sync.h>
59#include <grpc/support/time.h>
60
61#define INIT_PORT_CAP 2
62#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
63
64static gpr_once s_init_max_accept_queue_size;
65static int s_max_accept_queue_size;
66
67/* one listening port */
68typedef struct {
69 int fd;
ctiller18b49ab2014-12-09 14:39:16 -080070 grpc_fd *emfd;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080071 grpc_tcp_server *server;
72} server_port;
73
74/* the overall server */
75struct grpc_tcp_server {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080076 grpc_tcp_server_cb cb;
77 void *cb_arg;
78
79 gpr_mu mu;
80 gpr_cv cv;
81
82 /* active port count: how many ports are actually still listening */
83 int active_ports;
84
85 /* all listening ports */
86 server_port *ports;
87 size_t nports;
88 size_t port_capacity;
89};
90
Craig Tiller32946d32015-01-15 11:37:30 -080091grpc_tcp_server *grpc_tcp_server_create(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080092 grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
93 gpr_mu_init(&s->mu);
94 gpr_cv_init(&s->cv);
95 s->active_ports = 0;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -080096 s->cb = NULL;
97 s->cb_arg = NULL;
98 s->ports = gpr_malloc(sizeof(server_port) * INIT_PORT_CAP);
99 s->nports = 0;
100 s->port_capacity = INIT_PORT_CAP;
101 return s;
102}
103
104void grpc_tcp_server_destroy(grpc_tcp_server *s) {
105 size_t i;
106 gpr_mu_lock(&s->mu);
107 /* shutdown all fd's */
108 for (i = 0; i < s->nports; i++) {
ctiller18b49ab2014-12-09 14:39:16 -0800109 grpc_fd_shutdown(s->ports[i].emfd);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800110 }
111 /* wait while that happens */
112 while (s->active_ports) {
113 gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future);
114 }
115 gpr_mu_unlock(&s->mu);
116
117 /* delete ALL the things */
118 for (i = 0; i < s->nports; i++) {
119 server_port *sp = &s->ports[i];
ctiller58393c22015-01-07 14:03:30 -0800120 grpc_fd_orphan(sp->emfd, NULL, NULL);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800121 }
122 gpr_free(s->ports);
123 gpr_free(s);
124}
125
126/* get max listen queue size on linux */
Craig Tiller32946d32015-01-15 11:37:30 -0800127static void init_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800128 int n = SOMAXCONN;
129 char buf[64];
130 FILE *fp = fopen("/proc/sys/net/core/somaxconn", "r");
131 if (fp == NULL) {
132 /* 2.4 kernel. */
133 s_max_accept_queue_size = SOMAXCONN;
134 return;
135 }
136 if (fgets(buf, sizeof buf, fp)) {
137 char *end;
138 long i = strtol(buf, &end, 10);
139 if (i > 0 && i <= INT_MAX && end && *end == 0) {
140 n = i;
141 }
142 }
143 fclose(fp);
144 s_max_accept_queue_size = n;
145
146 if (s_max_accept_queue_size < MIN_SAFE_ACCEPT_QUEUE_SIZE) {
147 gpr_log(GPR_INFO,
148 "Suspiciously small accept queue (%d) will probably lead to "
149 "connection drops",
150 s_max_accept_queue_size);
151 }
152}
153
Craig Tiller32946d32015-01-15 11:37:30 -0800154static int get_max_accept_queue_size(void) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800155 gpr_once_init(&s_init_max_accept_queue_size, init_max_accept_queue_size);
156 return s_max_accept_queue_size;
157}
158
nnoble0c475f02014-12-05 15:37:39 -0800159/* Prepare a recently-created socket for listening. */
160static int prepare_socket(int fd, const struct sockaddr *addr, int addr_len) {
ctiller570d1f42015-01-12 16:29:52 -0800161 struct sockaddr_storage sockname_temp;
162 socklen_t sockname_len;
163
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800164 if (fd < 0) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800165 goto error;
166 }
167
168 if (!grpc_set_socket_nonblocking(fd, 1) || !grpc_set_socket_cloexec(fd, 1) ||
169 !grpc_set_socket_low_latency(fd, 1) ||
170 !grpc_set_socket_reuse_addr(fd, 1)) {
171 gpr_log(GPR_ERROR, "Unable to configure socket %d: %s", fd,
172 strerror(errno));
173 goto error;
174 }
175
nnoble0c475f02014-12-05 15:37:39 -0800176 if (bind(fd, addr, addr_len) < 0) {
177 char *addr_str;
178 grpc_sockaddr_to_string(&addr_str, addr, 0);
179 gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, strerror(errno));
180 gpr_free(addr_str);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800181 goto error;
182 }
183
184 if (listen(fd, get_max_accept_queue_size()) < 0) {
185 gpr_log(GPR_ERROR, "listen: %s", strerror(errno));
186 goto error;
187 }
188
ctiller570d1f42015-01-12 16:29:52 -0800189 sockname_len = sizeof(sockname_temp);
190 if (getsockname(fd, (struct sockaddr *)&sockname_temp, &sockname_len) < 0) {
191 goto error;
192 }
193
194 return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800195
196error:
197 if (fd >= 0) {
198 close(fd);
199 }
ctiller570d1f42015-01-12 16:29:52 -0800200 return -1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800201}
202
203/* event manager callback when reads are ready */
ctiller58393c22015-01-07 14:03:30 -0800204static void on_read(void *arg, int success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800205 server_port *sp = arg;
206
ctiller58393c22015-01-07 14:03:30 -0800207 if (!success) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800208 goto error;
209 }
210
211 /* loop until accept4 returns EAGAIN, and then re-arm notification */
212 for (;;) {
213 struct sockaddr_storage addr;
214 socklen_t addrlen = sizeof(addr);
nnoble0c475f02014-12-05 15:37:39 -0800215 /* Note: If we ever decide to return this address to the user, remember to
216 strip off the ::ffff:0.0.0.0/96 prefix first. */
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800217 int fd = grpc_accept4(sp->fd, (struct sockaddr *)&addr, &addrlen, 1, 1);
218 if (fd < 0) {
219 switch (errno) {
220 case EINTR:
221 continue;
222 case EAGAIN:
ctiller58393c22015-01-07 14:03:30 -0800223 grpc_fd_notify_on_read(sp->emfd, on_read, sp);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800224 return;
225 default:
226 gpr_log(GPR_ERROR, "Failed accept4: %s", strerror(errno));
227 goto error;
228 }
229 }
230
ctiller18b49ab2014-12-09 14:39:16 -0800231 sp->server->cb(
232 sp->server->cb_arg,
233 grpc_tcp_create(grpc_fd_create(fd), GRPC_TCP_DEFAULT_READ_SLICE_SIZE));
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800234 }
235
236 abort();
237
238error:
239 gpr_mu_lock(&sp->server->mu);
240 if (0 == --sp->server->active_ports) {
241 gpr_cv_broadcast(&sp->server->cv);
242 }
243 gpr_mu_unlock(&sp->server->mu);
244}
245
nnoble0c475f02014-12-05 15:37:39 -0800246static int add_socket_to_server(grpc_tcp_server *s, int fd,
247 const struct sockaddr *addr, int addr_len) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800248 server_port *sp;
ctiller570d1f42015-01-12 16:29:52 -0800249 int port;
nnoble0c475f02014-12-05 15:37:39 -0800250
ctiller570d1f42015-01-12 16:29:52 -0800251 port = prepare_socket(fd, addr, addr_len);
252 if (port >= 0) {
253 gpr_mu_lock(&s->mu);
254 GPR_ASSERT(!s->cb && "must add ports before starting server");
255 /* append it to the list under a lock */
256 if (s->nports == s->port_capacity) {
257 s->port_capacity *= 2;
258 s->ports =
259 gpr_realloc(s->ports, sizeof(server_port *) * s->port_capacity);
260 }
261 sp = &s->ports[s->nports++];
262 sp->server = s;
263 sp->fd = fd;
264 sp->emfd = grpc_fd_create(fd);
265 GPR_ASSERT(sp->emfd);
266 gpr_mu_unlock(&s->mu);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800267 }
268
ctiller570d1f42015-01-12 16:29:52 -0800269 return port;
nnoble0c475f02014-12-05 15:37:39 -0800270}
271
Craig Tillera172ad72015-01-21 15:51:47 -0800272int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
nnoble0c475f02014-12-05 15:37:39 -0800273 int addr_len) {
ctiller570d1f42015-01-12 16:29:52 -0800274 int allocated_port1 = -1;
275 int allocated_port2 = -1;
276 int i;
nnoble0c475f02014-12-05 15:37:39 -0800277 int fd;
278 grpc_dualstack_mode dsmode;
279 struct sockaddr_in6 addr6_v4mapped;
280 struct sockaddr_in wild4;
281 struct sockaddr_in6 wild6;
282 struct sockaddr_in addr4_copy;
ctiller570d1f42015-01-12 16:29:52 -0800283 struct sockaddr *allocated_addr = NULL;
284 struct sockaddr_storage sockname_temp;
285 socklen_t sockname_len;
nnoble0c475f02014-12-05 15:37:39 -0800286 int port;
287
ctiller570d1f42015-01-12 16:29:52 -0800288 /* Check if this is a wildcard port, and if so, try to keep the port the same
289 as some previously created listener. */
290 if (grpc_sockaddr_get_port(addr) == 0) {
291 for (i = 0; i < s->nports; i++) {
292 sockname_len = sizeof(sockname_temp);
293 if (0 == getsockname(s->ports[i].fd, (struct sockaddr *)&sockname_temp,
294 &sockname_len)) {
295 port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
296 if (port > 0) {
297 allocated_addr = malloc(addr_len);
298 memcpy(allocated_addr, addr, addr_len);
299 grpc_sockaddr_set_port(allocated_addr, port);
300 addr = allocated_addr;
301 break;
302 }
303 }
304 }
305 }
306
nnoble0c475f02014-12-05 15:37:39 -0800307 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
308 addr = (const struct sockaddr *)&addr6_v4mapped;
309 addr_len = sizeof(addr6_v4mapped);
310 }
311
312 /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
313 if (grpc_sockaddr_is_wildcard(addr, &port)) {
314 grpc_sockaddr_make_wildcards(port, &wild4, &wild6);
315
316 /* Try listening on IPv6 first. */
317 addr = (struct sockaddr *)&wild6;
318 addr_len = sizeof(wild6);
319 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
ctiller570d1f42015-01-12 16:29:52 -0800320 allocated_port1 = add_socket_to_server(s, fd, addr, addr_len);
nnoble0c475f02014-12-05 15:37:39 -0800321 if (fd >= 0 && dsmode == GRPC_DSMODE_DUALSTACK) {
ctiller570d1f42015-01-12 16:29:52 -0800322 goto done;
nnoble0c475f02014-12-05 15:37:39 -0800323 }
324
325 /* If we didn't get a dualstack socket, also listen on 0.0.0.0. */
ctiller570d1f42015-01-12 16:29:52 -0800326 if (port == 0 && allocated_port1 > 0) {
327 grpc_sockaddr_set_port((struct sockaddr *)&wild4, allocated_port1);
328 }
nnoble0c475f02014-12-05 15:37:39 -0800329 addr = (struct sockaddr *)&wild4;
330 addr_len = sizeof(wild4);
331 }
332
333 fd = grpc_create_dualstack_socket(addr, SOCK_STREAM, 0, &dsmode);
334 if (fd < 0) {
335 gpr_log(GPR_ERROR, "Unable to create socket: %s", strerror(errno));
336 }
337 if (dsmode == GRPC_DSMODE_IPV4 &&
338 grpc_sockaddr_is_v4mapped(addr, &addr4_copy)) {
339 addr = (struct sockaddr *)&addr4_copy;
340 addr_len = sizeof(addr4_copy);
341 }
ctiller570d1f42015-01-12 16:29:52 -0800342 allocated_port2 = add_socket_to_server(s, fd, addr, addr_len);
343
344done:
345 gpr_free(allocated_addr);
346 return allocated_port1 >= 0 ? allocated_port1 : allocated_port2;
nnoble0c475f02014-12-05 15:37:39 -0800347}
348
349int grpc_tcp_server_get_fd(grpc_tcp_server *s, int index) {
350 return (0 <= index && index < s->nports) ? s->ports[index].fd : -1;
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800351}
352
ctiller58393c22015-01-07 14:03:30 -0800353void grpc_tcp_server_start(grpc_tcp_server *s, grpc_pollset *pollset,
354 grpc_tcp_server_cb cb, void *cb_arg) {
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800355 size_t i;
356 GPR_ASSERT(cb);
357 gpr_mu_lock(&s->mu);
358 GPR_ASSERT(!s->cb);
359 GPR_ASSERT(s->active_ports == 0);
360 s->cb = cb;
361 s->cb_arg = cb_arg;
362 for (i = 0; i < s->nports; i++) {
ctiller58393c22015-01-07 14:03:30 -0800363 if (pollset) {
364 grpc_pollset_add_fd(pollset, s->ports[i].emfd);
365 }
366 grpc_fd_notify_on_read(s->ports[i].emfd, on_read, &s->ports[i]);
Nicolas Nobleb7ebd3b2014-11-26 16:33:03 -0800367 s->active_ports++;
368 }
369 gpr_mu_unlock(&s->mu);
370}
Craig Tiller0c0b60c2015-01-21 15:49:28 -0800371
372#endif