|  | @@ -31,8 +31,10 @@
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -#include <grpc/support/alloc.h>
 | 
	
		
			
				|  |  |  #include <grpc++/impl/call.h>
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#include <grpc/support/alloc.h>
 | 
	
		
			
				|  |  | +#include <grpc++/byte_buffer.h>
 | 
	
		
			
				|  |  |  #include <grpc++/client_context.h>
 | 
	
		
			
				|  |  |  #include <grpc++/channel_interface.h>
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -48,9 +50,11 @@ CallOpBuffer::CallOpBuffer()
 | 
	
		
			
				|  |  |        recv_initial_metadata_(nullptr),
 | 
	
		
			
				|  |  |        recv_initial_metadata_arr_{0, 0, nullptr},
 | 
	
		
			
				|  |  |        send_message_(nullptr),
 | 
	
		
			
				|  |  | -      send_message_buf_(nullptr),
 | 
	
		
			
				|  |  | +      send_message_buffer_(nullptr),
 | 
	
		
			
				|  |  | +      send_buf_(nullptr),
 | 
	
		
			
				|  |  |        recv_message_(nullptr),
 | 
	
		
			
				|  |  | -      recv_message_buf_(nullptr),
 | 
	
		
			
				|  |  | +      recv_message_buffer_(nullptr),
 | 
	
		
			
				|  |  | +      recv_buf_(nullptr),
 | 
	
		
			
				|  |  |        client_send_close_(false),
 | 
	
		
			
				|  |  |        recv_trailing_metadata_(nullptr),
 | 
	
		
			
				|  |  |        recv_status_(nullptr),
 | 
	
	
		
			
				|  | @@ -74,18 +78,20 @@ void CallOpBuffer::Reset(void* next_return_tag) {
 | 
	
		
			
				|  |  |    recv_initial_metadata_ = nullptr;
 | 
	
		
			
				|  |  |    recv_initial_metadata_arr_.count = 0;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  send_message_ = nullptr;
 | 
	
		
			
				|  |  | -  if (send_message_buf_) {
 | 
	
		
			
				|  |  | -    grpc_byte_buffer_destroy(send_message_buf_);
 | 
	
		
			
				|  |  | -    send_message_buf_ = nullptr;
 | 
	
		
			
				|  |  | +  if (send_buf_ && send_message_) {
 | 
	
		
			
				|  |  | +    grpc_byte_buffer_destroy(send_buf_);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  send_message_ = nullptr;
 | 
	
		
			
				|  |  | +  send_message_buffer_ = nullptr;
 | 
	
		
			
				|  |  | +  send_buf_ = nullptr;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  recv_message_ = nullptr;
 | 
	
		
			
				|  |  |    got_message = false;
 | 
	
		
			
				|  |  | -  if (recv_message_buf_) {
 | 
	
		
			
				|  |  | -    grpc_byte_buffer_destroy(recv_message_buf_);
 | 
	
		
			
				|  |  | -    recv_message_buf_ = nullptr;
 | 
	
		
			
				|  |  | +  if (recv_buf_ && recv_message_) {
 | 
	
		
			
				|  |  | +    grpc_byte_buffer_destroy(recv_buf_);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | +  recv_message_ = nullptr;
 | 
	
		
			
				|  |  | +  recv_message_buffer_ = nullptr;
 | 
	
		
			
				|  |  | +  recv_buf_ = nullptr;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    client_send_close_ = false;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -106,11 +112,11 @@ CallOpBuffer::~CallOpBuffer() {
 | 
	
		
			
				|  |  |    gpr_free(status_details_);
 | 
	
		
			
				|  |  |    gpr_free(recv_initial_metadata_arr_.metadata);
 | 
	
		
			
				|  |  |    gpr_free(recv_trailing_metadata_arr_.metadata);
 | 
	
		
			
				|  |  | -  if (recv_message_buf_) {
 | 
	
		
			
				|  |  | -    grpc_byte_buffer_destroy(recv_message_buf_);
 | 
	
		
			
				|  |  | +  if (recv_buf_ && recv_message_) {
 | 
	
		
			
				|  |  | +    grpc_byte_buffer_destroy(recv_buf_);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (send_message_buf_) {
 | 
	
		
			
				|  |  | -    grpc_byte_buffer_destroy(send_message_buf_);
 | 
	
		
			
				|  |  | +  if (send_buf_ && send_message_) {
 | 
	
		
			
				|  |  | +    grpc_byte_buffer_destroy(send_buf_);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -166,11 +172,19 @@ void CallOpBuffer::AddSendMessage(const grpc::protobuf::Message& message) {
 | 
	
		
			
				|  |  |    send_message_ = &message;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +void CallOpBuffer::AddSendMessage(const ByteBuffer& message) {
 | 
	
		
			
				|  |  | +  send_message_buffer_ = &message;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void CallOpBuffer::AddRecvMessage(grpc::protobuf::Message* message) {
 | 
	
		
			
				|  |  |    recv_message_ = message;
 | 
	
		
			
				|  |  |    recv_message_->Clear();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +void CallOpBuffer::AddRecvMessage(ByteBuffer* message) {
 | 
	
		
			
				|  |  | +  recv_message_buffer_ = message;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  void CallOpBuffer::AddClientSendClose() { client_send_close_ = true; }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  void CallOpBuffer::AddServerRecvClose(bool* cancelled) {
 | 
	
	
		
			
				|  | @@ -206,19 +220,23 @@ void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) {
 | 
	
		
			
				|  |  |      ops[*nops].data.recv_initial_metadata = &recv_initial_metadata_arr_;
 | 
	
		
			
				|  |  |      (*nops)++;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (send_message_) {
 | 
	
		
			
				|  |  | -    bool success = SerializeProto(*send_message_, &send_message_buf_);
 | 
	
		
			
				|  |  | -    if (!success) {
 | 
	
		
			
				|  |  | -      abort();
 | 
	
		
			
				|  |  | -      // TODO handle parse failure
 | 
	
		
			
				|  |  | +  if (send_message_ || send_message_buffer_) {
 | 
	
		
			
				|  |  | +    if (send_message_) {
 | 
	
		
			
				|  |  | +      bool success = SerializeProto(*send_message_, &send_buf_);
 | 
	
		
			
				|  |  | +      if (!success) {
 | 
	
		
			
				|  |  | +        abort();
 | 
	
		
			
				|  |  | +        // TODO handle parse failure
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      send_buf_ = send_message_buffer_->buffer();
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |      ops[*nops].op = GRPC_OP_SEND_MESSAGE;
 | 
	
		
			
				|  |  | -    ops[*nops].data.send_message = send_message_buf_;
 | 
	
		
			
				|  |  | +    ops[*nops].data.send_message = send_buf_;
 | 
	
		
			
				|  |  |      (*nops)++;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -  if (recv_message_) {
 | 
	
		
			
				|  |  | +  if (recv_message_ || recv_message_buffer_) {
 | 
	
		
			
				|  |  |      ops[*nops].op = GRPC_OP_RECV_MESSAGE;
 | 
	
		
			
				|  |  | -    ops[*nops].data.recv_message = &recv_message_buf_;
 | 
	
		
			
				|  |  | +    ops[*nops].data.recv_message = &recv_buf_;
 | 
	
		
			
				|  |  |      (*nops)++;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (client_send_close_) {
 | 
	
	
		
			
				|  | @@ -256,9 +274,11 @@ void CallOpBuffer::FillOps(grpc_op* ops, size_t* nops) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  bool CallOpBuffer::FinalizeResult(void** tag, bool* status) {
 | 
	
		
			
				|  |  |    // Release send buffers.
 | 
	
		
			
				|  |  | -  if (send_message_buf_) {
 | 
	
		
			
				|  |  | -    grpc_byte_buffer_destroy(send_message_buf_);
 | 
	
		
			
				|  |  | -    send_message_buf_ = nullptr;
 | 
	
		
			
				|  |  | +  if (send_buf_ && send_message_) {
 | 
	
		
			
				|  |  | +    if (send_message_) {
 | 
	
		
			
				|  |  | +      grpc_byte_buffer_destroy(send_buf_);
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    send_buf_ = nullptr;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    if (initial_metadata_) {
 | 
	
		
			
				|  |  |      gpr_free(initial_metadata_);
 | 
	
	
		
			
				|  | @@ -275,12 +295,16 @@ bool CallOpBuffer::FinalizeResult(void** tag, bool* status) {
 | 
	
		
			
				|  |  |      FillMetadataMap(&recv_initial_metadata_arr_, recv_initial_metadata_);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    // Parse received message if any.
 | 
	
		
			
				|  |  | -  if (recv_message_) {
 | 
	
		
			
				|  |  | -    if (recv_message_buf_) {
 | 
	
		
			
				|  |  | +  if (recv_message_ || recv_message_buffer_) {
 | 
	
		
			
				|  |  | +    if (recv_buf_) {
 | 
	
		
			
				|  |  |        got_message = *status;
 | 
	
		
			
				|  |  | -      *status = *status && DeserializeProto(recv_message_buf_, recv_message_);
 | 
	
		
			
				|  |  | -      grpc_byte_buffer_destroy(recv_message_buf_);
 | 
	
		
			
				|  |  | -      recv_message_buf_ = nullptr;
 | 
	
		
			
				|  |  | +      if (recv_message_) {
 | 
	
		
			
				|  |  | +        *status = *status && DeserializeProto(recv_buf_, recv_message_);
 | 
	
		
			
				|  |  | +        grpc_byte_buffer_destroy(recv_buf_);
 | 
	
		
			
				|  |  | +      } else {
 | 
	
		
			
				|  |  | +        recv_message_buffer_->set_buffer(recv_buf_);
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +      recv_buf_ = nullptr;
 | 
	
		
			
				|  |  |      } else {
 | 
	
		
			
				|  |  |        // Read failed
 | 
	
		
			
				|  |  |        got_message = false;
 |