|  | @@ -56,9 +56,9 @@ typedef struct http_connect_handshaker {
 | 
	
		
			
				|  |  |    void* user_data;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    // Objects for processing the HTTP CONNECT request and response.
 | 
	
		
			
				|  |  | -  gpr_slice_buffer request_buffer;
 | 
	
		
			
				|  |  | +  gpr_slice_buffer write_buffer;
 | 
	
		
			
				|  |  | +  gpr_slice_buffer* read_buffer;
 | 
	
		
			
				|  |  |    grpc_closure request_done_closure;
 | 
	
		
			
				|  |  | -  gpr_slice_buffer response_buffer;
 | 
	
		
			
				|  |  |    grpc_closure response_read_closure;
 | 
	
		
			
				|  |  |    grpc_http_parser http_parser;
 | 
	
		
			
				|  |  |    grpc_http_response http_response;
 | 
	
	
		
			
				|  | @@ -70,10 +70,11 @@ static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |    http_connect_handshaker* h = arg;
 | 
	
		
			
				|  |  |    if (error != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  |      // If the write failed, invoke the callback immediately with the error.
 | 
	
		
			
				|  |  | -    h->cb(exec_ctx, h->endpoint, h->args, h->user_data, GRPC_ERROR_REF(error));
 | 
	
		
			
				|  |  | +    h->cb(exec_ctx, h->endpoint, h->args, h->read_buffer, h->user_data,
 | 
	
		
			
				|  |  | +          GRPC_ERROR_REF(error));
 | 
	
		
			
				|  |  |    } else {
 | 
	
		
			
				|  |  |      // Otherwise, read the response.
 | 
	
		
			
				|  |  | -    grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer,
 | 
	
		
			
				|  |  | +    grpc_endpoint_read(exec_ctx, h->endpoint, h->read_buffer,
 | 
	
		
			
				|  |  |                         &h->response_read_closure);
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -87,12 +88,29 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |      goto done;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    // Add buffer to parser.
 | 
	
		
			
				|  |  | -  for (size_t i = 0; i < h->response_buffer.count; ++i) {
 | 
	
		
			
				|  |  | -    if (GPR_SLICE_LENGTH(h->response_buffer.slices[i]) > 0) {
 | 
	
		
			
				|  |  | +  for (size_t i = 0; i < h->read_buffer->count; ++i) {
 | 
	
		
			
				|  |  | +    if (GPR_SLICE_LENGTH(h->read_buffer->slices[i]) > 0) {
 | 
	
		
			
				|  |  | +      size_t body_start_offset = 0;
 | 
	
		
			
				|  |  |        error = grpc_http_parser_parse(
 | 
	
		
			
				|  |  | -          &h->http_parser, h->response_buffer.slices[i]);
 | 
	
		
			
				|  |  | +          &h->http_parser, h->read_buffer->slices[i], &body_start_offset);
 | 
	
		
			
				|  |  |        if (error != GRPC_ERROR_NONE)
 | 
	
		
			
				|  |  |          goto done;
 | 
	
		
			
				|  |  | +      if (h->http_parser.state == GRPC_HTTP_BODY) {
 | 
	
		
			
				|  |  | +        // Remove the data we've already read from the read buffer,
 | 
	
		
			
				|  |  | +        // leaving only the leftover bytes (if any).
 | 
	
		
			
				|  |  | +        gpr_slice_buffer tmp_buffer;
 | 
	
		
			
				|  |  | +        gpr_slice_buffer_init(&tmp_buffer);
 | 
	
		
			
				|  |  | +        if (body_start_offset < GPR_SLICE_LENGTH(h->read_buffer->slices[i])) {
 | 
	
		
			
				|  |  | +          gpr_slice_buffer_add(&tmp_buffer,
 | 
	
		
			
				|  |  | +                               gpr_slice_split_tail(&h->read_buffer->slices[i],
 | 
	
		
			
				|  |  | +                                                    body_start_offset));
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +        gpr_slice_buffer_addn(&tmp_buffer, &h->read_buffer->slices[i + 1],
 | 
	
		
			
				|  |  | +                              h->read_buffer->count - i - 1);
 | 
	
		
			
				|  |  | +        gpr_slice_buffer_swap(h->read_buffer, &tmp_buffer);
 | 
	
		
			
				|  |  | +        gpr_slice_buffer_destroy(&tmp_buffer);
 | 
	
		
			
				|  |  | +        break;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    // If we're not done reading the response, read more data.
 | 
	
	
		
			
				|  | @@ -107,8 +125,8 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |    // complete (e.g., handling chunked transfer encoding or looking
 | 
	
		
			
				|  |  |    // at the Content-Length: header).
 | 
	
		
			
				|  |  |    if (h->http_parser.state != GRPC_HTTP_BODY) {
 | 
	
		
			
				|  |  | -    gpr_slice_buffer_reset_and_unref(&h->response_buffer);
 | 
	
		
			
				|  |  | -    grpc_endpoint_read(exec_ctx, h->endpoint, &h->response_buffer,
 | 
	
		
			
				|  |  | +    gpr_slice_buffer_reset_and_unref(h->read_buffer);
 | 
	
		
			
				|  |  | +    grpc_endpoint_read(exec_ctx, h->endpoint, h->read_buffer,
 | 
	
		
			
				|  |  |                         &h->response_read_closure);
 | 
	
		
			
				|  |  |      return;
 | 
	
		
			
				|  |  |    }
 | 
	
	
		
			
				|  | @@ -122,7 +140,7 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |   done:
 | 
	
		
			
				|  |  |    // Invoke handshake-done callback.
 | 
	
		
			
				|  |  | -  h->cb(exec_ctx, h->endpoint, h->args, h->user_data, error);
 | 
	
		
			
				|  |  | +  h->cb(exec_ctx, h->endpoint, h->args, h->read_buffer, h->user_data, error);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  //
 | 
	
	
		
			
				|  | @@ -134,8 +152,7 @@ static void http_connect_handshaker_destroy(grpc_exec_ctx* exec_ctx,
 | 
	
		
			
				|  |  |    http_connect_handshaker* h = (http_connect_handshaker*)handshaker;
 | 
	
		
			
				|  |  |    gpr_free(h->proxy_server);
 | 
	
		
			
				|  |  |    gpr_free(h->server_name);
 | 
	
		
			
				|  |  | -  gpr_slice_buffer_destroy(&h->request_buffer);
 | 
	
		
			
				|  |  | -  gpr_slice_buffer_destroy(&h->response_buffer);
 | 
	
		
			
				|  |  | +  gpr_slice_buffer_destroy(&h->write_buffer);
 | 
	
		
			
				|  |  |    grpc_http_parser_destroy(&h->http_parser);
 | 
	
		
			
				|  |  |    grpc_http_response_destroy(&h->http_response);
 | 
	
		
			
				|  |  |    gpr_free(h);
 | 
	
	
		
			
				|  | @@ -148,7 +165,8 @@ static void http_connect_handshaker_shutdown(grpc_exec_ctx* exec_ctx,
 | 
	
		
			
				|  |  |  // FIXME BEFORE MERGING: apply deadline
 | 
	
		
			
				|  |  |  static void http_connect_handshaker_do_handshake(
 | 
	
		
			
				|  |  |      grpc_exec_ctx* exec_ctx, grpc_handshaker* handshaker,
 | 
	
		
			
				|  |  | -    grpc_endpoint* endpoint, grpc_channel_args* args, gpr_timespec deadline,
 | 
	
		
			
				|  |  | +    grpc_endpoint* endpoint, grpc_channel_args* args,
 | 
	
		
			
				|  |  | +    gpr_slice_buffer* read_buffer, gpr_timespec deadline,
 | 
	
		
			
				|  |  |      grpc_tcp_server_acceptor* acceptor, grpc_handshaker_done_cb cb,
 | 
	
		
			
				|  |  |      void* user_data) {
 | 
	
		
			
				|  |  |    http_connect_handshaker* h = (http_connect_handshaker*)handshaker;
 | 
	
	
		
			
				|  | @@ -158,9 +176,9 @@ static void http_connect_handshaker_do_handshake(
 | 
	
		
			
				|  |  |    h->cb = cb;
 | 
	
		
			
				|  |  |    h->user_data = user_data;
 | 
	
		
			
				|  |  |    // Initialize fields.
 | 
	
		
			
				|  |  | -  gpr_slice_buffer_init(&h->request_buffer);
 | 
	
		
			
				|  |  | +  gpr_slice_buffer_init(&h->write_buffer);
 | 
	
		
			
				|  |  | +  h->read_buffer = read_buffer;
 | 
	
		
			
				|  |  |    grpc_closure_init(&h->request_done_closure, on_write_done, h);
 | 
	
		
			
				|  |  | -  gpr_slice_buffer_init(&h->response_buffer);
 | 
	
		
			
				|  |  |    grpc_closure_init(&h->response_read_closure, on_read_done, h);
 | 
	
		
			
				|  |  |    grpc_http_parser_init(&h->http_parser, GRPC_HTTP_RESPONSE,
 | 
	
		
			
				|  |  |                          &h->http_response);
 | 
	
	
		
			
				|  | @@ -174,8 +192,8 @@ static void http_connect_handshaker_do_handshake(
 | 
	
		
			
				|  |  |    request.http.path = h->server_name;
 | 
	
		
			
				|  |  |    request.handshaker = &grpc_httpcli_plaintext;
 | 
	
		
			
				|  |  |    gpr_slice request_slice = grpc_httpcli_format_connect_request(&request);
 | 
	
		
			
				|  |  | -  gpr_slice_buffer_add(&h->request_buffer, request_slice);
 | 
	
		
			
				|  |  | -  grpc_endpoint_write(exec_ctx, endpoint, &h->request_buffer,
 | 
	
		
			
				|  |  | +  gpr_slice_buffer_add(&h->write_buffer, request_slice);
 | 
	
		
			
				|  |  | +  grpc_endpoint_write(exec_ctx, endpoint, &h->write_buffer,
 | 
	
		
			
				|  |  |                        &h->request_done_closure);
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 |