| 
					
				 | 
			
			
				@@ -39,7 +39,9 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/slice_buffer.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/alloc.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include <grpc/support/log.h> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-#include "src/core/lib/iomgr/timer.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/channel/channel_args.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+#include "src/core/lib/channel/handshaker.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/security/context/security_context.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/security/transport/secure_endpoint.h" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #include "src/core/lib/security/transport/tsi_error.h" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -47,24 +49,22 @@ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 #define GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE 256 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 typedef struct { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_handshaker base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_handshaker_args* args; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_closure* on_handshake_done; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_security_connector *connector; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tsi_handshaker *handshaker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  bool is_client_side; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unsigned char *handshake_buffer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t handshake_buffer_size; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_endpoint *wrapped_endpoint; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_endpoint *secure_endpoint; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer left_overs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_slice_buffer incoming; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer outgoing; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_handshake_done_cb cb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  void *user_data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_closure on_handshake_data_sent_to_peer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_closure on_handshake_data_received_from_peer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_auth_context *auth_context; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_timer timer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_refcount refs; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} grpc_security_handshake; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} security_handshaker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                  void *setup, 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -73,40 +73,12 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, void *setup, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                            grpc_error *error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void security_connector_remove_handshake(grpc_security_handshake *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  GPR_ASSERT(!h->is_client_side); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_connector_handshake_list *node; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_connector_handshake_list *tmp; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_server_security_connector *sc = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (grpc_server_security_connector *)h->connector; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_mu_lock(&sc->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  node = sc->handshaking_handshakes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (node && node->handshake == h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    sc->handshaking_handshakes = node->next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_free(node); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_unlock(&sc->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  while (node) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if (node->next->handshake == h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      tmp = node->next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      node->next = node->next->next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      gpr_free(tmp); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      gpr_mu_unlock(&sc->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    node = node->next; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_mu_unlock(&sc->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void unref_handshake(grpc_security_handshake *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void unref_handshake(security_handshaker *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (gpr_unref(&h->refs)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (h->handshaker != NULL) tsi_handshaker_destroy(h->handshaker); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (h->handshake_buffer != NULL) gpr_free(h->handshake_buffer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_slice_buffer_destroy(&h->left_overs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_slice_buffer_destroy(&h->outgoing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice_buffer_destroy(&h->incoming); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     GRPC_AUTH_CONTEXT_UNREF(h->auth_context, "handshake"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     GRPC_SECURITY_CONNECTOR_UNREF(h->connector, "handshake"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_free(h); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -114,36 +86,38 @@ static void unref_handshake(grpc_security_handshake *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void security_handshake_done(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    grpc_security_handshake *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    security_handshaker *h, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                     grpc_error *error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_timer_cancel(exec_ctx, &h->timer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!h->is_client_side) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    security_connector_remove_handshake(h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (error == GRPC_ERROR_NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_OK, h->secure_endpoint, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          h->auth_context); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    h->args->endpoint = h->secure_endpoint; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_channel_args* tmp_args = h->args->args; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    h->args->args = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        grpc_channel_args_copy_and_add(tmp_args, &auth_context_arg, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_channel_args_destroy(tmp_args); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     const char *msg = grpc_error_string(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     gpr_log(GPR_DEBUG, "Security handshake failed: %s", msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_error_free_string(msg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (h->secure_endpoint != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_endpoint_shutdown(exec_ctx, h->secure_endpoint); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_endpoint_destroy(exec_ctx, h->secure_endpoint); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_endpoint_destroy(exec_ctx, h->wrapped_endpoint); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    h->cb(exec_ctx, h->user_data, GRPC_SECURITY_ERROR, NULL, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Clear out the read buffer before it gets passed to the transport, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // since any excess bytes were already moved to h->left_overs. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_slice_buffer_reset_and_unref(h->args->read_buffer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  h->args = NULL; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_exec_ctx_sched(exec_ctx, h->on_handshake_done, error, NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unref_handshake(h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  GRPC_ERROR_UNREF(error); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             grpc_security_status status, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             grpc_auth_context *auth_context) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_handshake *h = user_data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker *h = user_data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tsi_frame_protector *protector; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tsi_result result; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (status != GRPC_SECURITY_OK) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -172,7 +146,7 @@ static void on_peer_checked(grpc_exec_ctx *exec_ctx, void *user_data, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void check_peer(grpc_exec_ctx *exec_ctx, security_handshaker *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tsi_peer peer; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tsi_result result = tsi_handshaker_extract_peer(h->handshaker, &peer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -187,7 +161,7 @@ static void check_peer(grpc_exec_ctx *exec_ctx, grpc_security_handshake *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                         grpc_security_handshake *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                         security_handshaker *h) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t offset = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tsi_result result = TSI_OK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice to_send; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -215,8 +189,6 @@ static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       grpc_slice_from_copied_buffer((const char *)h->handshake_buffer, offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer_reset_and_unref(&h->outgoing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer_add(&h->outgoing, to_send); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* TODO(klempner,jboeuf): This should probably use the client setup 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-     deadline */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_endpoint_write(exec_ctx, h->wrapped_endpoint, &h->outgoing, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                       &h->on_handshake_data_sent_to_peer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -224,7 +196,7 @@ static void send_handshake_bytes_to_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                  void *handshake, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                                  grpc_error *error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_handshake *h = handshake; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker *h = handshake; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t consumed_slice_size = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   tsi_result result = TSI_OK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   size_t i; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -238,10 +210,10 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  for (i = 0; i < h->incoming.count; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    consumed_slice_size = GRPC_SLICE_LENGTH(h->incoming.slices[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  for (i = 0; i < h->args->read_buffer->count; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    consumed_slice_size = GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     result = tsi_handshaker_process_bytes_from_peer( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        h->handshaker, GRPC_SLICE_START_PTR(h->incoming.slices[i]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        h->handshaker, GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         &consumed_slice_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (!tsi_handshaker_is_in_progress(h->handshaker)) break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -249,7 +221,7 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (tsi_handshaker_is_in_progress(h->handshaker)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /* We may need more data. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (result == TSI_INCOMPLETE_DATA) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, h->args->read_buffer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                          &h->on_handshake_data_received_from_peer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } else { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -267,32 +239,33 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Handshake is done and successful this point. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   has_left_overs_in_current_slice = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (consumed_slice_size < GRPC_SLICE_LENGTH(h->incoming.slices[i])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (consumed_slice_size < 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i])); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   num_left_overs = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      (has_left_overs_in_current_slice ? 1 : 0) + h->incoming.count - i - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (num_left_overs == 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    check_peer(exec_ctx, h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      (has_left_overs_in_current_slice ? 1 : 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      + h->args->read_buffer->count - i - 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (num_left_overs > 0) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    /* Put the leftovers in our buffer (ownership transfered). */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if (has_left_overs_in_current_slice) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_slice_buffer_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          &h->left_overs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          grpc_slice_split_tail(&h->args->read_buffer->slices[i], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          consumed_slice_size)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* split_tail above increments refcount. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      grpc_slice_unref(h->args->read_buffer->slices[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_slice_buffer_addn( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        &h->left_overs, &h->args->read_buffer->slices[i + 1], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        num_left_overs - (size_t)has_left_overs_in_current_slice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  /* Put the leftovers in our buffer (ownership transfered). */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (has_left_overs_in_current_slice) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice_buffer_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        &h->left_overs, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        grpc_slice_split_tail(&h->incoming.slices[i], consumed_slice_size)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice_unref( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        h->incoming.slices[i]); /* split_tail above increments refcount. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_slice_buffer_addn( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      &h->left_overs, &h->incoming.slices[i + 1], 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      num_left_overs - (size_t)has_left_overs_in_current_slice); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   check_peer(exec_ctx, h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 /* If handshake is NULL, the handshake is done. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                            void *handshake, grpc_error *error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_handshake *h = handshake; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker *h = handshake; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* Make sure that write is OK. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (error != GRPC_ERROR_NONE) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -305,70 +278,110 @@ static void on_handshake_data_sent_to_peer(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   /* We may be done. */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   if (tsi_handshaker_is_in_progress(h->handshaker)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    /* TODO(klempner,jboeuf): This should probably use the client setup 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-       deadline */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, &h->incoming, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_endpoint_read(exec_ctx, h->wrapped_endpoint, h->args->read_buffer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                        &h->on_handshake_data_received_from_peer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     check_peer(exec_ctx, h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static void on_timeout(grpc_exec_ctx *exec_ctx, void *arg, grpc_error *error) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_handshake *h = arg; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (error == GRPC_ERROR_NONE) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// public handshaker API 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void security_handshaker_destroy(grpc_exec_ctx* exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                            grpc_handshaker* handshaker) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker* h = (security_handshaker*)handshaker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   unref_handshake(h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void grpc_do_security_handshake( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void security_handshaker_shutdown(grpc_exec_ctx* exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                             grpc_handshaker* handshaker) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker *h = (security_handshaker*)handshaker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void security_handshaker_do_handshake( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_handshaker_args* args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker* h = (security_handshaker*)handshaker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  h->args = args; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  h->on_handshake_done = on_handshake_done; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  h->wrapped_endpoint = args->endpoint;  // FIXME: remove? 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_ref(&h->refs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  send_handshake_bytes_to_peer(exec_ctx, h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const grpc_handshaker_vtable security_handshaker_vtable = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker_destroy, security_handshaker_shutdown, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker_do_handshake}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static grpc_handshaker* security_handshaker_create( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_security_connector *connector, bool is_client_side, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_endpoint *nonsecure_endpoint, grpc_slice_buffer *read_buffer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_timespec deadline, grpc_security_handshake_done_cb cb, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    void *user_data) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_connector_handshake_list *handshake_node; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_handshake *h = gpr_malloc(sizeof(grpc_security_handshake)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  memset(h, 0, sizeof(grpc_security_handshake)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_security_connector *connector) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  security_handshaker *h = gpr_malloc(sizeof(security_handshaker)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  memset(h, 0, sizeof(security_handshaker)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_handshaker_init(&security_handshaker_vtable, &h->base); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   h->handshaker = handshaker; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   h->connector = GRPC_SECURITY_CONNECTOR_REF(connector, "handshake"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  h->is_client_side = is_client_side; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   h->handshake_buffer_size = GRPC_INITIAL_HANDSHAKE_BUFFER_SIZE; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   h->handshake_buffer = gpr_malloc(h->handshake_buffer_size); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  h->wrapped_endpoint = nonsecure_endpoint; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  h->user_data = user_data; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  h->cb = cb; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  gpr_ref_init(&h->refs, 2); /* timer and handshake proper each get a ref */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_ref_init(&h->refs, 1); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_closure_init(&h->on_handshake_data_sent_to_peer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     on_handshake_data_sent_to_peer, h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_closure_init(&h->on_handshake_data_received_from_peer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     on_handshake_data_received_from_peer, h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer_init(&h->left_overs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_slice_buffer_init(&h->outgoing); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_slice_buffer_init(&h->incoming); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (read_buffer != NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_slice_buffer_move_into(read_buffer, &h->incoming); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_free(read_buffer); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  if (!is_client_side) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    grpc_server_security_connector *server_connector = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        (grpc_server_security_connector *)connector; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    handshake_node = gpr_malloc(sizeof(grpc_security_connector_handshake_list)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    handshake_node->handshake = h; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_lock(&server_connector->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    handshake_node->next = server_connector->handshaking_handshakes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    server_connector->handshaking_handshakes = handshake_node; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    gpr_mu_unlock(&server_connector->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  send_handshake_bytes_to_peer(exec_ctx, h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_timer_init(exec_ctx, &h->timer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  gpr_convert_clock_type(deadline, GPR_CLOCK_MONOTONIC), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                  on_timeout, h, gpr_now(GPR_CLOCK_MONOTONIC)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return &h->base; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-void grpc_security_handshake_shutdown(grpc_exec_ctx *exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                      void *handshake) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_security_handshake *h = handshake; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-  grpc_endpoint_shutdown(exec_ctx, h->wrapped_endpoint); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// fail_handshaker 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void fail_handshaker_destroy(grpc_exec_ctx* exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                    grpc_handshaker* handshaker) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  gpr_free(handshaker); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void fail_handshaker_shutdown(grpc_exec_ctx* exec_ctx, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                     grpc_handshaker* handshaker) {} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void fail_handshaker_do_handshake( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_tcp_server_acceptor* acceptor, grpc_closure* on_handshake_done, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_handshaker_args* args) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_exec_ctx_sched( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      exec_ctx, on_handshake_done, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      GRPC_ERROR_CREATE("Failed to create security handshaker"), NULL); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static const grpc_handshaker_vtable fail_handshaker_vtable = { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fail_handshaker_destroy, fail_handshaker_shutdown, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  fail_handshaker_do_handshake}; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static grpc_handshaker* fail_handshaker_create() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_handshaker* h = gpr_malloc(sizeof(*h)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  grpc_handshaker_init(&fail_handshaker_vtable, h); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  return h; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// exported functions 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+// 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+void grpc_security_create_handshakers( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_exec_ctx *exec_ctx, tsi_handshaker *handshaker, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_security_connector *connector, grpc_handshake_manager *handshake_mgr) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // If no TSI handshaker was created, add a handshaker that always fails. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  // Otherwise, add a real security handshaker. 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  if (handshaker == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_handshake_manager_add(handshake_mgr, fail_handshaker_create()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } else { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    grpc_handshake_manager_add( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        handshake_mgr, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        security_handshaker_create(exec_ctx, handshaker, connector)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 |