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 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 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 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 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);
        }
示例#6
0
        public void Decode(HTTP2Stream context, Stream stream, List <KeyValuePair <string, string> > to)
        {
            int headerType = stream.ReadByte();

            while (headerType != -1)
            {
                byte firstDataByte = (byte)headerType;

                // https://http2.github.io/http2-spec/compression.html#indexed.header.representation
                if (BufferHelper.ReadBit(firstDataByte, 0) == 1)
                {
                    var header = ReadIndexedHeader(firstDataByte, stream);

                    if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
                    {
                        HTTPManager.Logger.Information("HPACKEncoder", string.Format("[{0}] Decode - IndexedHeader: {1}", context.Id, header.ToString()));
                    }

                    to.Add(header);
                }
                else if (BufferHelper.ReadValue(firstDataByte, 0, 1) == 1)
                {
                    // https://http2.github.io/http2-spec/compression.html#literal.header.with.incremental.indexing

                    if (BufferHelper.ReadValue(firstDataByte, 2, 7) == 0)
                    {
                        // Literal Header Field with Incremental Indexing — New Name
                        var header = ReadLiteralHeaderFieldWithIncrementalIndexing_NewName(firstDataByte, stream);

                        if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
                        {
                            HTTPManager.Logger.Information("HPACKEncoder", string.Format("[{0}] Decode - LiteralHeaderFieldWithIncrementalIndexing_NewName: {1}", context.Id, header.ToString()));
                        }

                        this.responseTable.Add(header);
                        to.Add(header);
                    }
                    else
                    {
                        // Literal Header Field with Incremental Indexing — Indexed Name
                        var header = ReadLiteralHeaderFieldWithIncrementalIndexing_IndexedName(firstDataByte, stream);

                        if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
                        {
                            HTTPManager.Logger.Information("HPACKEncoder", string.Format("[{0}] Decode - LiteralHeaderFieldWithIncrementalIndexing_IndexedName: {1}", context.Id, header.ToString()));
                        }

                        this.responseTable.Add(header);
                        to.Add(header);
                    }
                }
                else if (BufferHelper.ReadValue(firstDataByte, 0, 3) == 0)
                {
                    // https://http2.github.io/http2-spec/compression.html#literal.header.without.indexing

                    if (BufferHelper.ReadValue(firstDataByte, 4, 7) == 0)
                    {
                        // Literal Header Field without Indexing — New Name
                        var header = ReadLiteralHeaderFieldwithoutIndexing_NewName(firstDataByte, stream);

                        if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
                        {
                            HTTPManager.Logger.Information("HPACKEncoder", string.Format("[{0}] Decode - LiteralHeaderFieldwithoutIndexing_NewName: {1}", context.Id, header.ToString()));
                        }

                        to.Add(header);
                    }
                    else
                    {
                        // Literal Header Field without Indexing — Indexed Name
                        var header = ReadLiteralHeaderFieldwithoutIndexing_IndexedName(firstDataByte, stream);

                        if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
                        {
                            HTTPManager.Logger.Information("HPACKEncoder", string.Format("[{0}] Decode - LiteralHeaderFieldwithoutIndexing_IndexedName: {1}", context.Id, header.ToString()));
                        }

                        to.Add(header);
                    }
                }
                else if (BufferHelper.ReadValue(firstDataByte, 0, 3) == 1)
                {
                    // https://http2.github.io/http2-spec/compression.html#literal.header.never.indexed

                    if (BufferHelper.ReadValue(firstDataByte, 4, 7) == 0)
                    {
                        // Literal Header Field Never Indexed — New Name
                        var header = ReadLiteralHeaderFieldNeverIndexed_NewName(firstDataByte, stream);

                        if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
                        {
                            HTTPManager.Logger.Information("HPACKEncoder", string.Format("[{0}] Decode - LiteralHeaderFieldNeverIndexed_NewName: {1}", context.Id, header.ToString()));
                        }

                        to.Add(header);
                    }
                    else
                    {
                        // Literal Header Field Never Indexed — Indexed Name
                        var header = ReadLiteralHeaderFieldNeverIndexed_IndexedName(firstDataByte, stream);

                        if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
                        {
                            HTTPManager.Logger.Information("HPACKEncoder", string.Format("[{0}] Decode - LiteralHeaderFieldNeverIndexed_IndexedName: {1}", context.Id, header.ToString()));
                        }

                        to.Add(header);
                    }
                }
                else if (BufferHelper.ReadValue(firstDataByte, 0, 2) == 1)
                {
                    // https://http2.github.io/http2-spec/compression.html#encoding.context.update

                    UInt32 newMaxSize = DecodeInteger(5, firstDataByte, stream);

                    if (HTTPManager.Logger.Level <= Logger.Loglevels.Information)
                    {
                        HTTPManager.Logger.Information("HPACKEncoder", string.Format("[{0}] Decode - Dynamic Table Size Update: {1}", context.Id, newMaxSize));
                    }

                    //this.settingsRegistry[HTTP2Settings.HEADER_TABLE_SIZE] = (UInt16)newMaxSize;
                    this.responseTable.MaxDynamicTableSize = (UInt16)newMaxSize;
                }
                else
                {
                    // ERROR
                }

                headerType = stream.ReadByte();
            }
        }
示例#7
0
        private string DecodeString(Stream stream)
        {
            byte   start        = (byte)stream.ReadByte();
            bool   rawString    = BufferHelper.ReadBit(start, 0) == 0;
            UInt32 stringLength = DecodeInteger(7, start, stream);

            if (rawString)
            {
                byte[] buffer = BufferPool.Get(stringLength, true);

                stream.Read(buffer, 0, (int)stringLength);

                BufferPool.Release(buffer);

                return(System.Text.Encoding.UTF8.GetString(buffer, 0, (int)stringLength));
            }
            else
            {
                var  node        = HuffmanEncoder.GetRoot();
                byte currentByte = (byte)stream.ReadByte();
                byte bitIdx      = 0; // 0..7

                using (BufferPoolMemoryStream bufferStream = new BufferPoolMemoryStream())
                {
                    do
                    {
                        byte bitValue = BufferHelper.ReadBit(currentByte, bitIdx);

                        if (++bitIdx > 7)
                        {
                            stringLength--;

                            if (stringLength > 0)
                            {
                                bitIdx      = 0;
                                currentByte = (byte)stream.ReadByte();
                            }
                        }

                        node = HuffmanEncoder.GetNext(node, bitValue);

                        if (node.Value != 0)
                        {
                            if (node.Value != HuffmanEncoder.EOS)
                            {
                                bufferStream.WriteByte((byte)node.Value);
                            }

                            node = HuffmanEncoder.GetRoot();
                        }
                    } while (stringLength > 0);

                    byte[] buffer = bufferStream.ToArray(true);

                    string result = System.Text.Encoding.UTF8.GetString(buffer, 0, (int)bufferStream.Length);

                    BufferPool.Release(buffer);

                    return(result);
                }
            }
        }