private Task ProcessWindowUpdateFrameAsync() { if (_currentHeadersStream != null) { throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.Length != 4) { throw new Http2ConnectionErrorException(Http2ErrorCode.FRAME_SIZE_ERROR); } ThrowIfIncomingFrameSentToIdleStream(); if (_incomingFrame.WindowUpdateSizeIncrement == 0) { if (_incomingFrame.StreamId == 0) { throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } else { return(_frameWriter.WriteRstStreamAsync(_incomingFrame.StreamId, Http2ErrorCode.PROTOCOL_ERROR)); } } return(Task.CompletedTask); }
public ValueTask<FlushResult> WriteRstStreamAsync(Http2ErrorCode error) { lock (_dataWriterLock) { // Always send the reset even if the response body is _completed. The request body may not have completed yet. Stop(); return _frameWriter.WriteRstStreamAsync(StreamId, error); } }
public Task WriteRstStreamAsync(Http2ErrorCode error) { lock (_dataWriterLock) { // Always send the reset even if the response body is _completed. The request body may not have completed yet. Dispose(); return(_frameWriter.WriteRstStreamAsync(_streamId, error)); } }
private Task DecodeHeadersAsync<TContext>(IHttpApplication<TContext> application, bool endHeaders, Span<byte> payload) { try { _hpackDecoder.Decode(payload, endHeaders, handler: this); if (endHeaders) { StartStream(application); ResetRequestHeaderParsingState(); } } catch (Http2StreamErrorException ex) { Log.Http2StreamError(ConnectionId, ex); ResetRequestHeaderParsingState(); return _frameWriter.WriteRstStreamAsync(ex.StreamId, ex.ErrorCode); } return Task.CompletedTask; }
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 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(); } } }