public async Task ProcessRequestAsync <TContext>(IHttpApplication <TContext> application) where TContext : notnull { try { var streamType = await TryReadStreamIdAsync(); if (streamType == -1) { return; } if (streamType == ControlStream) { if (!_http3Connection.SetInboundControlStream(this)) { // https://quicwg.org/base-drafts/draft-ietf-quic-http.html#section-6.2.1 throw new Http3ConnectionErrorException(CoreStrings.FormatHttp3ControlStreamErrorMultipleInboundStreams("control"), Http3ErrorCode.StreamCreationError); } await HandleControlStream(); } else if (streamType == EncoderStream) { if (!_http3Connection.SetInboundEncoderStream(this)) { // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#section-4.2 throw new Http3ConnectionErrorException(CoreStrings.FormatHttp3ControlStreamErrorMultipleInboundStreams("encoder"), Http3ErrorCode.StreamCreationError); } await HandleEncodingDecodingTask(); } else if (streamType == DecoderStream) { if (!_http3Connection.SetInboundDecoderStream(this)) { // https://quicwg.org/base-drafts/draft-ietf-quic-qpack.html#section-4.2 throw new Http3ConnectionErrorException(CoreStrings.FormatHttp3ControlStreamErrorMultipleInboundStreams("decoder"), Http3ErrorCode.StreamCreationError); } await HandleEncodingDecodingTask(); } else { // TODO Close the control stream as it's unexpected. } } catch (Http3ConnectionErrorException ex) { Log.Http3ConnectionError(_http3Connection.ConnectionId, ex); _http3Connection.Abort(new ConnectionAbortedException(ex.Message, ex), ex.ErrorCode); } }
public async Task ProcessRequestAsync <TContext>(IHttpApplication <TContext> application) where TContext : notnull { Exception?error = null; try { while (_isClosed == 0) { var result = await Input.ReadAsync(); var readableBuffer = result.Buffer; var consumed = readableBuffer.Start; var examined = readableBuffer.End; try { if (!readableBuffer.IsEmpty) { while (Http3FrameReader.TryReadFrame(ref readableBuffer, _incomingFrame, out var framePayload)) { Log.Http3FrameReceived(ConnectionId, _streamIdFeature.StreamId, _incomingFrame); consumed = examined = framePayload.End; await ProcessHttp3Stream(application, framePayload); } } if (result.IsCompleted) { await OnEndStreamReceived(); return; } } finally { Input.AdvanceTo(consumed, examined); } } } // catch ConnectionResetException here? catch (Http3StreamErrorException ex) { error = ex; Abort(new ConnectionAbortedException(ex.Message, ex), ex.ErrorCode); } catch (Http3ConnectionErrorException ex) { error = ex; _errorCodeFeature.Error = (long)ex.ErrorCode; Log.Http3ConnectionError(_http3Connection.ConnectionId, ex); _http3Connection.Abort(new ConnectionAbortedException(ex.Message, ex), ex.ErrorCode); // TODO: HTTP/3 stream will be aborted by connection. Check this is correct. } catch (Exception ex) { error = ex; Log.LogWarning(0, ex, "Stream threw an unexpected exception."); } finally { var streamError = error as ConnectionAbortedException ?? new ConnectionAbortedException("The stream has completed.", error !); await Input.CompleteAsync(); // Make sure application func is completed before completing writer. if (_appCompleted != null) { await _appCompleted.Task; } try { await _frameWriter.CompleteAsync(); } catch { Abort(streamError, Http3ErrorCode.ProtocolError); throw; } finally { await _context.StreamContext.DisposeAsync(); _http3Connection.RemoveStream(_streamIdFeature.StreamId); } } }