|  | @@ -106,6 +106,31 @@ static void cleanup_args_for_failure_locked(
 | 
	
		
			
				|  |  |    handshaker->args->args = NULL;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +// If the handshake failed or we're shutting down, clean up and invoke the
 | 
	
		
			
				|  |  | +// callback with the error.
 | 
	
		
			
				|  |  | +static void handshake_failed_locked(grpc_exec_ctx* exec_ctx,
 | 
	
		
			
				|  |  | +                                    http_connect_handshaker* handshaker,
 | 
	
		
			
				|  |  | +                                    grpc_error* error) {
 | 
	
		
			
				|  |  | +  if (error == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | +    // If we were shut down after an endpoint operation succeeded but
 | 
	
		
			
				|  |  | +    // before the endpoint callback was invoked, we need to generate our
 | 
	
		
			
				|  |  | +    // own error.
 | 
	
		
			
				|  |  | +    error = GRPC_ERROR_CREATE("Handshaker shutdown");
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  if (!handshaker->shutdown) {
 | 
	
		
			
				|  |  | +    // TODO(ctiller): It is currently necessary to shutdown endpoints
 | 
	
		
			
				|  |  | +    // before destroying them, even if we know that there are no
 | 
	
		
			
				|  |  | +    // pending read/write callbacks.  This should be fixed, at which
 | 
	
		
			
				|  |  | +    // point this can be removed.
 | 
	
		
			
				|  |  | +    grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint);
 | 
	
		
			
				|  |  | +    // Not shutting down, so the handshake failed.  Clean up before
 | 
	
		
			
				|  |  | +    // invoking the callback.
 | 
	
		
			
				|  |  | +    cleanup_args_for_failure_locked(handshaker);
 | 
	
		
			
				|  |  | +  }
 | 
	
		
			
				|  |  | +  // Invoke callback.
 | 
	
		
			
				|  |  | +  grpc_exec_ctx_sched(exec_ctx, handshaker->on_handshake_done, error, NULL);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  // Callback invoked when finished writing HTTP CONNECT request.
 | 
	
		
			
				|  |  |  static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |                            grpc_error* error) {
 | 
	
	
		
			
				|  | @@ -114,25 +139,7 @@ static void on_write_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |    if (error != GRPC_ERROR_NONE || handshaker->shutdown) {
 | 
	
		
			
				|  |  |      // If the write failed or we're shutting down, clean up and invoke the
 | 
	
		
			
				|  |  |      // callback with the error.
 | 
	
		
			
				|  |  | -    if (error == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | -      // If we were shut down after the write succeeded but before this
 | 
	
		
			
				|  |  | -      // callback was invoked, we need to generate our own error.
 | 
	
		
			
				|  |  | -      error = GRPC_ERROR_CREATE("Handshaker shutdown");
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      GRPC_ERROR_REF(error);  // Take ref for the handshake-done callback.
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (!handshaker->shutdown) {
 | 
	
		
			
				|  |  | -      // TODO(ctiller): It is currently necessary to shutdown endpoints
 | 
	
		
			
				|  |  | -      // before destroying them, even if we know that there are no
 | 
	
		
			
				|  |  | -      // pending read/write callbacks.  This should be fixed, at which
 | 
	
		
			
				|  |  | -      // point this can be removed.
 | 
	
		
			
				|  |  | -      grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint);
 | 
	
		
			
				|  |  | -      // Not shutting down, so the write failed.  Clean up before
 | 
	
		
			
				|  |  | -      // invoking the callback.
 | 
	
		
			
				|  |  | -      cleanup_args_for_failure_locked(handshaker);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    // Invoke callback.
 | 
	
		
			
				|  |  | -    grpc_exec_ctx_sched(exec_ctx, handshaker->on_handshake_done, error, NULL);
 | 
	
		
			
				|  |  | +    handshake_failed_locked(exec_ctx, handshaker, GRPC_ERROR_REF(error));
 | 
	
		
			
				|  |  |      gpr_mu_unlock(&handshaker->mu);
 | 
	
		
			
				|  |  |      http_connect_handshaker_unref(exec_ctx, handshaker);
 | 
	
		
			
				|  |  |    } else {
 | 
	
	
		
			
				|  | @@ -151,25 +158,9 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |    http_connect_handshaker* handshaker = arg;
 | 
	
		
			
				|  |  |    gpr_mu_lock(&handshaker->mu);
 | 
	
		
			
				|  |  |    if (error != GRPC_ERROR_NONE || handshaker->shutdown) {
 | 
	
		
			
				|  |  | -    // If the write failed or we're shutting down, clean up and invoke the
 | 
	
		
			
				|  |  | +    // If the read failed or we're shutting down, clean up and invoke the
 | 
	
		
			
				|  |  |      // callback with the error.
 | 
	
		
			
				|  |  | -    if (error == GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | -      // If we were shut down after the write succeeded but before this
 | 
	
		
			
				|  |  | -      // callback was invoked, we need to generate our own error.
 | 
	
		
			
				|  |  | -      error = GRPC_ERROR_CREATE("Handshaker shutdown");
 | 
	
		
			
				|  |  | -    } else {
 | 
	
		
			
				|  |  | -      GRPC_ERROR_REF(error);  // Take ref for the handshake-done callback.
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | -    if (!handshaker->shutdown) {
 | 
	
		
			
				|  |  | -      // TODO(ctiller): It is currently necessary to shutdown endpoints
 | 
	
		
			
				|  |  | -      // before destroying them, even if we know that there are no
 | 
	
		
			
				|  |  | -      // pending read/write callbacks.  This should be fixed, at which
 | 
	
		
			
				|  |  | -      // point this can be removed.
 | 
	
		
			
				|  |  | -      grpc_endpoint_shutdown(exec_ctx, handshaker->args->endpoint);
 | 
	
		
			
				|  |  | -      // Not shutting down, so the write failed.  Clean up before
 | 
	
		
			
				|  |  | -      // invoking the callback.
 | 
	
		
			
				|  |  | -      cleanup_args_for_failure_locked(handshaker);
 | 
	
		
			
				|  |  | -    }
 | 
	
		
			
				|  |  | +    handshake_failed_locked(exec_ctx, handshaker, GRPC_ERROR_REF(error));
 | 
	
		
			
				|  |  |      goto done;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    // Add buffer to parser.
 | 
	
	
		
			
				|  | @@ -179,7 +170,10 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |        error = grpc_http_parser_parse(&handshaker->http_parser,
 | 
	
		
			
				|  |  |                                       handshaker->args->read_buffer->slices[i],
 | 
	
		
			
				|  |  |                                       &body_start_offset);
 | 
	
		
			
				|  |  | -      if (error != GRPC_ERROR_NONE) goto done;
 | 
	
		
			
				|  |  | +      if (error != GRPC_ERROR_NONE) {
 | 
	
		
			
				|  |  | +        handshake_failed_locked(exec_ctx, handshaker, error);
 | 
	
		
			
				|  |  | +        goto done;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  |        if (handshaker->http_parser.state == GRPC_HTTP_BODY) {
 | 
	
		
			
				|  |  |          // Remove the data we've already read from the read buffer,
 | 
	
		
			
				|  |  |          // leaving only the leftover bytes (if any).
 | 
	
	
		
			
				|  | @@ -228,10 +222,12 @@ static void on_read_done(grpc_exec_ctx* exec_ctx, void* arg,
 | 
	
		
			
				|  |  |                   handshaker->http_response.status);
 | 
	
		
			
				|  |  |      error = GRPC_ERROR_CREATE(msg);
 | 
	
		
			
				|  |  |      gpr_free(msg);
 | 
	
		
			
				|  |  | +    handshake_failed_locked(exec_ctx, handshaker, error);
 | 
	
		
			
				|  |  | +    goto done;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  | -done:
 | 
	
		
			
				|  |  | -  // Invoke handshake-done callback.
 | 
	
		
			
				|  |  | +  // Success.  Invoke handshake-done callback.
 | 
	
		
			
				|  |  |    grpc_exec_ctx_sched(exec_ctx, handshaker->on_handshake_done, error, NULL);
 | 
	
		
			
				|  |  | +done:
 | 
	
		
			
				|  |  |    gpr_mu_unlock(&handshaker->mu);
 | 
	
		
			
				|  |  |    http_connect_handshaker_unref(exec_ctx, handshaker);
 | 
	
		
			
				|  |  |  }
 |