| 
					
				 | 
			
			
				@@ -317,6 +317,17 @@ static void maybe_flush_read(stream_obj* s) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static void read_grpc_header(stream_obj* s) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  s->state.rs.read_buffer = s->state.rs.grpc_header_bytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  s->state.rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  s->state.rs.received_bytes = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  s->state.rs.compressed = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            s->state.rs.remaining_bytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+  s->state.pending_read_from_cronet = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static grpc_error* make_error_with_desc(int error_code, const char* desc) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   grpc_error* error = GRPC_ERROR_CREATE_FROM_COPIED_STRING(desc); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   error = grpc_error_set_int(error, GRPC_ERROR_INT_GRPC_STATUS, error_code); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -555,6 +566,11 @@ static void on_response_headers_received( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   for (size_t i = 0; i < headers->count; i++) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if (0 == strcmp("grpc-status", headers->headers[i].key)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       on_response_trailers_received(stream, headers); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      /* Do an extra read for a trailer-only stream with grpc_status = 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+       to trigger on_succeeded() callback */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      if (0 == strcmp(headers->headers[i].value, "0")) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        read_grpc_header(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -567,14 +583,7 @@ static void on_response_headers_received( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     /* Do an extra read to trigger on_succeeded() callback in case connection 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				      is closed */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     GPR_ASSERT(s->state.rs.length_field_received == false); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    s->state.rs.read_buffer = s->state.rs.grpc_header_bytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    s->state.rs.compressed = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    s->state.rs.received_bytes = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    s->state.rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    bidirectional_stream_read(s->cbs, s->state.rs.read_buffer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                              s->state.rs.remaining_bytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    s->state.pending_read_from_cronet = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    read_grpc_header(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   gpr_mu_unlock(&s->mu); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   execute_from_storage(s); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1260,17 +1269,10 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           oas->state.state_op_done[OP_RECV_MESSAGE] = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           /* Extra read to trigger on_succeed */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          stream_state->rs.received_bytes = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          stream_state->rs.compressed = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           stream_state->rs.length_field_received = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           stream_state->state_op_done[OP_READ_REQ_MADE] = 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				               true; /* Indicates that at least one read request has been made */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                    stream_state->rs.remaining_bytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-          stream_state->pending_read_from_cronet = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+          read_grpc_header(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				           result = ACTION_TAKEN_NO_CALLBACK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       } else if (stream_state->rs.remaining_bytes == 0) { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1316,15 +1318,8 @@ static enum e_op_result execute_stream_op(struct op_and_state* oas) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       oas->state.state_op_done[OP_RECV_MESSAGE] = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       /* Do an extra read to trigger on_succeeded() callback in case connection 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				          is closed */ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      stream_state->rs.read_buffer = stream_state->rs.grpc_header_bytes; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      stream_state->rs.compressed = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      stream_state->rs.received_bytes = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      stream_state->rs.remaining_bytes = GRPC_HEADER_SIZE_IN_BYTES; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       stream_state->rs.length_field_received = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      CRONET_LOG(GPR_DEBUG, "bidirectional_stream_read(%p)", s->cbs); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      bidirectional_stream_read(s->cbs, stream_state->rs.read_buffer, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                stream_state->rs.remaining_bytes); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-      stream_state->pending_read_from_cronet = true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+      read_grpc_header(s); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				       result = ACTION_TAKEN_NO_CALLBACK; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				   } else if (stream_op->recv_trailing_metadata && 
			 |