public async Task ProcessRequestsAsync <TContext>(IHttpApplication <TContext> application) { Exception error = null; var errorCode = Http2ErrorCode.NO_ERROR; try { ValidateTlsRequirements(); if (!await TryReadPrefaceAsync()) { return; } if (_state != Http2ConnectionState.Closed) { await _frameWriter.WriteSettingsAsync(_serverSettings.GetNonProtocolDefaults()); } while (_state != Http2ConnectionState.Closed) { var result = await Input.ReadAsync(); var readableBuffer = result.Buffer; var consumed = readableBuffer.Start; var examined = readableBuffer.End; try { if (!readableBuffer.IsEmpty) { if (Http2FrameReader.ReadFrame(readableBuffer, _incomingFrame, _serverSettings.MaxFrameSize, out consumed, out examined)) { Log.Http2FrameReceived(ConnectionId, _incomingFrame); await ProcessFrameAsync(application); } } if (result.IsCompleted) { return; } } catch (Http2StreamErrorException ex) { Log.Http2StreamError(ConnectionId, ex); AbortStream(_incomingFrame.StreamId, new IOException(ex.Message, ex)); await _frameWriter.WriteRstStreamAsync(ex.StreamId, ex.ErrorCode); } finally { Input.AdvanceTo(consumed, examined); } } } catch (ConnectionResetException ex) { // Don't log ECONNRESET errors when there are no active streams on the connection. Browsers like IE will reset connections regularly. if (_streams.Count > 0) { Log.RequestProcessingError(ConnectionId, ex); } error = ex; } catch (IOException ex) { Log.RequestProcessingError(ConnectionId, ex); error = ex; } catch (Http2ConnectionErrorException ex) { Log.Http2ConnectionError(ConnectionId, ex); error = ex; errorCode = ex.ErrorCode; } catch (HPackDecodingException ex) { Log.HPackDecodingError(ConnectionId, _currentHeadersStream.StreamId, ex); error = ex; errorCode = Http2ErrorCode.COMPRESSION_ERROR; } catch (Exception ex) { Log.LogWarning(0, ex, CoreStrings.RequestProcessingEndError); error = ex; errorCode = Http2ErrorCode.INTERNAL_ERROR; } finally { var connectionError = error as ConnectionAbortedException ?? new ConnectionAbortedException(CoreStrings.Http2ConnectionFaulted, error); try { lock (_stateLock) { if (_state != Http2ConnectionState.Closed) { _frameWriter.WriteGoAwayAsync(_highestOpenedStreamId, errorCode); UpdateState(Http2ConnectionState.Closed); } if (_streams.IsEmpty) { _streamsCompleted.TrySetResult(null); } } // Ensure aborting each stream doesn't result in unnecessary WINDOW_UPDATE frames being sent. _inputFlowControl.StopWindowUpdates(); foreach (var stream in _streams.Values) { stream.Abort(new IOException(CoreStrings.Http2StreamAborted, connectionError)); } await _streamsCompleted.Task; _frameWriter.Complete(); } catch { _frameWriter.Abort(connectionError); throw; } finally { Input.Complete(); } } }
public async Task ProcessRequestsAsync <TContext>(IHttpApplication <TContext> application) { Exception error = null; var errorCode = Http2ErrorCode.NO_ERROR; try { ValidateTlsRequirements(); if (!await TryReadPrefaceAsync()) { return; } if (!_stopping) { await _frameWriter.WriteSettingsAsync(_serverSettings); } while (!_stopping) { var result = await Input.ReadAsync(); var readableBuffer = result.Buffer; var consumed = readableBuffer.Start; var examined = readableBuffer.End; try { if (!readableBuffer.IsEmpty) { if (Http2FrameReader.ReadFrame(readableBuffer, _incomingFrame, _serverSettings.MaxFrameSize, out consumed, out examined)) { Log.LogTrace($"Connection id {ConnectionId} received {_incomingFrame.Type} frame with flags 0x{_incomingFrame.Flags:x} and length {_incomingFrame.Length} for stream ID {_incomingFrame.StreamId}"); await ProcessFrameAsync(application); } } if (result.IsCompleted) { return; } } catch (Http2StreamErrorException ex) { Log.Http2StreamError(ConnectionId, ex); AbortStream(_incomingFrame.StreamId, new ConnectionAbortedException(ex.Message, ex)); await _frameWriter.WriteRstStreamAsync(ex.StreamId, ex.ErrorCode); } finally { Input.AdvanceTo(consumed, examined); } } } catch (ConnectionResetException ex) { // Don't log ECONNRESET errors when there are no active streams on the connection. Browsers like IE will reset connections regularly. if (_streams.Count > 0) { Log.RequestProcessingError(ConnectionId, ex); } error = ex; } catch (Http2ConnectionErrorException ex) { Log.Http2ConnectionError(ConnectionId, ex); error = ex; errorCode = ex.ErrorCode; } catch (HPackDecodingException ex) { Log.HPackDecodingError(ConnectionId, _currentHeadersStream.StreamId, ex); error = ex; errorCode = Http2ErrorCode.COMPRESSION_ERROR; } catch (Exception ex) { error = ex; errorCode = Http2ErrorCode.INTERNAL_ERROR; throw; } finally { var connectionError = error as ConnectionAbortedException ?? new ConnectionAbortedException(CoreStrings.Http2ConnectionFaulted, error); try { foreach (var stream in _streams.Values) { stream.Abort(connectionError); } await _frameWriter.WriteGoAwayAsync(_highestOpenedStreamId, errorCode); _frameWriter.Complete(); } catch { _frameWriter.Abort(connectionError); throw; } finally { Input.Complete(); } } }
public async Task ProcessAsync <TContext>(IHttpApplication <TContext> application) { Exception error = null; var errorCode = Http2ErrorCode.NO_ERROR; try { while (!_stopping) { var result = await Input.ReadAsync(); var readableBuffer = result.Buffer; var consumed = readableBuffer.Start; var examined = readableBuffer.End; try { if (!readableBuffer.IsEmpty) { if (ParsePreface(readableBuffer, out consumed, out examined)) { break; } } else if (result.IsCompleted) { return; } } finally { Input.Advance(consumed, examined); } } if (!_stopping) { await _frameWriter.WriteSettingsAsync(_serverSettings); } while (!_stopping) { var result = await Input.ReadAsync(); var readableBuffer = result.Buffer; var consumed = readableBuffer.Start; var examined = readableBuffer.End; try { if (!readableBuffer.IsEmpty) { if (Http2FrameReader.ReadFrame(readableBuffer, _incomingFrame, out consumed, out examined)) { Log.LogTrace($"Connection id {ConnectionId} received {_incomingFrame.Type} frame with flags 0x{_incomingFrame.Flags:x} and length {_incomingFrame.Length} for stream ID {_incomingFrame.StreamId}"); await ProcessFrameAsync <TContext>(application); } } else if (result.IsCompleted) { return; } } finally { Input.Advance(consumed, examined); } } } catch (ConnectionAbortedException ex) { // TODO: log error = ex; } catch (Http2ConnectionErrorException ex) { // TODO: log error = ex; errorCode = ex.ErrorCode; } catch (HPackDecodingException ex) { // TODO: log error = ex; errorCode = Http2ErrorCode.COMPRESSION_ERROR; } catch (Exception ex) { // TODO: log error = ex; errorCode = Http2ErrorCode.INTERNAL_ERROR; } finally { try { foreach (var stream in _streams.Values) { stream.Abort(error); } await _frameWriter.WriteGoAwayAsync(_highestOpenedStreamId, errorCode); } finally { Input.Complete(); _frameWriter.Abort(ex: null); } } }