Example #1
0
        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);
        }
Example #3
0
        public void WriteWindowUpdate(Int32 windowSize)
        {
            var frame = new WindowUpdateFrame(_id, windowSize);

            _writeQueue.WriteFrame(frame);

            if (OnFrameSent != null)
            {
                OnFrameSent(this, new FrameSentArgs(frame));
            }
        }
Example #4
0
        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);
        }
Example #8
0
 /// <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();
     }
 }