internal async Task InnerProcessRequestsAsync <TContext>(IHttpApplication <TContext> application) { // Start other three unidirectional streams here. var controlTask = CreateControlStream(application); var encoderTask = CreateEncoderStream(application); var decoderTask = CreateDecoderStream(application); try { while (true) { var streamContext = await _multiplexedContext.AcceptAsync(); if (streamContext == null || _haveSentGoAway) { break; } var quicStreamFeature = streamContext.Features.Get <IStreamDirectionFeature>(); var streamIdFeature = streamContext.Features.Get <IStreamIdFeature>(); Debug.Assert(quicStreamFeature != null); var httpConnectionContext = new Http3StreamContext { ConnectionId = streamContext.ConnectionId, StreamContext = streamContext, // TODO connection context is null here. Should we set it to anything? ServiceContext = _context.ServiceContext, ConnectionFeatures = streamContext.Features, MemoryPool = _context.MemoryPool, Transport = streamContext.Transport, TimeoutControl = _context.TimeoutControl, LocalEndPoint = streamContext.LocalEndPoint as IPEndPoint, RemoteEndPoint = streamContext.RemoteEndPoint as IPEndPoint }; if (!quicStreamFeature.CanWrite) { // Unidirectional stream var stream = new Http3ControlStream <TContext>(application, this, httpConnectionContext); ThreadPool.UnsafeQueueUserWorkItem(stream, preferLocal: false); } else { // Keep track of highest stream id seen for GOAWAY var streamId = streamIdFeature.StreamId; HighestStreamId = streamId; var http3Stream = new Http3Stream <TContext>(application, this, httpConnectionContext); var stream = http3Stream; lock (_streams) { _streams[streamId] = http3Stream; } KestrelEventSource.Log.RequestQueuedStart(stream, AspNetCore.Http.HttpProtocol.Http3); ThreadPool.UnsafeQueueUserWorkItem(stream, preferLocal: false); } } } finally { // Abort all streams as connection has shutdown. lock (_streams) { foreach (var stream in _streams.Values) { stream.Abort(new ConnectionAbortedException("Connection is shutting down.")); } } ControlStream?.Abort(new ConnectionAbortedException("Connection is shutting down.")); EncoderStream?.Abort(new ConnectionAbortedException("Connection is shutting down.")); DecoderStream?.Abort(new ConnectionAbortedException("Connection is shutting down.")); await controlTask; await encoderTask; await decoderTask; } }
public async Task ProcessRequestsAsync <TContext>(IHttpApplication <TContext> application) { var streamListenerFeature = Context.ConnectionFeatures.Get <IQuicStreamListenerFeature>(); // Start other three unidirectional streams here. var controlTask = CreateControlStream(application); var encoderTask = CreateEncoderStream(application); var decoderTask = CreateDecoderStream(application); try { while (true) { var connectionContext = await streamListenerFeature.AcceptAsync(); if (connectionContext == null || _haveSentGoAway) { break; } var httpConnectionContext = new HttpConnectionContext { ConnectionId = connectionContext.ConnectionId, ConnectionContext = connectionContext, Protocols = Context.Protocols, ServiceContext = Context.ServiceContext, ConnectionFeatures = connectionContext.Features, MemoryPool = Context.MemoryPool, Transport = connectionContext.Transport, TimeoutControl = Context.TimeoutControl, LocalEndPoint = connectionContext.LocalEndPoint as IPEndPoint, RemoteEndPoint = connectionContext.RemoteEndPoint as IPEndPoint }; var streamFeature = httpConnectionContext.ConnectionFeatures.Get <IQuicStreamFeature>(); if (!streamFeature.CanWrite) { // Unidirectional stream var stream = new Http3ControlStream <TContext>(application, this, httpConnectionContext); ThreadPool.UnsafeQueueUserWorkItem(stream, preferLocal: false); } else { // Keep track of highest stream id seen for GOAWAY var streamId = streamFeature.StreamId; HighestStreamId = streamId; var http3Stream = new Http3Stream <TContext>(application, this, httpConnectionContext); var stream = http3Stream; _streams[streamId] = http3Stream; ThreadPool.UnsafeQueueUserWorkItem(stream, preferLocal: false); } } } finally { // Abort all streams as connection has shutdown. foreach (var stream in _streams.Values) { stream.Abort(new ConnectionAbortedException("Connection is shutting down.")); } ControlStream.Abort(new ConnectionAbortedException("Connection is shutting down.")); EncoderStream.Abort(new ConnectionAbortedException("Connection is shutting down.")); DecoderStream.Abort(new ConnectionAbortedException("Connection is shutting down.")); await controlTask; await encoderTask; await decoderTask; } }