public void WriteWindowUpdate(Int32 windowSize) { if (windowSize <= 0) { throw new ArgumentOutOfRangeException("windowSize should be greater than 0"); } if (windowSize > Constants.MaxWindowSize) { throw new ProtocolError(ResetStatusCode.FlowControlError, "window size is too large"); } //09 -> 6.9.4. Ending Flow Control //After a receiver reads in a frame that marks the end of a stream (for //example, a data stream with a END_STREAM flag set), it MUST cease //transmission of WINDOW_UPDATE frames for that stream. if (Closed) { return; } //TODO handle idle state var frame = new WindowUpdateFrame(_id, windowSize); _writeQueue.WriteFrame(frame); Http2Logger.LogDebug("Sending WINDOW_UPDATE: stream id={0}, delta={1}", frame.StreamId, frame.Delta); if (OnFrameSent != null) { OnFrameSent(this, new FrameSentEventArgs(frame)); } }
public WindowUpdateFrame BuildWindowUpdateFrame(Http2Stream stream, Int64 deltaSize) { WindowUpdateFrame frame = new WindowUpdateFrame(stream.StreamId, deltaSize); frame.Flags = 0; frame.Length = 8; return(frame); }
public void WriteWindowUpdate(Int32 windowSize) { var frame = new WindowUpdateFrame(_id, windowSize); _writeQueue.WriteFrame(frame); if (OnFrameSent != null) { OnFrameSent(this, new FrameSentArgs(frame)); } }
private void HandleWindowUpdateFrame(WindowUpdateFrame windowUpdateFrame, out Http2Stream stream) { Http2Logger.LogDebug("WINDOW_UPDATE frame: stream id={0}, delta={1}", windowUpdateFrame.StreamId, windowUpdateFrame.Delta); if (!_useFlowControl) { stream = null; return; } // TODO Remove this hack /* The WINDOW_UPDATE frame can be specific to a stream or to the entire * connection. In the former case, the frame's stream identifier * indicates the affected stream; in the latter, the value "0" indicates * that the _entire connection_ is the subject of the frame. */ if (windowUpdateFrame.StreamId == 0) { _flowControlManager.StreamsInitialWindowSize += windowUpdateFrame.Delta; stream = null; return; } stream = GetStream(windowUpdateFrame.StreamId); /* 12 -> 6.9 * WINDOW_UPDATE can be sent by a peer that has sent a frame bearing the * END_STREAM flag. This means that a receiver could receive a * WINDOW_UPDATE frame on a "half closed (remote)" or "closed" stream. * A receiver MUST NOT treat this as an error. */ if (!(stream.Opened || stream.HalfClosedRemote || stream.HalfClosedLocal || stream.Closed)) { throw new ProtocolError(ResetStatusCode.ProtocolError, "window update in incorrect state"); } //09 -> 6.9. WINDOW_UPDATE //The payload of a WINDOW_UPDATE frame is one reserved bit, plus an //unsigned 31-bit integer indicating the number of bytes that the //sender can transmit in addition to the existing flow control window. //The legal range for the increment to the flow control window is 1 to //2^31 - 1 (0x7fffffff) bytes. if (!(0 < windowUpdateFrame.Delta && windowUpdateFrame.Delta <= Constants.MaxPriority)) { Http2Logger.LogDebug("Incorrect window update delta : {0}", windowUpdateFrame.Delta); throw new ProtocolError(ResetStatusCode.FlowControlError, String.Format("Incorrect window update delta : {0}", windowUpdateFrame.Delta)); } stream.UpdateWindowSize(windowUpdateFrame.Delta); stream.PumpUnshippedFrames(); }
/// <summary> /// Deserializes the data into control frame. /// </summary> /// <param name="data">The data.</param> /// <returns>Deserialized frame.</returns> private BaseFrame DeserializeControlFrame(byte[] data) { FrameType type = GetFrameType(data); ControlFrame frame = new ControlFrame(); switch (type) { case FrameType.RTS: frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4)); frame.StatusCode = (StatusCode)BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 12, 4)); break; case FrameType.Headers: case FrameType.SynReply: ParseControlFrameHeader(ref frame, data); frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4)); ParseControlFrameHeaders(ref frame, data, 12); break; case FrameType.SynStream: ParseControlFrameHeader(ref frame, data); frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4)); frame.AssociatedToStreamId = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 12, 4)); frame.Priority = (byte)(data[16] >> 5); frame.Slot = data[17]; ParseControlFrameHeaders(ref frame, data, 18); break; case FrameType.Settings: int numberOfEntries = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4)); frame = new SettingsFrame(numberOfEntries); int headersOffset = 12; for (int i = 0; i < numberOfEntries; i++) { int key = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, headersOffset, 4)); headersOffset += 4; int value = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, headersOffset, 4)); headersOffset += 4; frame.SettingsHeaders.Add(key, value); } ParseControlFrameHeader(ref frame, data); break; case FrameType.GoAway: int lastSeenGoodStreamId = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4)); StatusCode status = StatusCode.Success; if (data.Length > 12) status = (StatusCode)BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 12, 4)); frame = new GoAwayFrame(lastSeenGoodStreamId, status); ParseControlFrameHeader(ref frame, data); break; case FrameType.Ping: int streamID = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 4, 4)); frame = new ControlFrame { StreamId = streamID }; ParseControlFrameHeader(ref frame, data); break; case FrameType.WindowUpdate: int streamId = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 4, 4)); int deltaWindowSize = BinaryHelper.Int32FromBytes(new ArraySegment<byte>(data, 8, 4)); frame = new WindowUpdateFrame(streamId, deltaWindowSize); ParseControlFrameHeader(ref frame, data); break; } frame.Type = type; return frame; }
public WindowUpdateFrame BuildWindowUpdateFrame(Http2Stream stream, Int64 deltaSize) { WindowUpdateFrame frame = new WindowUpdateFrame(stream.StreamId, deltaSize); frame.Flags = 0; frame.Length = 8; return frame; }
/// <summary> /// Deserializes the data into control frame. /// </summary> /// <param name="data">The data.</param> /// <returns>Deserialized frame.</returns> private BaseFrame DeserializeControlFrame(byte[] data) { FrameType type = GetFrameType(data); ControlFrame frame = new ControlFrame(); switch (type) { case FrameType.RTS: frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); frame.StatusCode = (StatusCode)BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 12, 4)); break; case FrameType.Headers: case FrameType.SynReply: ParseControlFrameHeader(ref frame, data); frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); ParseControlFrameHeaders(ref frame, data, 12); break; case FrameType.SynStream: ParseControlFrameHeader(ref frame, data); frame.StreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); frame.AssociatedToStreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 12, 4)); frame.Priority = (byte)(data[16] >> 5); frame.Slot = data[17]; ParseControlFrameHeaders(ref frame, data, 18); break; case FrameType.Settings: int numberOfEntries = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); frame = new SettingsFrame(numberOfEntries); int headersOffset = 12; for (int i = 0; i < numberOfEntries; i++) { int key = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, headersOffset, 4)); headersOffset += 4; int value = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, headersOffset, 4)); headersOffset += 4; frame.SettingsHeaders.Add(key, value); } ParseControlFrameHeader(ref frame, data); break; case FrameType.GoAway: int lastSeenGoodStreamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); StatusCode status = StatusCode.Success; if (data.Length > 12) { status = (StatusCode)BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 12, 4)); } frame = new GoAwayFrame(lastSeenGoodStreamId, status); ParseControlFrameHeader(ref frame, data); break; case FrameType.Ping: int streamID = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 4, 4)); frame = new ControlFrame { StreamId = streamID }; ParseControlFrameHeader(ref frame, data); break; case FrameType.WindowUpdate: int streamId = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 4, 4)); int deltaWindowSize = BinaryHelper.Int32FromBytes(new ArraySegment <byte>(data, 8, 4)); frame = new WindowUpdateFrame(streamId, deltaWindowSize); ParseControlFrameHeader(ref frame, data); break; } frame.Type = type; return(frame); }
/// <summary> /// Process a window update frame request. /// </summary> /// <param name="httpContext">The current http context.</param> /// <param name="windowUpdateFrame">The window update frame.</param> /// <param name="stream">The selected stream context.</param> private static void ProcessWindowUpdateFrameRequest(Nequeo.Net.Http2.HttpContext httpContext, WindowUpdateFrame windowUpdateFrame, out ContextStream stream) { // Attempt to get the sepcific stream. stream = httpContext.GetStream(windowUpdateFrame.StreamId); if (stream == null) { throw new MaxConcurrentStreamsLimitException(); } }