internal void Process(HTTP2FrameHeaderAndPayload frame, List <HTTP2FrameHeaderAndPayload> outgoingFrames)
        {
            if (frame.Type != HTTP2FrameTypes.SETTINGS)
            {
                return;
            }

            HTTP2SettingsFrame settingsFrame = HTTP2FrameHelper.ReadSettings(frame);

            if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
            {
                HTTPManager.Logger.Information("HTTP2SettingsManager", "Processing Settings frame: " + settingsFrame.ToString(), this.Parent.Context);
            }

            if ((settingsFrame.Flags & HTTP2SettingsFlags.ACK) == HTTP2SettingsFlags.ACK)
            {
                this.MySettings.Merge(this.InitiatedMySettings);
                this.SettingsChangesSentAt = DateTime.MinValue;
            }
            else
            {
                this.RemoteSettings.Merge(settingsFrame.Settings);
                outgoingFrames.Add(HTTP2FrameHelper.CreateACKSettingsFrame());
            }
        }
        protected override bool AdvanceFrame()
        {
            if (this.currentFrameIdx >= this.frames.Count - 1)
            {
                return(false);
            }

            this.currentFrameIdx++;
            HTTP2FrameHeaderAndPayload frame = this.frames[this.currentFrameIdx];

            this.data = frame.Payload;

            switch (frame.Type)
            {
            case HTTP2FrameTypes.HEADERS:
                var header = HTTP2FrameHelper.ReadHeadersFrame(frame);
                this.offset    = header.HeaderBlockFragmentIdx;
                this.maxOffset = this.offset + header.HeaderBlockFragmentLength;
                break;

            case HTTP2FrameTypes.CONTINUATION:
                this.offset    = 0;
                this.maxOffset = frame.PayloadLength;
                break;
            }

            return(true);
        }
        public static HTTP2PushPromiseFrame ReadPush_PromiseFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#PUSH_PROMISE

            HTTP2PushPromiseFrame frame = new HTTP2PushPromiseFrame(header);

            frame.HeaderBlockFragmentLength = header.PayloadLength - 4; // PromisedStreamId

            bool isPadded = (frame.Flags & HTTP2PushPromiseFlags.PADDED) != 0;

            if (isPadded)
            {
                frame.PadLength = header.Payload[0];
                frame.HeaderBlockFragmentLength -= (uint)(1 + (frame.PadLength ?? 0));
            }

            frame.ReservedBit      = BufferHelper.ReadBit(header.Payload[1], 0);
            frame.PromisedStreamId = BufferHelper.ReadUInt31(header.Payload, 1);

            frame.HeaderBlockFragmentIdx = (UInt32)(isPadded ? 5 : 4);
            frame.HeaderBlockFragment    = header.Payload;
            header.Payload = null;

            return(frame);
        }
        public static HTTP2DataFrame ReadDataFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#DATA

            HTTP2DataFrame frame = new HTTP2DataFrame(header);

            frame.DataLength = header.PayloadLength;

            bool isPadded = (frame.Flags & HTTP2DataFlags.PADDED) != 0;

            if (isPadded)
            {
                frame.PadLength = header.Payload[0];

                uint subLength = (uint)(1 + (frame.PadLength ?? 0));
                if (subLength <= frame.DataLength)
                {
                    frame.DataLength -= subLength;
                }
                //else
                //    throw PROTOCOL_ERROR;
            }

            frame.DataIdx  = (UInt32)(isPadded ? 1 : 0);
            frame.Data     = header.Payload;
            header.Payload = null;

            return(frame);
        }
Пример #5
0
 public HTTP2PriorityFrame(HTTP2FrameHeaderAndPayload header)
 {
     this.Header           = header;
     this.IsExclusive      = 0;
     this.StreamDependency = 0;
     this.Weight           = 0;
 }
Пример #6
0
 public HTTP2DataFrame(HTTP2FrameHeaderAndPayload header)
 {
     this.Header     = header;
     this.PadLength  = null;
     this.DataIdx    = 0;
     this.Data       = null;
     this.DataLength = 0;
 }
        public static HTTP2AltSVCFrame ReadAltSvcFrame(HTTP2FrameHeaderAndPayload header)
        {
            HTTP2AltSVCFrame frame = new HTTP2AltSVCFrame(header);

            // Implement

            return(frame);
        }
