private Task ProcessWindowUpdateFrameAsync() { if (_currentHeadersStream != null) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorHeadersInterleaved(_incomingFrame.Type, _incomingFrame.StreamId, _currentHeadersStream.StreamId), Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.Length != 4) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorUnexpectedFrameLength(_incomingFrame.Type, 4), Http2ErrorCode.FRAME_SIZE_ERROR); } ThrowIfIncomingFrameSentToIdleStream(); if (_incomingFrame.WindowUpdateSizeIncrement == 0) { // http://httpwg.org/specs/rfc7540.html#rfc.section.6.9 // A receiver MUST treat the receipt of a WINDOW_UPDATE // frame with an flow-control window increment of 0 as a // stream error (Section 5.4.2) of type PROTOCOL_ERROR; // errors on the connection flow-control window MUST be // treated as a connection error (Section 5.4.1). // // http://httpwg.org/specs/rfc7540.html#rfc.section.5.4.1 // An endpoint can end a connection at any time. In // particular, an endpoint MAY choose to treat a stream // error as a connection error. // // Since server initiated stream resets are not yet properly // implemented and tested, we treat all zero length window // increments as connection errors for now. throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorWindowUpdateIncrementZero, Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.StreamId == 0) { if (!_frameWriter.TryUpdateConnectionWindow(_incomingFrame.WindowUpdateSizeIncrement)) { throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorWindowUpdateSizeInvalid, Http2ErrorCode.FLOW_CONTROL_ERROR); } } else if (_streams.TryGetValue(_incomingFrame.StreamId, out var stream)) { if (!stream.TryUpdateOutputWindow(_incomingFrame.WindowUpdateSizeIncrement)) { throw new Http2StreamErrorException(_incomingFrame.StreamId, CoreStrings.Http2ErrorWindowUpdateSizeInvalid, Http2ErrorCode.FLOW_CONTROL_ERROR); } } else { // The stream was not found in the dictionary which means the stream was probably closed. This can // happen when the client sends a window update for a stream right as the server closes the same stream // Since this is an unavoidable race, we just ignore the window update frame. } return(Task.CompletedTask); }