blob: a4abc5b9743a0f103df7bbd50e41ac2d1493b4d1 [file] [log] [blame]
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +01001/*
2 *
Dan Born725ee282016-01-13 13:14:56 -08003 * Copyright 2015-2016, Google Inc.
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +01004 * 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
34#include <grpc/support/port_platform.h>
35
36#ifdef GPR_WINSOCK_SOCKET
37
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080038#include <io.h>
39
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010040#include "src/core/iomgr/sockaddr_utils.h"
41
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010042#include <grpc/support/alloc.h>
43#include <grpc/support/log.h>
44#include <grpc/support/log_win32.h>
Masood Malekghassemi701af602015-06-03 15:01:17 -070045#include <grpc/support/string_util.h>
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010046#include <grpc/support/sync.h>
47#include <grpc/support/time.h>
48
Nicolas Nobled72ba6a2015-02-09 16:30:35 -080049#include "src/core/iomgr/iocp_windows.h"
50#include "src/core/iomgr/pollset_windows.h"
51#include "src/core/iomgr/socket_windows.h"
52#include "src/core/iomgr/tcp_server.h"
53#include "src/core/iomgr/tcp_windows.h"
54
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010055#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
56
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010057/* one listening port */
Dan Born5d81d152016-01-12 20:29:29 -080058typedef struct grpc_tcp_listener grpc_tcp_listener;
Nicolas Noble8f714622015-11-19 11:16:54 -080059struct grpc_tcp_listener {
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -070060 /* This seemingly magic number comes from AcceptEx's documentation. each
61 address buffer needs to have at least 16 more bytes at their end. */
Craig Tiller7536af02015-12-22 13:49:30 -080062 uint8_t addresses[(sizeof(struct sockaddr_in6) + 16) * 2];
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -070063 /* This will hold the socket for the next accept. */
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010064 SOCKET new_socket;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080065 /* The listener winsocket. */
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010066 grpc_winsocket *socket;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080067 /* The actual TCP port number. */
68 int port;
Dan Bornfa6b6062016-01-08 21:01:59 -080069 unsigned port_index;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010070 grpc_tcp_server *server;
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -070071 /* The cached AcceptEx for that port. */
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010072 LPFN_ACCEPTEX AcceptEx;
Nicolas "Pixel" Noble404fc6a2015-05-02 02:34:39 -070073 int shutting_down;
Craig Tiller82f9bd82015-09-23 09:31:51 -070074 /* closure for socket notification of accept being ready */
75 grpc_closure on_accept;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080076 /* linked list */
Nicolas Noble8f714622015-11-19 11:16:54 -080077 struct grpc_tcp_listener *next;
78};
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010079
80/* the overall server */
Craig Tillera82950e2015-09-22 12:33:20 -070081struct grpc_tcp_server {
Dan Bornfa6b6062016-01-08 21:01:59 -080082 gpr_refcount refs;
Robbie Shade3cd2d182015-08-28 14:30:35 -040083 /* Called whenever accept() succeeds on a server port. */
84 grpc_tcp_server_cb on_accept_cb;
85 void *on_accept_cb_arg;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010086
87 gpr_mu mu;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010088
89 /* active port count: how many ports are actually still listening */
90 int active_ports;
91
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080092 /* linked list of server ports */
Nicolas Noble8f714622015-11-19 11:16:54 -080093 grpc_tcp_listener *head;
Dan Bornfa6b6062016-01-08 21:01:59 -080094 grpc_tcp_listener *tail;
Craig Tiller063560e2015-09-01 08:44:42 -070095
Dan Born9c12bc22016-01-13 16:52:20 -080096 /* List of closures passed to shutdown_starting_add(). */
97 grpc_closure_list shutdown_starting;
98
Craig Tiller063560e2015-09-01 08:44:42 -070099 /* shutdown callback */
Craig Tiller82f9bd82015-09-23 09:31:51 -0700100 grpc_closure *shutdown_complete;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100101};
102
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700103/* Public function. Allocates the proper data structures to hold a
104 grpc_tcp_server. */
Dan Bornfa6b6062016-01-08 21:01:59 -0800105grpc_tcp_server *grpc_tcp_server_create(grpc_closure *shutdown_complete) {
Craig Tillera82950e2015-09-22 12:33:20 -0700106 grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
Dan Bornfa6b6062016-01-08 21:01:59 -0800107 gpr_ref_init(&s->refs, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700108 gpr_mu_init(&s->mu);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100109 s->active_ports = 0;
Robbie Shade3cd2d182015-08-28 14:30:35 -0400110 s->on_accept_cb = NULL;
111 s->on_accept_cb_arg = NULL;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800112 s->head = NULL;
Dan Bornfa6b6062016-01-08 21:01:59 -0800113 s->tail = NULL;
Dan Born9c12bc22016-01-13 16:52:20 -0800114 s->shutdown_starting.head = NULL;
115 s->shutdown_starting.tail = NULL;
Dan Bornfa6b6062016-01-08 21:01:59 -0800116 s->shutdown_complete = shutdown_complete;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100117 return s;
118}
119
Craig Tiller82f9bd82015-09-23 09:31:51 -0700120static void finish_shutdown(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800121 if (s->shutdown_complete != NULL) {
Craig Tillereced8ae2016-01-28 14:13:20 -0800122 grpc_exec_ctx_enqueue(exec_ctx, s->shutdown_complete, true, NULL);
Dan Bornfa6b6062016-01-08 21:01:59 -0800123 }
Craig Tiller5100ea02015-09-01 12:23:28 -0700124
125 /* Now that the accepts have been aborted, we can destroy the sockets.
Craig Tiller45724b32015-09-22 10:42:19 -0700126 The IOCP won't get notified on these, so we can flag them as already
127 closed by the system. */
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800128 while (s->head) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800129 grpc_tcp_listener *sp = s->head;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800130 s->head = sp->next;
131 sp->next = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700132 grpc_winsocket_destroy(sp->socket);
Dan Born50ef3042016-01-13 13:35:33 -0800133 gpr_free(sp);
Craig Tillera82950e2015-09-22 12:33:20 -0700134 }
Craig Tillera82950e2015-09-22 12:33:20 -0700135 gpr_free(s);
Craig Tiller5100ea02015-09-01 12:23:28 -0700136}
137
Dan Bornfa6b6062016-01-08 21:01:59 -0800138grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
139 gpr_ref(&s->refs);
140 return s;
141}
142
Dan Born9c12bc22016-01-13 16:52:20 -0800143void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
144 grpc_closure *shutdown_starting) {
145 gpr_mu_lock(&s->mu);
146 grpc_closure_list_add(&s->shutdown_starting, shutdown_starting, 1);
147 gpr_mu_unlock(&s->mu);
148}
149
Dan Born5d81d152016-01-12 20:29:29 -0800150static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Craig Tiller063560e2015-09-01 08:44:42 -0700151 int immediately_done = 0;
Nicolas Noble8f714622015-11-19 11:16:54 -0800152 grpc_tcp_listener *sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700153 gpr_mu_lock(&s->mu);
Craig Tiller063560e2015-09-01 08:44:42 -0700154
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700155 /* First, shutdown all fd's. This will queue abortion calls for all
Nicolas "Pixel" Noblee503cd52015-07-14 02:27:23 +0200156 of the pending accepts due to the normal operation mechanism. */
Craig Tillera82950e2015-09-22 12:33:20 -0700157 if (s->active_ports == 0) {
158 immediately_done = 1;
159 }
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800160 for (sp = s->head; sp; sp = sp->next) {
Craig Tillera82950e2015-09-22 12:33:20 -0700161 sp->shutting_down = 1;
162 grpc_winsocket_shutdown(sp->socket);
163 }
164 gpr_mu_unlock(&s->mu);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100165
Craig Tillera82950e2015-09-22 12:33:20 -0700166 if (immediately_done) {
Craig Tiller82f9bd82015-09-23 09:31:51 -0700167 finish_shutdown(exec_ctx, s);
Craig Tillera82950e2015-09-22 12:33:20 -0700168 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100169}
170
Dan Bornfa6b6062016-01-08 21:01:59 -0800171void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
172 if (gpr_unref(&s->refs)) {
Dan Born9c12bc22016-01-13 16:52:20 -0800173 /* Complete shutdown_starting work before destroying. */
174 grpc_exec_ctx local_exec_ctx = GRPC_EXEC_CTX_INIT;
175 gpr_mu_lock(&s->mu);
Craig Tillereced8ae2016-01-28 14:13:20 -0800176 grpc_exec_ctx_enqueue_list(&local_exec_ctx, &s->shutdown_starting, NULL);
Dan Born9c12bc22016-01-13 16:52:20 -0800177 gpr_mu_unlock(&s->mu);
Dan Bornfa6b6062016-01-08 21:01:59 -0800178 if (exec_ctx == NULL) {
Dan Born9c12bc22016-01-13 16:52:20 -0800179 grpc_exec_ctx_flush(&local_exec_ctx);
Dan Born5d81d152016-01-12 20:29:29 -0800180 tcp_server_destroy(&local_exec_ctx, s);
Dan Bornfa6b6062016-01-08 21:01:59 -0800181 grpc_exec_ctx_finish(&local_exec_ctx);
182 } else {
Dan Born9c12bc22016-01-13 16:52:20 -0800183 grpc_exec_ctx_finish(&local_exec_ctx);
Dan Born5d81d152016-01-12 20:29:29 -0800184 tcp_server_destroy(exec_ctx, s);
Dan Bornfa6b6062016-01-08 21:01:59 -0800185 }
186 }
187}
188
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700189/* Prepare (bind) a recently-created socket for listening. */
Craig Tillera82950e2015-09-22 12:33:20 -0700190static int prepare_socket(SOCKET sock, const struct sockaddr *addr,
Jan Tattermusch48e57fa2015-09-21 13:43:54 -0700191 size_t addr_len) {
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100192 struct sockaddr_storage sockname_temp;
193 socklen_t sockname_len;
194
Craig Tillera82950e2015-09-22 12:33:20 -0700195 if (sock == INVALID_SOCKET) goto error;
196
197 if (!grpc_tcp_prepare_socket(sock)) {
198 char *utf8_message = gpr_format_message(WSAGetLastError());
199 gpr_log(GPR_ERROR, "Unable to prepare socket: %s", utf8_message);
200 gpr_free(utf8_message);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100201 goto error;
Craig Tillera82950e2015-09-22 12:33:20 -0700202 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100203
Jan Tattermusch48e57fa2015-09-21 13:43:54 -0700204 if (bind(sock, addr, (int)addr_len) == SOCKET_ERROR) {
Craig Tillera82950e2015-09-22 12:33:20 -0700205 char *addr_str;
206 char *utf8_message = gpr_format_message(WSAGetLastError());
207 grpc_sockaddr_to_string(&addr_str, addr, 0);
208 gpr_log(GPR_ERROR, "bind addr=%s: %s", addr_str, utf8_message);
209 gpr_free(utf8_message);
210 gpr_free(addr_str);
211 goto error;
212 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100213
Craig Tillera82950e2015-09-22 12:33:20 -0700214 if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
215 char *utf8_message = gpr_format_message(WSAGetLastError());
216 gpr_log(GPR_ERROR, "listen: %s", utf8_message);
217 gpr_free(utf8_message);
218 goto error;
219 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100220
Craig Tillera82950e2015-09-22 12:33:20 -0700221 sockname_len = sizeof(sockname_temp);
222 if (getsockname(sock, (struct sockaddr *)&sockname_temp, &sockname_len) ==
223 SOCKET_ERROR) {
224 char *utf8_message = gpr_format_message(WSAGetLastError());
225 gpr_log(GPR_ERROR, "getsockname: %s", utf8_message);
226 gpr_free(utf8_message);
227 goto error;
228 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100229
Craig Tillera82950e2015-09-22 12:33:20 -0700230 return grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100231
232error:
Craig Tillera82950e2015-09-22 12:33:20 -0700233 if (sock != INVALID_SOCKET) closesocket(sock);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100234 return -1;
235}
236
Craig Tiller565b18b2015-09-23 10:09:42 -0700237static void decrement_active_ports_and_notify(grpc_exec_ctx *exec_ctx,
Nicolas Noble8f714622015-11-19 11:16:54 -0800238 grpc_tcp_listener *sp) {
Craig Tiller5100ea02015-09-01 12:23:28 -0700239 int notify = 0;
Jan Tattermusch2f25d982015-08-03 18:01:26 -0700240 sp->shutting_down = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700241 gpr_mu_lock(&sp->server->mu);
242 GPR_ASSERT(sp->server->active_ports > 0);
yang-g9aa4f1b2016-03-02 16:39:13 -0800243 if (0 == --sp->server->active_ports) {
Craig Tillera82950e2015-09-22 12:33:20 -0700244 notify = 1;
245 }
246 gpr_mu_unlock(&sp->server->mu);
247 if (notify) {
Craig Tiller82f9bd82015-09-23 09:31:51 -0700248 finish_shutdown(exec_ctx, sp->server);
Craig Tillera82950e2015-09-22 12:33:20 -0700249 }
Jan Tattermusch2f25d982015-08-03 18:01:26 -0700250}
251
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700252/* In order to do an async accept, we need to create a socket first which
253 will be the one assigned to the new incoming connection. */
Nicolas Noble8f714622015-11-19 11:16:54 -0800254static void start_accept(grpc_exec_ctx *exec_ctx, grpc_tcp_listener *port) {
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100255 SOCKET sock = INVALID_SOCKET;
256 char *message;
257 char *utf8_message;
258 BOOL success;
Craig Tillera82950e2015-09-22 12:33:20 -0700259 DWORD addrlen = sizeof(struct sockaddr_in6) + 16;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100260 DWORD bytes_received = 0;
261
Craig Tillera82950e2015-09-22 12:33:20 -0700262 sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
263 WSA_FLAG_OVERLAPPED);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100264
Craig Tillera82950e2015-09-22 12:33:20 -0700265 if (sock == INVALID_SOCKET) {
266 message = "Unable to create socket: %s";
267 goto failure;
268 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100269
Craig Tillera82950e2015-09-22 12:33:20 -0700270 if (!grpc_tcp_prepare_socket(sock)) {
271 message = "Unable to prepare socket: %s";
272 goto failure;
273 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100274
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700275 /* Start the "accept" asynchronously. */
Craig Tillera82950e2015-09-22 12:33:20 -0700276 success = port->AcceptEx(port->socket->socket, sock, port->addresses, 0,
277 addrlen, addrlen, &bytes_received,
278 &port->socket->read_info.overlapped);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100279
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700280 /* It is possible to get an accept immediately without delay. However, we
281 will still get an IOCP notification for it. So let's just ignore it. */
Craig Tillera82950e2015-09-22 12:33:20 -0700282 if (!success) {
283 int error = WSAGetLastError();
284 if (error != ERROR_IO_PENDING) {
285 message = "AcceptEx failed: %s";
286 goto failure;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100287 }
Craig Tillera82950e2015-09-22 12:33:20 -0700288 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100289
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700290 /* We're ready to do the accept. Calling grpc_socket_notify_on_read may
291 immediately process an accept that happened in the meantime. */
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100292 port->new_socket = sock;
Craig Tiller82f9bd82015-09-23 09:31:51 -0700293 grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100294 return;
295
296failure:
Craig Tillera82950e2015-09-22 12:33:20 -0700297 if (port->shutting_down) {
298 /* We are abandoning the listener port, take that into account to prevent
299 occasional hangs on shutdown. The hang happens when sp->shutting_down
300 change is not seen by on_accept and we proceed to trying new accept,
301 but we fail there because the listening port has been closed in the
302 meantime. */
Craig Tiller82f9bd82015-09-23 09:31:51 -0700303 decrement_active_ports_and_notify(exec_ctx, port);
Craig Tillera82950e2015-09-22 12:33:20 -0700304 return;
305 }
306 utf8_message = gpr_format_message(WSAGetLastError());
307 gpr_log(GPR_ERROR, message, utf8_message);
308 gpr_free(utf8_message);
309 if (sock != INVALID_SOCKET) closesocket(sock);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100310}
311
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700312/* Event manager callback when reads are ready. */
Craig Tillereced8ae2016-01-28 14:13:20 -0800313static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, bool from_iocp) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800314 grpc_tcp_listener *sp = arg;
Dan Born5d81d152016-01-12 20:29:29 -0800315 grpc_tcp_server_acceptor acceptor = {sp->server, sp->port_index, 0};
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100316 SOCKET sock = sp->new_socket;
317 grpc_winsocket_callback_info *info = &sp->socket->read_info;
318 grpc_endpoint *ep = NULL;
Craig Tiller81bcc4c2015-07-20 14:04:18 -0700319 struct sockaddr_storage peer_name;
320 char *peer_name_string;
321 char *fd_name;
Craig Tillera82950e2015-09-22 12:33:20 -0700322 int peer_name_len = sizeof(peer_name);
chai2010e55e1832015-07-14 13:24:48 +0800323 DWORD transfered_bytes;
324 DWORD flags;
325 BOOL wsa_success;
Jan Tattermusch3f7809d2015-07-24 13:20:40 -0700326 int err;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100327
Nicolas "Pixel" Noblee503cd52015-07-14 02:27:23 +0200328 /* The general mechanism for shutting down is to queue abortion calls. While
329 this is necessary in the read/write case, it's useless for the accept
Jan Tattermuscheab5c332015-07-29 11:49:31 -0700330 case. We only need to adjust the pending callback count */
Craig Tillera82950e2015-09-22 12:33:20 -0700331 if (!from_iocp) {
332 return;
333 }
Nicolas "Pixel" Noble404fc6a2015-05-02 02:34:39 -0700334
Nicolas "Pixel" Noblee503cd52015-07-14 02:27:23 +0200335 /* The IOCP notified us of a completed operation. Let's grab the results,
Craig Tiller45724b32015-09-22 10:42:19 -0700336 and act accordingly. */
chai2010e55e1832015-07-14 13:24:48 +0800337 transfered_bytes = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700338 wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
339 &transfered_bytes, FALSE, &flags);
340 if (!wsa_success) {
341 if (sp->shutting_down) {
342 /* During the shutdown case, we ARE expecting an error. So that's well,
343 and we can wake up the shutdown thread. */
Craig Tiller82f9bd82015-09-23 09:31:51 -0700344 decrement_active_ports_and_notify(exec_ctx, sp);
Craig Tillera82950e2015-09-22 12:33:20 -0700345 return;
346 } else {
347 char *utf8_message = gpr_format_message(WSAGetLastError());
348 gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
349 gpr_free(utf8_message);
350 closesocket(sock);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100351 }
Craig Tillera82950e2015-09-22 12:33:20 -0700352 } else {
353 if (!sp->shutting_down) {
354 peer_name_string = NULL;
355 err = setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
356 (char *)&sp->socket->socket, sizeof(sp->socket->socket));
357 if (err) {
358 char *utf8_message = gpr_format_message(WSAGetLastError());
359 gpr_log(GPR_ERROR, "setsockopt error: %s", utf8_message);
360 gpr_free(utf8_message);
361 }
362 err = getpeername(sock, (struct sockaddr *)&peer_name, &peer_name_len);
363 if (!err) {
364 peer_name_string = grpc_sockaddr_to_uri((struct sockaddr *)&peer_name);
365 } else {
366 char *utf8_message = gpr_format_message(WSAGetLastError());
367 gpr_log(GPR_ERROR, "getpeername error: %s", utf8_message);
368 gpr_free(utf8_message);
369 }
370 gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string);
371 ep = grpc_tcp_create(grpc_winsocket_create(sock, fd_name),
372 peer_name_string);
373 gpr_free(fd_name);
374 gpr_free(peer_name_string);
Craig Tillerfaf8f682015-10-06 09:12:34 -0700375 } else {
376 closesocket(sock);
Nicolas "Pixel" Noble0f981e92015-05-03 10:40:56 +0200377 }
Craig Tillera82950e2015-09-22 12:33:20 -0700378 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100379
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700380 /* The only time we should call our callback, is where we successfully
381 managed to accept a connection, and created an endpoint. */
Dan Borna78ca382016-01-14 13:02:09 -0800382 if (ep)
383 sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep,
384 &acceptor);
Nicolas "Pixel" Noble0f981e92015-05-03 10:40:56 +0200385 /* As we were notified from the IOCP of one and exactly one accept,
Nicolas "Pixel" Noblee503cd52015-07-14 02:27:23 +0200386 the former socked we created has now either been destroy or assigned
387 to the new connection. We need to create a new one for the next
388 connection. */
Craig Tiller82f9bd82015-09-23 09:31:51 -0700389 start_accept(exec_ctx, sp);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100390}
391
Nicolas Noble8f714622015-11-19 11:16:54 -0800392static grpc_tcp_listener *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
yang-g3ff97272015-11-20 17:01:57 -0800393 const struct sockaddr *addr,
Dan Bornfa6b6062016-01-08 21:01:59 -0800394 size_t addr_len,
395 unsigned port_index) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800396 grpc_tcp_listener *sp = NULL;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100397 int port;
398 int status;
399 GUID guid = WSAID_ACCEPTEX;
400 DWORD ioctl_num_bytes;
401 LPFN_ACCEPTEX AcceptEx;
402
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800403 if (sock == INVALID_SOCKET) return NULL;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100404
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700405 /* We need to grab the AcceptEx pointer for that port, as it may be
406 interface-dependent. We'll cache it to avoid doing that again. */
Craig Tillera82950e2015-09-22 12:33:20 -0700407 status =
408 WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
409 &AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100410
Craig Tillera82950e2015-09-22 12:33:20 -0700411 if (status != 0) {
412 char *utf8_message = gpr_format_message(WSAGetLastError());
413 gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
414 gpr_free(utf8_message);
415 closesocket(sock);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800416 return NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700417 }
Craig Tiller45724b32015-09-22 10:42:19 -0700418
Craig Tillera82950e2015-09-22 12:33:20 -0700419 port = prepare_socket(sock, addr, addr_len);
420 if (port >= 0) {
421 gpr_mu_lock(&s->mu);
422 GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
Nicolas Noble8f714622015-11-19 11:16:54 -0800423 sp = gpr_malloc(sizeof(grpc_tcp_listener));
Dan Bornfa6b6062016-01-08 21:01:59 -0800424 sp->next = NULL;
425 if (s->head == NULL) {
426 s->head = sp;
427 } else {
428 s->tail->next = sp;
429 }
430 s->tail = sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700431 sp->server = s;
432 sp->socket = grpc_winsocket_create(sock, "listener");
433 sp->shutting_down = 0;
434 sp->AcceptEx = AcceptEx;
435 sp->new_socket = INVALID_SOCKET;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800436 sp->port = port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800437 sp->port_index = port_index;
Craig Tiller258f8de2015-09-23 12:32:40 -0700438 grpc_closure_init(&sp->on_accept, on_accept, sp);
Craig Tillera82950e2015-09-22 12:33:20 -0700439 GPR_ASSERT(sp->socket);
440 gpr_mu_unlock(&s->mu);
441 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100442
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800443 return sp;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100444}
445
Dan Bornfa6b6062016-01-08 21:01:59 -0800446int grpc_tcp_server_add_port(grpc_tcp_server *s, const void *addr,
447 size_t addr_len) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800448 grpc_tcp_listener *sp;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100449 SOCKET sock;
450 struct sockaddr_in6 addr6_v4mapped;
451 struct sockaddr_in6 wildcard;
452 struct sockaddr *allocated_addr = NULL;
453 struct sockaddr_storage sockname_temp;
454 socklen_t sockname_len;
455 int port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800456 unsigned port_index = 0;
457 if (s->tail != NULL) {
458 port_index = s->tail->port_index + 1;
459 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100460
461 /* Check if this is a wildcard port, and if so, try to keep the port the same
462 as some previously created listener. */
Craig Tillera82950e2015-09-22 12:33:20 -0700463 if (grpc_sockaddr_get_port(addr) == 0) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800464 for (sp = s->head; sp; sp = sp->next) {
Craig Tillera82950e2015-09-22 12:33:20 -0700465 sockname_len = sizeof(sockname_temp);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800466 if (0 == getsockname(sp->socket->socket,
Craig Tillera82950e2015-09-22 12:33:20 -0700467 (struct sockaddr *)&sockname_temp, &sockname_len)) {
468 port = grpc_sockaddr_get_port((struct sockaddr *)&sockname_temp);
469 if (port > 0) {
470 allocated_addr = malloc(addr_len);
471 memcpy(allocated_addr, addr, addr_len);
472 grpc_sockaddr_set_port(allocated_addr, port);
473 addr = allocated_addr;
474 break;
475 }
476 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100477 }
Craig Tillera82950e2015-09-22 12:33:20 -0700478 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100479
Craig Tillera82950e2015-09-22 12:33:20 -0700480 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
481 addr = (const struct sockaddr *)&addr6_v4mapped;
482 addr_len = sizeof(addr6_v4mapped);
483 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100484
485 /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
Craig Tillera82950e2015-09-22 12:33:20 -0700486 if (grpc_sockaddr_is_wildcard(addr, &port)) {
487 grpc_sockaddr_make_wildcard6(port, &wildcard);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100488
Craig Tillera82950e2015-09-22 12:33:20 -0700489 addr = (struct sockaddr *)&wildcard;
490 addr_len = sizeof(wildcard);
491 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100492
Craig Tillera82950e2015-09-22 12:33:20 -0700493 sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
494 WSA_FLAG_OVERLAPPED);
495 if (sock == INVALID_SOCKET) {
496 char *utf8_message = gpr_format_message(WSAGetLastError());
497 gpr_log(GPR_ERROR, "unable to create socket: %s", utf8_message);
498 gpr_free(utf8_message);
499 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100500
Dan Bornfa6b6062016-01-08 21:01:59 -0800501 sp = add_socket_to_server(s, sock, addr, addr_len, port_index);
Craig Tillera82950e2015-09-22 12:33:20 -0700502 gpr_free(allocated_addr);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100503
Dan Bornfa6b6062016-01-08 21:01:59 -0800504 if (sp) {
505 return sp->port;
506 } else {
507 return -1;
508 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100509}
510
Dan Born50ef3042016-01-13 13:35:33 -0800511unsigned grpc_tcp_server_port_fd_count(grpc_tcp_server *s,
512 unsigned port_index) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800513 grpc_tcp_listener *sp;
Dan Bornfa6b6062016-01-08 21:01:59 -0800514 for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index)
yang-g3ff97272015-11-20 17:01:57 -0800515 ;
Dan Bornfa6b6062016-01-08 21:01:59 -0800516 if (sp) {
517 return 1;
518 } else {
519 return 0;
520 }
521}
522
Dan Born5d81d152016-01-12 20:29:29 -0800523int grpc_tcp_server_port_fd(grpc_tcp_server *s, unsigned port_index,
524 unsigned fd_index) {
Dan Bornfa6b6062016-01-08 21:01:59 -0800525 grpc_tcp_listener *sp;
526 if (fd_index != 0) {
527 /* Windows implementation has only one fd per port_index. */
528 return -1;
529 }
530 for (sp = s->head; sp && port_index != 0; sp = sp->next, --port_index)
531 ;
532 if (sp) {
Nicolas "Pixel" Noble742eac12016-01-26 22:41:19 +0100533 return _open_osfhandle((intptr_t)sp->socket->socket, 0);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800534 } else {
535 return -1;
536 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100537}
538
Craig Tiller565b18b2015-09-23 10:09:42 -0700539void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
540 grpc_pollset **pollset, size_t pollset_count,
Craig Tillera82950e2015-09-22 12:33:20 -0700541 grpc_tcp_server_cb on_accept_cb,
542 void *on_accept_cb_arg) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800543 grpc_tcp_listener *sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700544 GPR_ASSERT(on_accept_cb);
545 gpr_mu_lock(&s->mu);
546 GPR_ASSERT(!s->on_accept_cb);
547 GPR_ASSERT(s->active_ports == 0);
Robbie Shade3cd2d182015-08-28 14:30:35 -0400548 s->on_accept_cb = on_accept_cb;
549 s->on_accept_cb_arg = on_accept_cb_arg;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800550 for (sp = s->head; sp; sp = sp->next) {
551 start_accept(exec_ctx, sp);
Craig Tillera82950e2015-09-22 12:33:20 -0700552 s->active_ports++;
553 }
554 gpr_mu_unlock(&s->mu);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100555}
556
Craig Tillerc02c1d82015-04-07 16:21:55 -0700557#endif /* GPR_WINSOCK_SOCKET */