| 
					
				 | 
			
			
				@@ -55,11 +55,17 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* one listening port */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct server_port { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_uint8 addresses[sizeof(struct sockaddr_in6) * 2 + 32]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* This seemingly magic number comes from AcceptEx's documentation. each 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     address buffer needs to have at least 16 more bytes at their end. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_uint8 addresses[(sizeof(struct sockaddr_in6) + 16) * 2]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* This will hold the socket for the next accept. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SOCKET new_socket; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* The listener winsocked. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_winsocket *socket; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_tcp_server *server; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* The cached AcceptEx for that port. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   LPFN_ACCEPTEX AcceptEx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int shutting_down; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } server_port; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* the overall server */ 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -79,6 +85,8 @@ struct grpc_tcp_server { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t port_capacity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Public function. Allocates the proper data structures to hold a 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   grpc_tcp_server. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 grpc_tcp_server *grpc_tcp_server_create(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_tcp_server *s = gpr_malloc(sizeof(grpc_tcp_server)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_init(&s->mu); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -92,24 +100,29 @@ grpc_tcp_server *grpc_tcp_server_create(void) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return s; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Public function. Stops and destroys a grpc_tcp_server. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 void grpc_tcp_server_destroy(grpc_tcp_server *s, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                              void (*shutdown_done)(void *shutdown_done_arg), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                              void *shutdown_done_arg) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_lock(&s->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* shutdown all fd's */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* First, shutdown all fd's. This will queue abortion calls for all 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     of the pending accepts. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (i = 0; i < s->nports; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_winsocket_shutdown(s->ports[i].socket); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* wait while that happens */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* This happens asynchronously. Wait while that happens. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   while (s->active_ports) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_cv_wait(&s->cv, &s->mu, gpr_inf_future); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_unlock(&s->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* delete ALL the things */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Now that the accepts have been aborted, we can destroy the sockets. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     The IOCP won't get notified on these, so we can flag them as already 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     closed by the system. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (i = 0; i < s->nports; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     server_port *sp = &s->ports[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sp->socket->closed_early = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_winsocket_orphan(sp->socket); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_free(s->ports); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -120,7 +133,7 @@ void grpc_tcp_server_destroy(grpc_tcp_server *s, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/* Prepare a recently-created socket for listening. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Prepare (bind) a recently-created socket for listening. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static int prepare_socket(SOCKET sock, const struct sockaddr *addr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                           int addr_len) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   struct sockaddr_storage sockname_temp; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -168,8 +181,11 @@ error: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void on_accept(void *arg, int success); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* start_accept will reference that for the IOCP notification request. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void on_accept(void *arg, int from_iocp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* In order to do an async accept, we need to create a socket first which 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+   will be the one assigned to the new incoming connection. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void start_accept(server_port *port) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SOCKET sock = INVALID_SOCKET; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   char *message; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -191,12 +207,13 @@ static void start_accept(server_port *port) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     goto failure; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* TODO(jtattermusch): probably a race here, we regularly get use-after-free on server shutdown */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  GPR_ASSERT(port->socket != (grpc_winsocket*)0xfeeefeee); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* Start the "accept" asynchronously. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   success = port->AcceptEx(port->socket->socket, sock, port->addresses, 0, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                            addrlen, addrlen, &bytes_received, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                            &port->socket->read_info.overlapped); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* It is possible to get an accept immediately without delay. However, we 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     will still get an IOCP notification for it. So let's just ignore it. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (!success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int error = WSAGetLastError(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (error != ERROR_IO_PENDING) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -205,6 +222,8 @@ static void start_accept(server_port *port) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* We're ready to do the accept. Calling grpc_socket_notify_on_read may 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     immediately process an accept that happened in the meantime. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   port->new_socket = sock; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_socket_notify_on_read(port->socket, on_accept, port); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -216,14 +235,30 @@ failure: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (sock != INVALID_SOCKET) closesocket(sock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-/* event manager callback when reads are ready */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void on_accept(void *arg, int success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+/* Event manager callback when reads are ready. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void on_accept(void *arg, int from_iocp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   server_port *sp = arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   SOCKET sock = sp->new_socket; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_winsocket_callback_info *info = &sp->socket->read_info; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_endpoint *ep = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* The shutdown sequence is done in two parts. This is the second 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     part here, acknowledging the IOCP notification, and doing nothing 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     else, especially not queuing a new accept. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (sp->shutting_down) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    GPR_ASSERT(from_iocp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sp->shutting_down = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_lock(&sp->server->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (0 == --sp->server->active_ports) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      gpr_cv_broadcast(&sp->server->cv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_unlock(&sp->server->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (from_iocp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* The IOCP notified us of a completed operation. Let's grab the results, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       and act accordingly. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     DWORD transfered_bytes = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     DWORD flags; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     BOOL wsa_success = WSAGetOverlappedResult(sock, &info->overlapped, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -237,16 +272,23 @@ static void on_accept(void *arg, int success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       ep = grpc_tcp_create(grpc_winsocket_create(sock)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* If we're not notified from the IOCP, it means we are asked to shutdown. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       This will initiate that shutdown. Calling closesocket will trigger an 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       IOCP notification, that will call this function a second time, from 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       the IOCP thread. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sp->shutting_down = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sp->new_socket = INVALID_SOCKET; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     closesocket(sock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_lock(&sp->server->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (0 == --sp->server->active_ports) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      gpr_cv_broadcast(&sp->server->cv); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_unlock(&sp->server->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* The only time we should call our callback, is where we successfully 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     managed to accept a connection, and created an endpoint. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (ep) sp->server->cb(sp->server->cb_arg, ep); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (success) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (from_iocp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* As we were notified from the IOCP of one and exactly one accept, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       the former socked we created has now either been destroy or assigned 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       to the new connection. We need to create a new one for the next 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       connection. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     start_accept(sp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -262,6 +304,8 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (sock == INVALID_SOCKET) return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  /* We need to grab the AcceptEx pointer for that port, as it may be 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+     interface-dependent. We'll cache it to avoid doing that again. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   status = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       WSAIoctl(sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                &AcceptEx, sizeof(AcceptEx), &ioctl_num_bytes, NULL, NULL); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -286,6 +330,7 @@ static int add_socket_to_server(grpc_tcp_server *s, SOCKET sock, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sp = &s->ports[s->nports++]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sp->server = s; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sp->socket = grpc_winsocket_create(sock); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    sp->shutting_down = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     sp->AcceptEx = AcceptEx; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     GPR_ASSERT(sp->socket); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_mu_unlock(&s->mu); 
			 |