|  | @@ -41,6 +41,11 @@
 | 
	
		
			
				|  |  |  #include "src/core/tsi/alts/handshaker/alts_tsi_utils.h"
 | 
	
		
			
				|  |  |  #include "src/core/tsi/alts/zero_copy_frame_protector/alts_zero_copy_grpc_protector.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// Frame size negotiation extends send frame size range to
 | 
	
		
			
				|  |  | +// [kMinFrameSize, kMaxFrameSize]
 | 
	
		
			
				|  |  | +constexpr size_t kMinFrameSize = 16 * 1024;
 | 
	
		
			
				|  |  | +constexpr size_t kMaxFrameSize = 128 * 1024;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  /* Main struct for ALTS TSI handshaker. */
 | 
	
		
			
				|  |  |  struct alts_tsi_handshaker {
 | 
	
		
			
				|  |  |    tsi_handshaker base;
 | 
	
	
		
			
				|  | @@ -63,6 +68,8 @@ struct alts_tsi_handshaker {
 | 
	
		
			
				|  |  |    // shutdown effectively follows base.handshake_shutdown,
 | 
	
		
			
				|  |  |    // but is synchronized by the mutex of this object.
 | 
	
		
			
				|  |  |    bool shutdown;
 | 
	
		
			
				|  |  | +  // Maximum frame size used by frame protector.
 | 
	
		
			
				|  |  | +  size_t max_frame_size;
 | 
	
		
			
				|  |  |  };
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /* Main struct for ALTS TSI handshaker result. */
 | 
	
	
		
			
				|  | @@ -75,6 +82,8 @@ typedef struct alts_tsi_handshaker_result {
 | 
	
		
			
				|  |  |    grpc_slice rpc_versions;
 | 
	
		
			
				|  |  |    bool is_client;
 | 
	
		
			
				|  |  |    grpc_slice serialized_context;
 | 
	
		
			
				|  |  | +  // Peer's maximum frame size.
 | 
	
		
			
				|  |  | +  size_t max_frame_size;
 | 
	
		
			
				|  |  |  } alts_tsi_handshaker_result;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static tsi_result handshaker_result_extract_peer(
 | 
	
	
		
			
				|  | @@ -156,6 +165,26 @@ static tsi_result handshaker_result_create_zero_copy_grpc_protector(
 | 
	
		
			
				|  |  |    alts_tsi_handshaker_result* result =
 | 
	
		
			
				|  |  |        reinterpret_cast<alts_tsi_handshaker_result*>(
 | 
	
		
			
				|  |  |            const_cast<tsi_handshaker_result*>(self));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +  // In case the peer does not send max frame size (e.g. peer is gRPC Go or
 | 
	
		
			
				|  |  | +  // peer uses an old binary), the negotiated frame size is set to
 | 
	
		
			
				|  |  | +  // kMinFrameSize (ignoring max_output_protected_frame_size value if
 | 
	
		
			
				|  |  | +  // present). Otherwise, it is based on peer and user specified max frame
 | 
	
		
			
				|  |  | +  // size (if present).
 | 
	
		
			
				|  |  | +  size_t max_frame_size = kMinFrameSize;
 | 
	
		
			
				|  |  | +  if (result->max_frame_size) {
 | 
	
		
			
				|  |  | +    size_t peer_max_frame_size = result->max_frame_size;
 | 
	
		
			
				|  |  | +    max_frame_size = std::min<size_t>(peer_max_frame_size,
 | 
	
		
			
				|  |  | +                                      max_output_protected_frame_size == nullptr
 | 
	
		
			
				|  |  | +                                          ? kMaxFrameSize
 | 
	
		
			
				|  |  | +                                          : *max_output_protected_frame_size);
 | 
	
		
			
				|  |  | +    max_frame_size = std::max<size_t>(max_frame_size, kMinFrameSize);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  max_output_protected_frame_size = &max_frame_size;
 | 
	
		
			
				|  |  | +  gpr_log(GPR_DEBUG,
 | 
	
		
			
				|  |  | +          "After Frame Size Negotiation, maximum frame size used by frame "
 | 
	
		
			
				|  |  | +          "protector equals %zu",
 | 
	
		
			
				|  |  | +          *max_output_protected_frame_size);
 | 
	
		
			
				|  |  |    tsi_result ok = alts_zero_copy_grpc_protector_create(
 | 
	
		
			
				|  |  |        reinterpret_cast<const uint8_t*>(result->key_data),
 | 
	
		
			
				|  |  |        kAltsAes128GcmRekeyKeyLength, /*is_rekey=*/true, result->is_client,
 | 
	
	
		
			
				|  | @@ -288,6 +317,7 @@ tsi_result alts_tsi_handshaker_result_create(grpc_gcp_HandshakerResp* resp,
 | 
	
		
			
				|  |  |        static_cast<char*>(gpr_zalloc(peer_service_account.size + 1));
 | 
	
		
			
				|  |  |    memcpy(result->peer_identity, peer_service_account.data,
 | 
	
		
			
				|  |  |           peer_service_account.size);
 | 
	
		
			
				|  |  | +  result->max_frame_size = grpc_gcp_HandshakerResult_max_frame_size(hresult);
 | 
	
		
			
				|  |  |    upb::Arena rpc_versions_arena;
 | 
	
		
			
				|  |  |    bool serialized = grpc_gcp_rpc_protocol_versions_encode(
 | 
	
		
			
				|  |  |        peer_rpc_version, rpc_versions_arena.ptr(), &result->rpc_versions);
 | 
	
	
		
			
				|  | @@ -374,7 +404,8 @@ static tsi_result alts_tsi_handshaker_continue_handshaker_next(
 | 
	
		
			
				|  |  |          handshaker, channel, handshaker->handshaker_service_url,
 | 
	
		
			
				|  |  |          handshaker->interested_parties, handshaker->options,
 | 
	
		
			
				|  |  |          handshaker->target_name, grpc_cb, cb, user_data,
 | 
	
		
			
				|  |  | -        handshaker->client_vtable_for_testing, handshaker->is_client);
 | 
	
		
			
				|  |  | +        handshaker->client_vtable_for_testing, handshaker->is_client,
 | 
	
		
			
				|  |  | +        handshaker->max_frame_size);
 | 
	
		
			
				|  |  |      if (client == nullptr) {
 | 
	
		
			
				|  |  |        gpr_log(GPR_ERROR, "Failed to create ALTS handshaker client");
 | 
	
		
			
				|  |  |        return TSI_FAILED_PRECONDITION;
 | 
	
	
		
			
				|  | @@ -570,7 +601,8 @@ bool alts_tsi_handshaker_has_shutdown(alts_tsi_handshaker* handshaker) {
 | 
	
		
			
				|  |  |  tsi_result alts_tsi_handshaker_create(
 | 
	
		
			
				|  |  |      const grpc_alts_credentials_options* options, const char* target_name,
 | 
	
		
			
				|  |  |      const char* handshaker_service_url, bool is_client,
 | 
	
		
			
				|  |  | -    grpc_pollset_set* interested_parties, tsi_handshaker** self) {
 | 
	
		
			
				|  |  | +    grpc_pollset_set* interested_parties, tsi_handshaker** self,
 | 
	
		
			
				|  |  | +    size_t user_specified_max_frame_size) {
 | 
	
		
			
				|  |  |    if (handshaker_service_url == nullptr || self == nullptr ||
 | 
	
		
			
				|  |  |        options == nullptr || (is_client && target_name == nullptr)) {
 | 
	
		
			
				|  |  |      gpr_log(GPR_ERROR, "Invalid arguments to alts_tsi_handshaker_create()");
 | 
	
	
		
			
				|  | @@ -590,6 +622,9 @@ tsi_result alts_tsi_handshaker_create(
 | 
	
		
			
				|  |  |    handshaker->has_created_handshaker_client = false;
 | 
	
		
			
				|  |  |    handshaker->handshaker_service_url = gpr_strdup(handshaker_service_url);
 | 
	
		
			
				|  |  |    handshaker->options = grpc_alts_credentials_options_copy(options);
 | 
	
		
			
				|  |  | +  handshaker->max_frame_size = user_specified_max_frame_size != 0
 | 
	
		
			
				|  |  | +                                   ? user_specified_max_frame_size
 | 
	
		
			
				|  |  | +                                   : kMaxFrameSize;
 | 
	
		
			
				|  |  |    handshaker->base.vtable = handshaker->use_dedicated_cq
 | 
	
		
			
				|  |  |                                  ? &handshaker_vtable_dedicated
 | 
	
		
			
				|  |  |                                  : &handshaker_vtable;
 |