Пример #8
0
        public void AddFrame(HTTP2FrameHeaderAndPayload frame, List <HTTP2FrameHeaderAndPayload> outgoingFrames)
        {
            // Room for improvement: error check for forbidden frames (like settings) and stream state

            this.incomingFrames.Enqueue(frame);

            ProcessIncomingFrames(outgoingFrames);
        }
        public static HTTP2FrameHeaderAndPayload CreateACKSettingsFrame()
        {
            HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload();

            frame.Type  = HTTP2FrameTypes.SETTINGS;
            frame.Flags = (byte)HTTP2SettingsFlags.ACK;

            return(frame);
        }
Пример #10
0
 public HTTP2GoAwayFrame(HTTP2FrameHeaderAndPayload header)
 {
     this.Header                    = header;
     this.ReservedBit               = 0;
     this.LastStreamId              = 0;
     this.ErrorCode                 = 0;
     this.AdditionalDebugData       = null;
     this.AdditionalDebugDataLength = 0;
 }
Пример #11
0
 public HTTP2PushPromiseFrame(HTTP2FrameHeaderAndPayload header)
 {
     this.Header                    = header;
     this.PadLength                 = null;
     this.ReservedBit               = 0;
     this.PromisedStreamId          = 0;
     this.HeaderBlockFragmentIdx    = 0;
     this.HeaderBlockFragment       = null;
     this.HeaderBlockFragmentLength = 0;
 }
        public static HTTP2RSTStreamFrame ReadRST_StreamFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#RST_STREAM

            HTTP2RSTStreamFrame frame = new HTTP2RSTStreamFrame(header);

            frame.ErrorCode = BufferHelper.ReadUInt32(header.Payload, 0);

            return(frame);
        }
Пример #13
0
        public override void AddFrame(HTTP2FrameHeaderAndPayload frame)
        {
            if (frame.Type != HTTP2FrameTypes.DATA)
            {
                throw new ArgumentException("HeaderFrameView - Unexpected frame type: " + frame.Type);
            }

            this.frames.Add(frame);
            this.Length += CalculateDataLengthForFrame(frame);
        }
        public static HTTP2PingFrame ReadPingFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#PING

            HTTP2PingFrame frame = new HTTP2PingFrame(header);

            Array.Copy(header.Payload, 0, frame.OpaqueData, 0, frame.OpaqueDataLength);

            return(frame);
        }
        public static HTTP2WindowUpdateFrame ReadWindowUpdateFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#WINDOW_UPDATE

            HTTP2WindowUpdateFrame frame = new HTTP2WindowUpdateFrame(header);

            frame.ReservedBit         = BufferHelper.ReadBit(header.Payload[0], 0);
            frame.WindowSizeIncrement = BufferHelper.ReadUInt31(header.Payload, 0);

            return(frame);
        }
        public static HTTP2ContinuationFrame ReadContinuationFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#CONTINUATION

            HTTP2ContinuationFrame frame = new HTTP2ContinuationFrame(header);

            frame.HeaderBlockFragment = header.Payload;
            header.Payload            = null;

            return(frame);
        }
Пример #17
0
 public HTTP2HeadersFrame(HTTP2FrameHeaderAndPayload header)
 {
     this.Header                    = header;
     this.PadLength                 = null;
     this.IsExclusive               = null;
     this.StreamDependency          = null;
     this.Weight                    = null;
     this.HeaderBlockFragmentIdx    = 0;
     this.HeaderBlockFragment       = null;
     this.HeaderBlockFragmentLength = 0;
 }
Пример #18
0
        protected override long CalculateDataLengthForFrame(HTTP2FrameHeaderAndPayload frame)
        {
            switch (frame.Type)
            {
            case HTTP2FrameTypes.HEADERS:
                return(HTTP2FrameHelper.ReadHeadersFrame(frame).HeaderBlockFragmentLength);

            case HTTP2FrameTypes.CONTINUATION:
                return(frame.PayloadLength);
            }

            return(0);
        }
        public static HTTP2FrameHeaderAndPayload CreatePingFrame(HTTP2PingFlags flags = HTTP2PingFlags.None)
        {
            // https://httpwg.org/specs/rfc7540.html#PING

            HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload();

            frame.Type          = HTTP2FrameTypes.PING;
            frame.Flags         = (byte)flags;
            frame.StreamId      = 0;
            frame.Payload       = BufferPool.Get(8, true);
            frame.PayloadLength = 8;

            return(frame);
        }
        public static PooledBuffer HeaderAsBinary(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#FrameHeader

            var buffer = BufferPool.Get(9, true);

            BufferHelper.SetUInt24(buffer, 0, header.PayloadLength);
            buffer[3] = (byte)header.Type;
            buffer[4] = header.Flags;
            BufferHelper.SetUInt31(buffer, 5, header.StreamId);

            return(new PooledBuffer {
                Data = buffer, Length = 9
            });
        }
