| 
					
				 | 
			
			
				@@ -35,6 +35,7 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/channel/http_filter.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/channel/http_server_filter.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/iomgr/endpoint.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/iomgr/resolve_address.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/iomgr/tcp_server.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/security/security_context.h" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -43,8 +44,27 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/transport/chttp2_transport.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/alloc.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/log.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include <grpc/support/sync.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/useful.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+typedef struct grpc_server_secure_state { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server *server; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_tcp_server *tcp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  int is_shutdown; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_mu mu; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_refcount refcount; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} grpc_server_secure_state; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void state_ref(grpc_server_secure_state *state) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_ref(&state->refcount); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void state_unref(grpc_server_secure_state *state) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (gpr_unref(&state->refcount)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_free(state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static grpc_transport_setup_result setup_transport(void *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                    grpc_transport *transport, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                    grpc_mdctx *mdctx) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -54,44 +74,62 @@ static grpc_transport_setup_result setup_transport(void *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                      GPR_ARRAY_SIZE(extra_filters), mdctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void on_secure_transport_setup_done(void *server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void on_secure_transport_setup_done(void *statep, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                            grpc_security_status status, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                            grpc_endpoint *secure_endpoint) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server_secure_state *state = statep; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (status == GRPC_SECURITY_OK) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_create_chttp2_transport( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        setup_transport, server, grpc_server_get_channel_args(server), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        secure_endpoint, NULL, 0, grpc_mdctx_create(), 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_lock(&state->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (!state->is_shutdown) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_create_chttp2_transport( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          setup_transport, state->server, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          grpc_server_get_channel_args(state->server), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          secure_endpoint, NULL, 0, grpc_mdctx_create(), 0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* We need to consume this here, because the server may already have gone 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       * away. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_endpoint_destroy(secure_endpoint); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    gpr_mu_unlock(&state->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_log(GPR_ERROR, "Secure transport failed with error %d", status); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  state_unref(state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void on_accept(void *server, grpc_endpoint *tcp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  const grpc_channel_args *args = grpc_server_get_channel_args(server); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void on_accept(void *statep, grpc_endpoint *tcp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server_secure_state *state = statep; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  const grpc_channel_args *args = grpc_server_get_channel_args(state->server); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_security_context *ctx = grpc_find_security_context_in_args(args); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   GPR_ASSERT(ctx); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_setup_secure_transport(ctx, tcp, on_secure_transport_setup_done, server); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  state_ref(state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_setup_secure_transport(ctx, tcp, on_secure_transport_setup_done, state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* Note: the following code is the same with server_chttp2.c */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* Server callback: start listening on our ports */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void start(grpc_server *server, void *tcpp, grpc_pollset **pollsets, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void start(grpc_server *server, void *statep, grpc_pollset **pollsets, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                   size_t pollset_count) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_tcp_server *tcp = tcpp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_tcp_server_start(tcp, pollsets, pollset_count, on_accept, server); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server_secure_state *state = statep; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_tcp_server_start(state->tcp, pollsets, pollset_count, on_accept, state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* Server callback: destroy the tcp listener (so we don't generate further 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				    callbacks) */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void destroy(grpc_server *server, void *tcpp) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_tcp_server *tcp = tcpp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_tcp_server_destroy(tcp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void destroy(grpc_server *server, void *statep) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server_secure_state *state = statep; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_mu_lock(&state->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  state->is_shutdown = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_tcp_server_destroy(state->tcp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_mu_unlock(&state->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  state_unref(state); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_resolved_addresses *resolved = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_tcp_server *tcp = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server_secure_state *state = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t i; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unsigned count = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   int port_num = -1; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -132,8 +170,15 @@ int grpc_server_add_secure_http2_port(grpc_server *server, const char *addr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_resolved_addresses_destroy(resolved); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  state = gpr_malloc(sizeof(*state)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  state->server = server; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  state->tcp = tcp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  state->is_shutdown = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_mu_init(&state->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_ref_init(&state->refcount, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Register with the server only upon success */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_server_add_listener(server, tcp, start, destroy); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_server_add_listener(server, state, start, destroy); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return port_num; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 |