private async Task ProcessRequestsAsync <TContext>(IHttpApplication <TContext> httpApplication) { try { KestrelEventSource.Log.ConnectionStart(this); AdaptedPipeline adaptedPipeline = null; var adaptedPipelineTask = Task.CompletedTask; var transport = _context.Transport; var application = _context.Application; if (_context.ConnectionAdapters.Count > 0) { adaptedPipeline = new AdaptedPipeline(transport, application, new Pipe(AdaptedInputPipeOptions), new Pipe(AdaptedOutputPipeOptions)); transport = adaptedPipeline; } // _http1Connection must be initialized before adding the connection to the connection manager CreateHttp1Connection(httpApplication, transport, application); // _http2Connection must be initialized before yielding control to the transport thread, // to prevent a race condition where _http2Connection.Abort() is called just as // _http2Connection is about to be initialized. CreateHttp2Connection(httpApplication, transport, application); // Do this before the first await so we don't yield control to the transport until we've // added the connection to the connection manager _context.ServiceContext.ConnectionManager.AddConnection(_context.HttpConnectionId, this); _lastTimestamp = _context.ServiceContext.SystemClock.UtcNow.Ticks; _http1Connection.ConnectionFeatures.Set <IConnectionTimeoutFeature>(this); _http2Connection.ConnectionFeatures.Set <IConnectionTimeoutFeature>(this); if (adaptedPipeline != null) { // Stream can be null here and run async will close the connection in that case var stream = await ApplyConnectionAdaptersAsync(); adaptedPipelineTask = adaptedPipeline.RunAsync(stream); } var protocol = SelectProtocol(); if (protocol == HttpProtocols.None) { Abort(ex: null); } // One of these has to run even if no protocol was selected so the abort propagates and everything completes properly if (protocol == HttpProtocols.Http2 && Interlocked.CompareExchange(ref _http2ConnectionState, Http2ConnectionStarted, Http2ConnectionNotStarted) == Http2ConnectionNotStarted) { await _http2Connection.ProcessAsync(httpApplication); } else { await _http1Connection.ProcessRequestsAsync(); } await adaptedPipelineTask; await _socketClosedTcs.Task; } catch (Exception ex) { Log.LogError(0, ex, $"Unexpected exception in {nameof(HttpConnection)}.{nameof(ProcessRequestsAsync)}."); } finally { _context.ServiceContext.ConnectionManager.RemoveConnection(_context.HttpConnectionId); DisposeAdaptedConnections(); if (_http1Connection.IsUpgraded) { _context.ServiceContext.ConnectionManager.UpgradedConnectionCount.ReleaseOne(); } KestrelEventSource.Log.ConnectionStop(this); } }