blob: bd4b9b2df11856bf966e6ea49e5b762b6c7b9a04 [file] [log] [blame]
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +01001/*
2 *
Craig Tiller6169d5f2016-03-31 07:46:18 -07003 * Copyright 2015, 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
murgatroid9954070892016-08-08 17:01:18 -070034#include "src/core/lib/iomgr/port.h"
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010035
murgatroid99623dd4f2016-08-08 17:31:27 -070036#ifdef GRPC_WINSOCK_SOCKET
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010037
Michael Lumish77c6cce2016-09-26 13:51:57 -070038#include "src/core/lib/iomgr/sockaddr.h"
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080039
Michael Lumish77c6cce2016-09-26 13:51:57 -070040#include <io.h>
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010041
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010042#include <grpc/support/alloc.h>
43#include <grpc/support/log.h>
Yuchen Zeng12dfdc32016-04-26 22:05:41 -070044#include <grpc/support/log_windows.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
Craig Tiller9533d042016-03-25 17:11:06 -070049#include "src/core/lib/iomgr/iocp_windows.h"
50#include "src/core/lib/iomgr/pollset_windows.h"
Michael Lumish77c6cce2016-09-26 13:51:57 -070051#include "src/core/lib/iomgr/resolve_address.h"
52#include "src/core/lib/iomgr/sockaddr_utils.h"
Craig Tiller9533d042016-03-25 17:11:06 -070053#include "src/core/lib/iomgr/socket_windows.h"
54#include "src/core/lib/iomgr/tcp_server.h"
55#include "src/core/lib/iomgr/tcp_windows.h"
Nicolas Nobled72ba6a2015-02-09 16:30:35 -080056
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010057#define MIN_SAFE_ACCEPT_QUEUE_SIZE 100
58
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010059/* one listening port */
Dan Born5d81d152016-01-12 20:29:29 -080060typedef struct grpc_tcp_listener grpc_tcp_listener;
Nicolas Noble8f714622015-11-19 11:16:54 -080061struct grpc_tcp_listener {
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -070062 /* This seemingly magic number comes from AcceptEx's documentation. each
63 address buffer needs to have at least 16 more bytes at their end. */
Craig Tiller7536af02015-12-22 13:49:30 -080064 uint8_t addresses[(sizeof(struct sockaddr_in6) + 16) * 2];
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -070065 /* This will hold the socket for the next accept. */
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010066 SOCKET new_socket;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080067 /* The listener winsocket. */
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010068 grpc_winsocket *socket;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080069 /* The actual TCP port number. */
70 int port;
Dan Bornfa6b6062016-01-08 21:01:59 -080071 unsigned port_index;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010072 grpc_tcp_server *server;
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -070073 /* The cached AcceptEx for that port. */
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010074 LPFN_ACCEPTEX AcceptEx;
Nicolas "Pixel" Noble404fc6a2015-05-02 02:34:39 -070075 int shutting_down;
Craig Tillercbafdd12016-11-29 13:54:00 -080076 int outstanding_calls;
Craig Tiller82f9bd82015-09-23 09:31:51 -070077 /* closure for socket notification of accept being ready */
78 grpc_closure on_accept;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080079 /* linked list */
Nicolas Noble8f714622015-11-19 11:16:54 -080080 struct grpc_tcp_listener *next;
81};
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010082
83/* the overall server */
Craig Tillera82950e2015-09-22 12:33:20 -070084struct grpc_tcp_server {
Dan Bornfa6b6062016-01-08 21:01:59 -080085 gpr_refcount refs;
Robbie Shade3cd2d182015-08-28 14:30:35 -040086 /* Called whenever accept() succeeds on a server port. */
87 grpc_tcp_server_cb on_accept_cb;
88 void *on_accept_cb_arg;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010089
90 gpr_mu mu;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +010091
92 /* active port count: how many ports are actually still listening */
93 int active_ports;
94
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -080095 /* linked list of server ports */
Nicolas Noble8f714622015-11-19 11:16:54 -080096 grpc_tcp_listener *head;
Dan Bornfa6b6062016-01-08 21:01:59 -080097 grpc_tcp_listener *tail;
Craig Tiller063560e2015-09-01 08:44:42 -070098
Dan Born9c12bc22016-01-13 16:52:20 -080099 /* List of closures passed to shutdown_starting_add(). */
100 grpc_closure_list shutdown_starting;
101
Craig Tiller063560e2015-09-01 08:44:42 -0700102 /* shutdown callback */
Craig Tiller82f9bd82015-09-23 09:31:51 -0700103 grpc_closure *shutdown_complete;
Craig Tiller290e9a72016-10-28 08:17:00 -0700104
105 grpc_resource_quota *resource_quota;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100106};
107
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700108/* Public function. Allocates the proper data structures to hold a
109 grpc_tcp_server. */
Craig Tillera5ea56b2016-10-28 08:19:02 -0700110grpc_error *grpc_tcp_server_create(grpc_exec_ctx *exec_ctx,
111 grpc_closure *shutdown_complete,
Craig Tillerb1878952016-06-20 09:11:54 -0700112 const grpc_channel_args *args,
Craig Tiller3e149f32016-05-17 16:11:04 -0700113 grpc_tcp_server **server) {
Craig Tillera82950e2015-09-22 12:33:20 -0700114 grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server));
Craig Tiller290e9a72016-10-28 08:17:00 -0700115 s->resource_quota = grpc_resource_quota_create(NULL);
116 for (size_t i = 0; i < (args == NULL ? 0 : args->num_args); i++) {
117 if (0 == strcmp(GRPC_ARG_RESOURCE_QUOTA, args->args[i].key)) {
118 if (args->args[i].type == GRPC_ARG_POINTER) {
Craig Tillera59c16c2016-10-31 07:25:01 -0700119 grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
Craig Tiller290e9a72016-10-28 08:17:00 -0700120 s->resource_quota =
Craig Tillera59c16c2016-10-31 07:25:01 -0700121 grpc_resource_quota_ref_internal(args->args[i].value.pointer.p);
Craig Tiller290e9a72016-10-28 08:17:00 -0700122 } else {
Craig Tillera59c16c2016-10-31 07:25:01 -0700123 grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
Craig Tiller290e9a72016-10-28 08:17:00 -0700124 gpr_free(s);
125 return GRPC_ERROR_CREATE(GRPC_ARG_RESOURCE_QUOTA
126 " must be a pointer to a buffer pool");
127 }
128 }
129 }
Dan Bornfa6b6062016-01-08 21:01:59 -0800130 gpr_ref_init(&s->refs, 1);
Craig Tillera82950e2015-09-22 12:33:20 -0700131 gpr_mu_init(&s->mu);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100132 s->active_ports = 0;
Robbie Shade3cd2d182015-08-28 14:30:35 -0400133 s->on_accept_cb = NULL;
134 s->on_accept_cb_arg = NULL;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800135 s->head = NULL;
Dan Bornfa6b6062016-01-08 21:01:59 -0800136 s->tail = NULL;
Dan Born9c12bc22016-01-13 16:52:20 -0800137 s->shutdown_starting.head = NULL;
138 s->shutdown_starting.tail = NULL;
Dan Bornfa6b6062016-01-08 21:01:59 -0800139 s->shutdown_complete = shutdown_complete;
Craig Tillera41ac572016-05-17 16:08:17 -0700140 *server = s;
141 return GRPC_ERROR_NONE;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100142}
143
Craig Tillerfdc17aa2016-11-29 13:54:19 -0800144static void destroy_server(grpc_exec_ctx *exec_ctx, void *arg,
145 grpc_error *error) {
Craig Tillercbafdd12016-11-29 13:54:00 -0800146 grpc_tcp_server *s = arg;
Craig Tiller5100ea02015-09-01 12:23:28 -0700147
148 /* Now that the accepts have been aborted, we can destroy the sockets.
Craig Tiller45724b32015-09-22 10:42:19 -0700149 The IOCP won't get notified on these, so we can flag them as already
150 closed by the system. */
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800151 while (s->head) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800152 grpc_tcp_listener *sp = s->head;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800153 s->head = sp->next;
154 sp->next = NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700155 grpc_winsocket_destroy(sp->socket);
Dan Born50ef3042016-01-13 13:35:33 -0800156 gpr_free(sp);
Craig Tillera82950e2015-09-22 12:33:20 -0700157 }
Craig Tillera59c16c2016-10-31 07:25:01 -0700158 grpc_resource_quota_unref_internal(exec_ctx, s->resource_quota);
Craig Tillera82950e2015-09-22 12:33:20 -0700159 gpr_free(s);
Craig Tiller5100ea02015-09-01 12:23:28 -0700160}
161
Craig Tillerfdc17aa2016-11-29 13:54:19 -0800162static void finish_shutdown_locked(grpc_exec_ctx *exec_ctx,
163 grpc_tcp_server *s) {
Craig Tillercbafdd12016-11-29 13:54:00 -0800164 if (s->shutdown_complete != NULL) {
Craig Tiller91031da2016-12-28 15:44:25 -0800165 grpc_closure_sched(exec_ctx, s->shutdown_complete, GRPC_ERROR_NONE);
Craig Tillercbafdd12016-11-29 13:54:00 -0800166 }
167
Craig Tillerd4654562017-01-03 08:45:56 -0800168 grpc_closure_sched(exec_ctx, grpc_closure_create(destroy_server, s,
169 grpc_schedule_on_exec_ctx),
170 GRPC_ERROR_NONE);
Craig Tillercbafdd12016-11-29 13:54:00 -0800171}
172
Dan Bornfa6b6062016-01-08 21:01:59 -0800173grpc_tcp_server *grpc_tcp_server_ref(grpc_tcp_server *s) {
Dan Born966a4482016-09-26 15:51:42 -0700174 gpr_ref_non_zero(&s->refs);
Dan Bornfa6b6062016-01-08 21:01:59 -0800175 return s;
176}
177
Dan Born9c12bc22016-01-13 16:52:20 -0800178void grpc_tcp_server_shutdown_starting_add(grpc_tcp_server *s,
179 grpc_closure *shutdown_starting) {
180 gpr_mu_lock(&s->mu);
Craig Tiller3e149f32016-05-17 16:11:04 -0700181 grpc_closure_list_append(&s->shutdown_starting, shutdown_starting,
182 GRPC_ERROR_NONE);
Dan Born9c12bc22016-01-13 16:52:20 -0800183 gpr_mu_unlock(&s->mu);
184}
185
Dan Born5d81d152016-01-12 20:29:29 -0800186static void tcp_server_destroy(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800187 grpc_tcp_listener *sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700188 gpr_mu_lock(&s->mu);
Craig Tiller063560e2015-09-01 08:44:42 -0700189
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700190 /* First, shutdown all fd's. This will queue abortion calls for all
Nicolas "Pixel" Noblee503cd52015-07-14 02:27:23 +0200191 of the pending accepts due to the normal operation mechanism. */
Craig Tillera82950e2015-09-22 12:33:20 -0700192 if (s->active_ports == 0) {
Craig Tillercbafdd12016-11-29 13:54:00 -0800193 finish_shutdown_locked(exec_ctx, s);
194 } else {
195 for (sp = s->head; sp; sp = sp->next) {
196 sp->shutting_down = 1;
197 grpc_winsocket_shutdown(sp->socket);
198 }
Craig Tillera82950e2015-09-22 12:33:20 -0700199 }
200 gpr_mu_unlock(&s->mu);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100201}
202
Dan Bornfa6b6062016-01-08 21:01:59 -0800203void grpc_tcp_server_unref(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s) {
204 if (gpr_unref(&s->refs)) {
Dan Born966a4482016-09-26 15:51:42 -0700205 grpc_tcp_server_shutdown_listeners(exec_ctx, s);
Dan Born9c12bc22016-01-13 16:52:20 -0800206 gpr_mu_lock(&s->mu);
Craig Tiller460da032017-01-03 08:45:29 -0800207 grpc_closure_list_sched(exec_ctx, &s->shutdown_starting);
Dan Born9c12bc22016-01-13 16:52:20 -0800208 gpr_mu_unlock(&s->mu);
Dan Born966a4482016-09-26 15:51:42 -0700209 tcp_server_destroy(exec_ctx, s);
Dan Bornfa6b6062016-01-08 21:01:59 -0800210 }
211}
212
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700213/* Prepare (bind) a recently-created socket for listening. */
murgatroid99dedb9232016-09-26 13:54:04 -0700214static grpc_error *prepare_socket(SOCKET sock,
215 const grpc_resolved_address *addr,
Michael Lumish77c6cce2016-09-26 13:51:57 -0700216 int *port) {
Michael Lumish77c6cce2016-09-26 13:51:57 -0700217 grpc_resolved_address sockname_temp;
Craig Tillera41ac572016-05-17 16:08:17 -0700218 grpc_error *error = GRPC_ERROR_NONE;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100219
Craig Tillera41ac572016-05-17 16:08:17 -0700220 error = grpc_tcp_prepare_socket(sock);
221 if (error != GRPC_ERROR_NONE) {
222 goto failure;
Craig Tillera82950e2015-09-22 12:33:20 -0700223 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100224
murgatroid99dedb9232016-09-26 13:54:04 -0700225 if (bind(sock, (const struct sockaddr *)addr->addr, (int)addr->len) ==
226 SOCKET_ERROR) {
Craig Tillera41ac572016-05-17 16:08:17 -0700227 error = GRPC_WSA_ERROR(WSAGetLastError(), "bind");
228 goto failure;
Craig Tillera82950e2015-09-22 12:33:20 -0700229 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100230
Craig Tillera82950e2015-09-22 12:33:20 -0700231 if (listen(sock, SOMAXCONN) == SOCKET_ERROR) {
Craig Tillera41ac572016-05-17 16:08:17 -0700232 error = GRPC_WSA_ERROR(WSAGetLastError(), "listen");
233 goto failure;
Craig Tillera82950e2015-09-22 12:33:20 -0700234 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100235
Craig Tiller85fe0382016-10-28 08:43:01 -0700236 int sockname_temp_len = sizeof(struct sockaddr_storage);
murgatroid99dedb9232016-09-26 13:54:04 -0700237 if (getsockname(sock, (struct sockaddr *)sockname_temp.addr,
Craig Tiller85fe0382016-10-28 08:43:01 -0700238 &sockname_temp_len) == SOCKET_ERROR) {
Craig Tillera41ac572016-05-17 16:08:17 -0700239 error = GRPC_WSA_ERROR(WSAGetLastError(), "getsockname");
240 goto failure;
Craig Tillera82950e2015-09-22 12:33:20 -0700241 }
Mario Emmenlauerd817c1b2016-12-13 22:35:50 +0100242 sockname_temp.len = (size_t)sockname_temp_len;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100243
Michael Lumish77c6cce2016-09-26 13:51:57 -0700244 *port = grpc_sockaddr_get_port(&sockname_temp);
Craig Tillera41ac572016-05-17 16:08:17 -0700245 return GRPC_ERROR_NONE;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100246
Craig Tillera41ac572016-05-17 16:08:17 -0700247failure:
248 GPR_ASSERT(error != GRPC_ERROR_NONE);
249 char *tgtaddr = grpc_sockaddr_to_uri(addr);
Jan Tattermuschdf715182017-01-11 10:44:41 +0100250 grpc_error_set_int(
Craig Tiller3e149f32016-05-17 16:11:04 -0700251 grpc_error_set_str(GRPC_ERROR_CREATE_REFERENCING(
252 "Failed to prepare server socket", &error, 1),
253 GRPC_ERROR_STR_TARGET_ADDRESS, tgtaddr),
254 GRPC_ERROR_INT_FD, (intptr_t)sock);
Craig Tillera41ac572016-05-17 16:08:17 -0700255 gpr_free(tgtaddr);
256 GRPC_ERROR_UNREF(error);
Craig Tillera82950e2015-09-22 12:33:20 -0700257 if (sock != INVALID_SOCKET) closesocket(sock);
Craig Tillera41ac572016-05-17 16:08:17 -0700258 return error;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100259}
260
Craig Tillercbafdd12016-11-29 13:54:00 -0800261static void decrement_active_ports_and_notify_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerfdc17aa2016-11-29 13:54:19 -0800262 grpc_tcp_listener *sp) {
Jan Tattermusch2f25d982015-08-03 18:01:26 -0700263 sp->shutting_down = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700264 GPR_ASSERT(sp->server->active_ports > 0);
yang-g9aa4f1b2016-03-02 16:39:13 -0800265 if (0 == --sp->server->active_ports) {
Craig Tillercbafdd12016-11-29 13:54:00 -0800266 finish_shutdown_locked(exec_ctx, sp->server);
Craig Tillera82950e2015-09-22 12:33:20 -0700267 }
Jan Tattermusch2f25d982015-08-03 18:01:26 -0700268}
269
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700270/* In order to do an async accept, we need to create a socket first which
271 will be the one assigned to the new incoming connection. */
Craig Tillercbafdd12016-11-29 13:54:00 -0800272static grpc_error *start_accept_locked(grpc_exec_ctx *exec_ctx,
Craig Tillerfdc17aa2016-11-29 13:54:19 -0800273 grpc_tcp_listener *port) {
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100274 SOCKET sock = INVALID_SOCKET;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100275 BOOL success;
Craig Tillera82950e2015-09-22 12:33:20 -0700276 DWORD addrlen = sizeof(struct sockaddr_in6) + 16;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100277 DWORD bytes_received = 0;
Craig Tillera41ac572016-05-17 16:08:17 -0700278 grpc_error *error = GRPC_ERROR_NONE;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100279
Craig Tillercbafdd12016-11-29 13:54:00 -0800280 if (port->shutting_down) {
281 return GRPC_ERROR_NONE;
282 }
283
Craig Tillera82950e2015-09-22 12:33:20 -0700284 sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
285 WSA_FLAG_OVERLAPPED);
Craig Tillera82950e2015-09-22 12:33:20 -0700286 if (sock == INVALID_SOCKET) {
Craig Tillera41ac572016-05-17 16:08:17 -0700287 error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
Craig Tillera82950e2015-09-22 12:33:20 -0700288 goto failure;
289 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100290
Craig Tillera41ac572016-05-17 16:08:17 -0700291 error = grpc_tcp_prepare_socket(sock);
292 if (error != GRPC_ERROR_NONE) goto failure;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100293
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700294 /* Start the "accept" asynchronously. */
Craig Tillera82950e2015-09-22 12:33:20 -0700295 success = port->AcceptEx(port->socket->socket, sock, port->addresses, 0,
296 addrlen, addrlen, &bytes_received,
297 &port->socket->read_info.overlapped);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100298
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700299 /* It is possible to get an accept immediately without delay. However, we
300 will still get an IOCP notification for it. So let's just ignore it. */
Craig Tillera82950e2015-09-22 12:33:20 -0700301 if (!success) {
Craig Tillera41ac572016-05-17 16:08:17 -0700302 int last_error = WSAGetLastError();
303 if (last_error != ERROR_IO_PENDING) {
304 error = GRPC_WSA_ERROR(last_error, "AcceptEx");
Craig Tillera82950e2015-09-22 12:33:20 -0700305 goto failure;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100306 }
Craig Tillera82950e2015-09-22 12:33:20 -0700307 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100308
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700309 /* We're ready to do the accept. Calling grpc_socket_notify_on_read may
310 immediately process an accept that happened in the meantime. */
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100311 port->new_socket = sock;
Craig Tiller82f9bd82015-09-23 09:31:51 -0700312 grpc_socket_notify_on_read(exec_ctx, port->socket, &port->on_accept);
Craig Tillercbafdd12016-11-29 13:54:00 -0800313 port->outstanding_calls++;
Craig Tillera41ac572016-05-17 16:08:17 -0700314 return error;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100315
316failure:
Craig Tillera41ac572016-05-17 16:08:17 -0700317 GPR_ASSERT(error != GRPC_ERROR_NONE);
Craig Tillera82950e2015-09-22 12:33:20 -0700318 if (sock != INVALID_SOCKET) closesocket(sock);
Craig Tillera41ac572016-05-17 16:08:17 -0700319 return error;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100320}
321
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700322/* Event manager callback when reads are ready. */
Craig Tillera41ac572016-05-17 16:08:17 -0700323static void on_accept(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800324 grpc_tcp_listener *sp = arg;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100325 SOCKET sock = sp->new_socket;
326 grpc_winsocket_callback_info *info = &sp->socket->read_info;
327 grpc_endpoint *ep = NULL;
Michael Lumish77c6cce2016-09-26 13:51:57 -0700328 grpc_resolved_address peer_name;
Craig Tiller81bcc4c2015-07-20 14:04:18 -0700329 char *peer_name_string;
330 char *fd_name;
chai2010e55e1832015-07-14 13:24:48 +0800331 DWORD transfered_bytes;
332 DWORD flags;
333 BOOL wsa_success;
Jan Tattermusch3f7809d2015-07-24 13:20:40 -0700334 int err;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100335
Craig Tillercbafdd12016-11-29 13:54:00 -0800336 gpr_mu_lock(&sp->server->mu);
337
Michael Lumish77c6cce2016-09-26 13:51:57 -0700338 peer_name.len = sizeof(struct sockaddr_storage);
339
Nicolas "Pixel" Noblee503cd52015-07-14 02:27:23 +0200340 /* The general mechanism for shutting down is to queue abortion calls. While
341 this is necessary in the read/write case, it's useless for the accept
Jan Tattermuscheab5c332015-07-29 11:49:31 -0700342 case. We only need to adjust the pending callback count */
Craig Tillera41ac572016-05-17 16:08:17 -0700343 if (error != GRPC_ERROR_NONE) {
344 const char *msg = grpc_error_string(error);
345 gpr_log(GPR_INFO, "Skipping on_accept due to error: %s", msg);
Craig Tiller7c70b6c2017-01-23 07:48:42 -0800346
Craig Tillercbafdd12016-11-29 13:54:00 -0800347 gpr_mu_unlock(&sp->server->mu);
Craig Tillera82950e2015-09-22 12:33:20 -0700348 return;
349 }
Nicolas "Pixel" Noble404fc6a2015-05-02 02:34:39 -0700350
Nicolas "Pixel" Noblee503cd52015-07-14 02:27:23 +0200351 /* The IOCP notified us of a completed operation. Let's grab the results,
Craig Tiller45724b32015-09-22 10:42:19 -0700352 and act accordingly. */
chai2010e55e1832015-07-14 13:24:48 +0800353 transfered_bytes = 0;
Craig Tillera82950e2015-09-22 12:33:20 -0700354 wsa_success = WSAGetOverlappedResult(sock, &info->overlapped,
355 &transfered_bytes, FALSE, &flags);
356 if (!wsa_success) {
Craig Tillercbafdd12016-11-29 13:54:00 -0800357 if (!sp->shutting_down) {
Craig Tillera82950e2015-09-22 12:33:20 -0700358 char *utf8_message = gpr_format_message(WSAGetLastError());
359 gpr_log(GPR_ERROR, "on_accept error: %s", utf8_message);
360 gpr_free(utf8_message);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100361 }
Craig Tillercbafdd12016-11-29 13:54:00 -0800362 closesocket(sock);
Craig Tillera82950e2015-09-22 12:33:20 -0700363 } else {
364 if (!sp->shutting_down) {
365 peer_name_string = NULL;
366 err = setsockopt(sock, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,
367 (char *)&sp->socket->socket, sizeof(sp->socket->socket));
368 if (err) {
369 char *utf8_message = gpr_format_message(WSAGetLastError());
370 gpr_log(GPR_ERROR, "setsockopt error: %s", utf8_message);
371 gpr_free(utf8_message);
372 }
Craig Tiller6108d1f2016-10-28 08:43:21 -0700373 int peer_name_len = (int)peer_name.len;
murgatroid99dedb9232016-09-26 13:54:04 -0700374 err =
Craig Tiller85fe0382016-10-28 08:43:01 -0700375 getpeername(sock, (struct sockaddr *)peer_name.addr, &peer_name_len);
Mario Emmenlauerd817c1b2016-12-13 22:35:50 +0100376 peer_name.len = (size_t)peer_name_len;
Craig Tillera82950e2015-09-22 12:33:20 -0700377 if (!err) {
Michael Lumish77c6cce2016-09-26 13:51:57 -0700378 peer_name_string = grpc_sockaddr_to_uri(&peer_name);
Craig Tillera82950e2015-09-22 12:33:20 -0700379 } else {
380 char *utf8_message = gpr_format_message(WSAGetLastError());
381 gpr_log(GPR_ERROR, "getpeername error: %s", utf8_message);
382 gpr_free(utf8_message);
383 }
384 gpr_asprintf(&fd_name, "tcp_server:%s", peer_name_string);
Craig Tillera5ea56b2016-10-28 08:19:02 -0700385 ep = grpc_tcp_create(grpc_winsocket_create(sock, fd_name),
386 sp->server->resource_quota, peer_name_string);
Craig Tillera82950e2015-09-22 12:33:20 -0700387 gpr_free(fd_name);
388 gpr_free(peer_name_string);
Craig Tillerfaf8f682015-10-06 09:12:34 -0700389 } else {
390 closesocket(sock);
Nicolas "Pixel" Noble0f981e92015-05-03 10:40:56 +0200391 }
Craig Tillera82950e2015-09-22 12:33:20 -0700392 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100393
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700394 /* The only time we should call our callback, is where we successfully
395 managed to accept a connection, and created an endpoint. */
Craig Tiller8ad69bf2016-05-20 08:48:22 -0700396 if (ep) {
Mark D. Roth6c07bf82016-12-09 08:38:38 -0800397 // Create acceptor.
398 grpc_tcp_server_acceptor *acceptor = gpr_malloc(sizeof(*acceptor));
399 acceptor->from_server = sp->server;
400 acceptor->port_index = sp->port_index;
401 acceptor->fd_index = 0;
Craig Tillere0049582016-05-20 10:31:09 -0700402 sp->server->on_accept_cb(exec_ctx, sp->server->on_accept_cb_arg, ep, NULL,
Mark D. Rotheed38152016-12-08 13:59:13 -0800403 acceptor);
Craig Tiller8ad69bf2016-05-20 08:48:22 -0700404 }
Nicolas "Pixel" Noble0f981e92015-05-03 10:40:56 +0200405 /* As we were notified from the IOCP of one and exactly one accept,
Nicolas "Pixel" Noblee503cd52015-07-14 02:27:23 +0200406 the former socked we created has now either been destroy or assigned
407 to the new connection. We need to create a new one for the next
408 connection. */
Craig Tillerfdc17aa2016-11-29 13:54:19 -0800409 GPR_ASSERT(
410 GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp)));
Craig Tillercbafdd12016-11-29 13:54:00 -0800411 if (0 == --sp->outstanding_calls) {
412 decrement_active_ports_and_notify_locked(exec_ctx, sp);
413 }
414 gpr_mu_unlock(&sp->server->mu);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100415}
416
Craig Tillera41ac572016-05-17 16:08:17 -0700417static grpc_error *add_socket_to_server(grpc_tcp_server *s, SOCKET sock,
Michael Lumish77c6cce2016-09-26 13:51:57 -0700418 const grpc_resolved_address *addr,
419 unsigned port_index,
Craig Tiller3e149f32016-05-17 16:11:04 -0700420 grpc_tcp_listener **listener) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800421 grpc_tcp_listener *sp = NULL;
Ken Payson8891ef52016-06-22 16:47:52 -0700422 int port = -1;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100423 int status;
424 GUID guid = WSAID_ACCEPTEX;
425 DWORD ioctl_num_bytes;
426 LPFN_ACCEPTEX AcceptEx;
Craig Tillera41ac572016-05-17 16:08:17 -0700427 grpc_error *error = GRPC_ERROR_NONE;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100428
Nicolas "Pixel" Noble8e1a55d2015-05-02 15:21:25 -0700429 /* We need to grab the AcceptEx pointer for that port, as it may be
430 interface-dependent. We'll cache it to avoid doing that again. */
Craig Tillera82950e2015-09-22 12:33:20 -0700431 status =
432 WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
433 &AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100434
Craig Tillera82950e2015-09-22 12:33:20 -0700435 if (status != 0) {
436 char *utf8_message = gpr_format_message(WSAGetLastError());
437 gpr_log(GPR_ERROR, "on_connect error: %s", utf8_message);
438 gpr_free(utf8_message);
439 closesocket(sock);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800440 return NULL;
Craig Tillera82950e2015-09-22 12:33:20 -0700441 }
Craig Tiller45724b32015-09-22 10:42:19 -0700442
Michael Lumish77c6cce2016-09-26 13:51:57 -0700443 error = prepare_socket(sock, addr, &port);
Craig Tillera41ac572016-05-17 16:08:17 -0700444 if (error != GRPC_ERROR_NONE) {
445 return error;
Craig Tillera82950e2015-09-22 12:33:20 -0700446 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100447
Craig Tillera41ac572016-05-17 16:08:17 -0700448 GPR_ASSERT(port >= 0);
449 gpr_mu_lock(&s->mu);
450 GPR_ASSERT(!s->on_accept_cb && "must add ports before starting server");
451 sp = gpr_malloc(sizeof(grpc_tcp_listener));
452 sp->next = NULL;
453 if (s->head == NULL) {
454 s->head = sp;
455 } else {
456 s->tail->next = sp;
457 }
458 s->tail = sp;
459 sp->server = s;
460 sp->socket = grpc_winsocket_create(sock, "listener");
461 sp->shutting_down = 0;
Craig Tillercbafdd12016-11-29 13:54:00 -0800462 sp->outstanding_calls = 0;
Craig Tillera41ac572016-05-17 16:08:17 -0700463 sp->AcceptEx = AcceptEx;
464 sp->new_socket = INVALID_SOCKET;
465 sp->port = port;
466 sp->port_index = port_index;
Craig Tiller91031da2016-12-28 15:44:25 -0800467 grpc_closure_init(&sp->on_accept, on_accept, sp, grpc_schedule_on_exec_ctx);
Craig Tillera41ac572016-05-17 16:08:17 -0700468 GPR_ASSERT(sp->socket);
469 gpr_mu_unlock(&s->mu);
470 *listener = sp;
471
472 return GRPC_ERROR_NONE;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100473}
474
Michael Lumish77c6cce2016-09-26 13:51:57 -0700475grpc_error *grpc_tcp_server_add_port(grpc_tcp_server *s,
murgatroid99dedb9232016-09-26 13:54:04 -0700476 const grpc_resolved_address *addr,
Michael Lumish77c6cce2016-09-26 13:51:57 -0700477 int *port) {
Craig Tiller5352ff12016-05-18 10:44:38 -0700478 grpc_tcp_listener *sp = NULL;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100479 SOCKET sock;
Michael Lumish77c6cce2016-09-26 13:51:57 -0700480 grpc_resolved_address addr6_v4mapped;
481 grpc_resolved_address wildcard;
482 grpc_resolved_address *allocated_addr = NULL;
483 grpc_resolved_address sockname_temp;
Dan Bornfa6b6062016-01-08 21:01:59 -0800484 unsigned port_index = 0;
Craig Tillera41ac572016-05-17 16:08:17 -0700485 grpc_error *error = GRPC_ERROR_NONE;
486
Dan Bornfa6b6062016-01-08 21:01:59 -0800487 if (s->tail != NULL) {
488 port_index = s->tail->port_index + 1;
489 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100490
491 /* Check if this is a wildcard port, and if so, try to keep the port the same
492 as some previously created listener. */
Craig Tillera82950e2015-09-22 12:33:20 -0700493 if (grpc_sockaddr_get_port(addr) == 0) {
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800494 for (sp = s->head; sp; sp = sp->next) {
Craig Tiller85fe0382016-10-28 08:43:01 -0700495 int sockname_temp_len = sizeof(struct sockaddr_storage);
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800496 if (0 == getsockname(sp->socket->socket,
murgatroid99dedb9232016-09-26 13:54:04 -0700497 (struct sockaddr *)sockname_temp.addr,
Craig Tiller85fe0382016-10-28 08:43:01 -0700498 &sockname_temp_len)) {
Mario Emmenlauerd817c1b2016-12-13 22:35:50 +0100499 sockname_temp.len = (size_t)sockname_temp_len;
Michael Lumish77c6cce2016-09-26 13:51:57 -0700500 *port = grpc_sockaddr_get_port(&sockname_temp);
Craig Tillera41ac572016-05-17 16:08:17 -0700501 if (*port > 0) {
Michael Lumish77c6cce2016-09-26 13:51:57 -0700502 allocated_addr = gpr_malloc(sizeof(grpc_resolved_address));
503 memcpy(allocated_addr, addr, sizeof(grpc_resolved_address));
Craig Tillera41ac572016-05-17 16:08:17 -0700504 grpc_sockaddr_set_port(allocated_addr, *port);
Craig Tillera82950e2015-09-22 12:33:20 -0700505 addr = allocated_addr;
506 break;
507 }
508 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100509 }
Craig Tillera82950e2015-09-22 12:33:20 -0700510 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100511
Craig Tillera82950e2015-09-22 12:33:20 -0700512 if (grpc_sockaddr_to_v4mapped(addr, &addr6_v4mapped)) {
Michael Lumish77c6cce2016-09-26 13:51:57 -0700513 addr = &addr6_v4mapped;
Craig Tillera82950e2015-09-22 12:33:20 -0700514 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100515
516 /* Treat :: or 0.0.0.0 as a family-agnostic wildcard. */
Craig Tillera41ac572016-05-17 16:08:17 -0700517 if (grpc_sockaddr_is_wildcard(addr, port)) {
518 grpc_sockaddr_make_wildcard6(*port, &wildcard);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100519
Michael Lumish77c6cce2016-09-26 13:51:57 -0700520 addr = &wildcard;
Craig Tillera82950e2015-09-22 12:33:20 -0700521 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100522
Craig Tillera82950e2015-09-22 12:33:20 -0700523 sock = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, NULL, 0,
524 WSA_FLAG_OVERLAPPED);
525 if (sock == INVALID_SOCKET) {
Craig Tillera41ac572016-05-17 16:08:17 -0700526 error = GRPC_WSA_ERROR(WSAGetLastError(), "WSASocket");
527 goto done;
Craig Tillera82950e2015-09-22 12:33:20 -0700528 }
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100529
Michael Lumish77c6cce2016-09-26 13:51:57 -0700530 error = add_socket_to_server(s, sock, addr, port_index, &sp);
Craig Tillera41ac572016-05-17 16:08:17 -0700531
532done:
Craig Tillera82950e2015-09-22 12:33:20 -0700533 gpr_free(allocated_addr);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100534
Craig Tillera41ac572016-05-17 16:08:17 -0700535 if (error != GRPC_ERROR_NONE) {
Craig Tiller3e149f32016-05-17 16:11:04 -0700536 grpc_error *error_out = GRPC_ERROR_CREATE_REFERENCING(
537 "Failed to add port to server", &error, 1);
Craig Tillera41ac572016-05-17 16:08:17 -0700538 GRPC_ERROR_UNREF(error);
539 error = error_out;
Craig Tiller5352ff12016-05-18 10:44:38 -0700540 *port = -1;
541 } else {
542 GPR_ASSERT(sp != NULL);
543 *port = sp->port;
Dan Bornfa6b6062016-01-08 21:01:59 -0800544 }
Craig Tillera41ac572016-05-17 16:08:17 -0700545 return error;
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100546}
547
Craig Tiller565b18b2015-09-23 10:09:42 -0700548void grpc_tcp_server_start(grpc_exec_ctx *exec_ctx, grpc_tcp_server *s,
549 grpc_pollset **pollset, size_t pollset_count,
Craig Tillera82950e2015-09-22 12:33:20 -0700550 grpc_tcp_server_cb on_accept_cb,
551 void *on_accept_cb_arg) {
Nicolas Noble8f714622015-11-19 11:16:54 -0800552 grpc_tcp_listener *sp;
Craig Tillera82950e2015-09-22 12:33:20 -0700553 GPR_ASSERT(on_accept_cb);
554 gpr_mu_lock(&s->mu);
555 GPR_ASSERT(!s->on_accept_cb);
556 GPR_ASSERT(s->active_ports == 0);
Robbie Shade3cd2d182015-08-28 14:30:35 -0400557 s->on_accept_cb = on_accept_cb;
558 s->on_accept_cb_arg = on_accept_cb_arg;
Nicolas Noble5eb4e1c2015-11-18 17:19:45 -0800559 for (sp = s->head; sp; sp = sp->next) {
Craig Tillerfdc17aa2016-11-29 13:54:19 -0800560 GPR_ASSERT(
561 GRPC_LOG_IF_ERROR("start_accept", start_accept_locked(exec_ctx, sp)));
Craig Tillera82950e2015-09-22 12:33:20 -0700562 s->active_ports++;
563 }
564 gpr_mu_unlock(&s->mu);
Nicolas "Pixel" Noble0f3ec822015-02-05 19:40:38 +0100565}
566
yang-g9275d402016-07-11 16:51:39 -0700567void grpc_tcp_server_shutdown_listeners(grpc_exec_ctx *exec_ctx,
568 grpc_tcp_server *s) {}
569
murgatroid99623dd4f2016-08-08 17:31:27 -0700570#endif /* GRPC_WINSOCK_SOCKET */