private Task ProcessSettingsFrameAsync() { if (_currentHeadersStream != null) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorHeadersInterleaved(_incomingFrame.Type, _incomingFrame.StreamId, _currentHeadersStream.StreamId), Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.StreamId != 0) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorStreamIdNotZero(_incomingFrame.Type), Http2ErrorCode.PROTOCOL_ERROR); } if ((_incomingFrame.SettingsFlags & Http2SettingsFrameFlags.ACK) == Http2SettingsFrameFlags.ACK && _incomingFrame.Length != 0) { throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorSettingsAckLengthNotZero, Http2ErrorCode.FRAME_SIZE_ERROR); } if (_incomingFrame.Length % 6 != 0) { throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorSettingsLengthNotMultipleOfSix, Http2ErrorCode.FRAME_SIZE_ERROR); } try { _clientSettings.ParseFrame(_incomingFrame); return _frameWriter.WriteSettingsAckAsync(); } catch (Http2SettingsParameterOutOfRangeException ex) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorSettingsParameterOutOfRange(ex.Parameter), ex.Parameter == Http2SettingsParameter.SETTINGS_INITIAL_WINDOW_SIZE ? Http2ErrorCode.FLOW_CONTROL_ERROR : Http2ErrorCode.PROTOCOL_ERROR); } }
private Task ProcessSettingsFrameAsync() { if (_currentHeadersStream != null) { throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.StreamId != 0) { throw new Http2ConnectionErrorException(Http2ErrorCode.PROTOCOL_ERROR); } if ((_incomingFrame.SettingsFlags & Http2SettingsFrameFlags.ACK) == Http2SettingsFrameFlags.ACK && _incomingFrame.Length != 0) { throw new Http2ConnectionErrorException(Http2ErrorCode.FRAME_SIZE_ERROR); } if (_incomingFrame.Length % 6 != 0) { throw new Http2ConnectionErrorException(Http2ErrorCode.FRAME_SIZE_ERROR); } try { _clientSettings.ParseFrame(_incomingFrame); return(_frameWriter.WriteSettingsAckAsync()); } catch (Http2SettingsParameterOutOfRangeException ex) { throw new Http2ConnectionErrorException(ex.Parameter == Http2SettingsParameter.SETTINGS_INITIAL_WINDOW_SIZE ? Http2ErrorCode.FLOW_CONTROL_ERROR : Http2ErrorCode.PROTOCOL_ERROR); } }
private Task ProcessSettingsFrameAsync() { if (_currentHeadersStream != null) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorHeadersInterleaved(_incomingFrame.Type, _incomingFrame.StreamId, _currentHeadersStream.StreamId), Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.StreamId != 0) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorStreamIdNotZero(_incomingFrame.Type), Http2ErrorCode.PROTOCOL_ERROR); } if ((_incomingFrame.SettingsFlags & Http2SettingsFrameFlags.ACK) == Http2SettingsFrameFlags.ACK && _incomingFrame.Length != 0) { throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorSettingsAckLengthNotZero, Http2ErrorCode.FRAME_SIZE_ERROR); } if (_incomingFrame.Length % 6 != 0) { throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorSettingsLengthNotMultipleOfSix, Http2ErrorCode.FRAME_SIZE_ERROR); } try { // ParseFrame will not parse an InitialWindowSize > int.MaxValue. var previousInitialWindowSize = (int)_clientSettings.InitialWindowSize; _clientSettings.ParseFrame(_incomingFrame); // This difference can be negative. var windowSizeDifference = (int)_clientSettings.InitialWindowSize - previousInitialWindowSize; if (windowSizeDifference != 0) { foreach (var stream in _streams.Values) { if (!stream.TryUpdateOutputWindow(windowSizeDifference)) { // This means that this caused a stream window to become larger than int.MaxValue. // This can never happen with a well behaved client and MUST be treated as a connection error. // https://httpwg.org/specs/rfc7540.html#rfc.section.6.9.2 throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorInitialWindowSizeInvalid, Http2ErrorCode.FLOW_CONTROL_ERROR); } } } return(_frameWriter.WriteSettingsAckAsync()); } catch (Http2SettingsParameterOutOfRangeException ex) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorSettingsParameterOutOfRange(ex.Parameter), ex.Parameter == Http2SettingsParameter.SETTINGS_INITIAL_WINDOW_SIZE ? Http2ErrorCode.FLOW_CONTROL_ERROR : Http2ErrorCode.PROTOCOL_ERROR); } }
private async Task ProcessSettingsFrameAsync() { if (_currentHeadersStream != null) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorHeadersInterleaved(_incomingFrame.Type, _incomingFrame.StreamId, _currentHeadersStream.StreamId), Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.StreamId != 0) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorStreamIdNotZero(_incomingFrame.Type), Http2ErrorCode.PROTOCOL_ERROR); } if (_incomingFrame.SettingsAck) { if (_incomingFrame.PayloadLength != 0) { throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorSettingsAckLengthNotZero, Http2ErrorCode.FRAME_SIZE_ERROR); } return; } if (_incomingFrame.PayloadLength % 6 != 0) { throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorSettingsLengthNotMultipleOfSix, Http2ErrorCode.FRAME_SIZE_ERROR); } try { // int.MaxValue is the largest allowed windows size. var previousInitialWindowSize = (int)_clientSettings.InitialWindowSize; var previousMaxFrameSize = _clientSettings.MaxFrameSize; _clientSettings.Update(_incomingFrame.GetSettings()); // Ack before we update the windows, they could send data immediately. await _frameWriter.WriteSettingsAckAsync(); if (_clientSettings.MaxFrameSize != previousMaxFrameSize) { _frameWriter.UpdateMaxFrameSize(_clientSettings.MaxFrameSize); } // This difference can be negative. var windowSizeDifference = (int)_clientSettings.InitialWindowSize - previousInitialWindowSize; if (windowSizeDifference != 0) { foreach (var stream in _streams.Values) { if (!stream.TryUpdateOutputWindow(windowSizeDifference)) { // This means that this caused a stream window to become larger than int.MaxValue. // This can never happen with a well behaved client and MUST be treated as a connection error. // https://httpwg.org/specs/rfc7540.html#rfc.section.6.9.2 throw new Http2ConnectionErrorException(CoreStrings.Http2ErrorInitialWindowSizeInvalid, Http2ErrorCode.FLOW_CONTROL_ERROR); } } } } catch (Http2SettingsParameterOutOfRangeException ex) { throw new Http2ConnectionErrorException(CoreStrings.FormatHttp2ErrorSettingsParameterOutOfRange(ex.Parameter), ex.Parameter == Http2SettingsParameter.SETTINGS_INITIAL_WINDOW_SIZE ? Http2ErrorCode.FLOW_CONTROL_ERROR : Http2ErrorCode.PROTOCOL_ERROR); } }