Пример #21
0
        public override void AddFrame(HTTP2FrameHeaderAndPayload frame)
        {
            if (frame.Type != HTTP2FrameTypes.HEADERS && frame.Type != HTTP2FrameTypes.CONTINUATION)
            {
                throw new ArgumentException("HeaderFrameView - Unexpected frame type: " + frame.Type);
            }

            this.frames.Add(frame);
            this.Length += CalculateDataLengthForFrame(frame);

            if (this.currentFrameIdx == -1)
            {
                AdvanceFrame();
            }
        }
        public static HTTP2FrameHeaderAndPayload CreateRSTFrame(UInt32 streamId, HTTP2ErrorCodes errorCode)
        {
            // https://httpwg.org/specs/rfc7540.html#RST_STREAM

            HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload();

            frame.Type          = HTTP2FrameTypes.RST_STREAM;
            frame.Flags         = 0;
            frame.StreamId      = streamId;
            frame.Payload       = BufferPool.Get(4, true);
            frame.PayloadLength = 4;

            BufferHelper.SetUInt32(frame.Payload, 0, (UInt32)errorCode);

            return(frame);
        }
        public static HTTP2HeadersFrame ReadHeadersFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#HEADERS

            HTTP2HeadersFrame frame = new HTTP2HeadersFrame(header);

            frame.HeaderBlockFragmentLength = header.PayloadLength;

            bool isPadded   = (frame.Flags & HTTP2HeadersFlags.PADDED) != 0;
            bool isPriority = (frame.Flags & HTTP2HeadersFlags.PRIORITY) != 0;

            int payloadIdx = 0;

            if (isPadded)
            {
                frame.PadLength = header.Payload[payloadIdx++];

                uint subLength = (uint)(1 + (frame.PadLength ?? 0));
                if (subLength <= frame.HeaderBlockFragmentLength)
                {
                    frame.HeaderBlockFragmentLength -= subLength;
                }
                //else
                //    throw PROTOCOL_ERROR;
            }

            if (isPriority)
            {
                frame.IsExclusive      = BufferHelper.ReadBit(header.Payload[payloadIdx], 0);
                frame.StreamDependency = BufferHelper.ReadUInt31(header.Payload, payloadIdx);
                payloadIdx            += 4;
                frame.Weight           = header.Payload[payloadIdx++];

                uint subLength = 5;
                if (subLength <= frame.HeaderBlockFragmentLength)
                {
                    frame.HeaderBlockFragmentLength -= subLength;
                }
                //else
                //    throw PROTOCOL_ERROR;
            }

            frame.HeaderBlockFragmentIdx = (UInt32)payloadIdx;
            frame.HeaderBlockFragment    = header.Payload;

            return(frame);
        }
        public static HTTP2FrameHeaderAndPayload CreateGoAwayFrame(UInt32 lastStreamId, HTTP2ErrorCodes error)
        {
            // https://httpwg.org/specs/rfc7540.html#GOAWAY

            HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload();

            frame.Type          = HTTP2FrameTypes.GOAWAY;
            frame.Flags         = 0;
            frame.StreamId      = 0;
            frame.Payload       = BufferPool.Get(8, true);
            frame.PayloadLength = 8;

            BufferHelper.SetUInt31(frame.Payload, 0, lastStreamId);
            BufferHelper.SetUInt31(frame.Payload, 4, (UInt32)error);

            return(frame);
        }
        public static HTTP2PriorityFrame ReadPriorityFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#PRIORITY

            if (header.PayloadLength != 5)
            {
                //throw FRAME_SIZE_ERROR
            }

            HTTP2PriorityFrame frame = new HTTP2PriorityFrame(header);

            frame.IsExclusive      = BufferHelper.ReadBit(header.Payload[0], 0);
            frame.StreamDependency = BufferHelper.ReadUInt31(header.Payload, 0);
            frame.Weight           = header.Payload[4];

            return(frame);
        }
        public static HTTP2FrameHeaderAndPayload CreateWindowUpdateFrame(UInt32 streamId, UInt32 windowSizeIncrement)
        {
            // https://httpwg.org/specs/rfc7540.html#WINDOW_UPDATE

            HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload();

            frame.Type          = HTTP2FrameTypes.WINDOW_UPDATE;
            frame.Flags         = 0;
            frame.StreamId      = streamId;
            frame.Payload       = BufferPool.Get(4, true);
            frame.PayloadLength = 4;

            BufferHelper.SetBit(0, 0, 0);
            BufferHelper.SetUInt31(frame.Payload, 0, windowSizeIncrement);

            return(frame);
        }
