Plumbed read_buffer through and fixed leftover bytes problem.
diff --git a/src/core/ext/client_config/http_connect_handshaker.c b/src/core/ext/client_config/http_connect_handshaker.c
index 25851c2..e6660fe 100644
--- a/src/core/ext/client_config/http_connect_handshaker.c
+++ b/src/core/ext/client_config/http_connect_handshaker.c
@@ -56,9 +56,9 @@
   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 @@
   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 @@
     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 @@
   // 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 @@
   }
  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 @@
   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 @@
 // 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 @@
   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 @@
   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);
 }