Пример #27
0
        protected override bool AdvanceFrame()
        {
            if (this.currentFrameIdx >= this.frames.Count - 1)
            {
                return(false);
            }

            this.currentFrameIdx++;
            HTTP2FrameHeaderAndPayload frame     = this.frames[this.currentFrameIdx];
            HTTP2DataFrame             dataFrame = HTTP2FrameHelper.ReadDataFrame(frame);

            this.data      = frame.Payload;
            this.offset    = dataFrame.DataIdx;
            this.maxOffset = dataFrame.DataIdx + dataFrame.DataLength;

            return(true);
        }
        public static HTTP2FrameHeaderAndPayload CreateSettingsFrame(List <KeyValuePair <HTTP2Settings, UInt32> > settings)
        {
            HTTP2FrameHeaderAndPayload frame = new HTTP2FrameHeaderAndPayload();

            frame.Type          = HTTP2FrameTypes.SETTINGS;
            frame.Flags         = 0;
            frame.PayloadLength = (UInt32)settings.Count * 6;

            frame.Payload = BufferPool.Get(frame.PayloadLength, true);

            for (int i = 0; i < settings.Count; ++i)
            {
                BufferHelper.SetUInt16(frame.Payload, i * 6, (UInt16)settings[i].Key);
                BufferHelper.SetUInt32(frame.Payload, (i * 6) + 2, settings[i].Value);
            }

            return(frame);
        }
        public void Process(List <HTTP2FrameHeaderAndPayload> outgoingFrames)
        {
            if (this.AssignedRequest.IsCancellationRequested && !this.isRSTFrameSent)
            {
                // These two are already set in HTTPRequest's Abort().
                //this.AssignedRequest.Response = null;
                //this.AssignedRequest.State = this.AssignedRequest.IsTimedOut ? HTTPRequestStates.TimedOut : HTTPRequestStates.Aborted;

                this.outgoing.Clear();
                if (this.State != HTTP2StreamStates.Idle)
                {
                    this.outgoing.Enqueue(HTTP2FrameHelper.CreateRSTFrame(this.Id, HTTP2ErrorCodes.CANCEL));
                }

                // We can close the stream if already received headers, or not even sent one
                if (this.State == HTTP2StreamStates.HalfClosedRemote || this.State == HTTP2StreamStates.Idle)
                {
                    this.State = HTTP2StreamStates.Closed;
                }

                this.isRSTFrameSent = true;
            }

            // 1.) Go through incoming frames
            ProcessIncomingFrames(outgoingFrames);

            // 2.) Create outgoing frames based on the stream's state and the request processing state.
            ProcessState(outgoingFrames);

            // 3.) Send one frame per Process call
            if (this.outgoing.Count > 0)
            {
                HTTP2FrameHeaderAndPayload frame = this.outgoing.Dequeue();

                outgoingFrames.Add(frame);

                // If END_Stream in header or data frame is present => half closed local
                if ((frame.Type == HTTP2FrameTypes.HEADERS && (frame.Flags & (byte)HTTP2HeadersFlags.END_STREAM) != 0) ||
                    (frame.Type == HTTP2FrameTypes.DATA && (frame.Flags & (byte)HTTP2DataFlags.END_STREAM) != 0))
                {
                    this.State = HTTP2StreamStates.HalfClosedLocal;
                }
            }
        }
        public static HTTP2GoAwayFrame ReadGoAwayFrame(HTTP2FrameHeaderAndPayload header)
        {
            // https://httpwg.org/specs/rfc7540.html#GOAWAY

            HTTP2GoAwayFrame frame = new HTTP2GoAwayFrame(header);

            frame.ReservedBit  = BufferHelper.ReadBit(header.Payload[0], 0);
            frame.LastStreamId = BufferHelper.ReadUInt31(header.Payload, 0);
            frame.ErrorCode    = BufferHelper.ReadUInt32(header.Payload, 4);

            frame.AdditionalDebugDataLength = header.PayloadLength - 8;
            if (frame.AdditionalDebugDataLength > 0)
            {
                frame.AdditionalDebugData = BufferPool.Get(frame.AdditionalDebugDataLength, true);
                Array.Copy(header.Payload, 0, frame.AdditionalDebugData, 0, frame.AdditionalDebugDataLength);
            }

            return(frame);
        }