예제 #1
0
        public static (int bytesConsumed, HttpHeaderData) DecodeHeader(ReadOnlySpan <byte> buffer)
        {
            switch (BitOperations.LeadingZeroCount(buffer[0]) - 24) // byte 'b' is extended to uint, so will have 24 extra 0s.
            {
            case 0:                                                 // Indexed Header Field
            {
                if ((buffer[0] & 0b0100_0000) == 0)
                {
                    throw new Exception("QPack dynamic table is not yet supported.");
                }

                (int bytesConsumed, int staticIndex) = DecodeInteger(buffer, 0b0011_1111);

                var staticHeader = s_staticTable[staticIndex];
                var header       = new HttpHeaderData(staticHeader.Name, staticHeader.Value, raw: buffer.Slice(0, bytesConsumed).ToArray());

                return(bytesConsumed, header);
            }

            case 1:     // Literal Header Field With Name Reference
            {
                if ((buffer[0] & 0b0001_0000) == 0)
                {
                    throw new Exception("QPack dynamic table is not yet supported.");
                }

                (int nameLength, int staticIndex) = DecodeInteger(buffer, 0b0000_1111);
                (int valueLength, string value)   = DecodeString(buffer.Slice(nameLength), 0b0111_1111);

                int headerLength = nameLength + valueLength;
                var header       = new HttpHeaderData(s_staticTable[staticIndex].Name, value, raw: buffer.Slice(0, headerLength).ToArray());

                return(headerLength, header);
            }

            case 2:     // Literal Header Field Without Name Reference
            {
                (int nameLength, string name)   = DecodeString(buffer, 0b0000_0111);
                (int valueLength, string value) = DecodeString(buffer.Slice(nameLength), 0b0111_1111);

                int headerLength = nameLength + valueLength;
                var header       = new HttpHeaderData(name, value, raw: buffer.Slice(0, headerLength).ToArray());

                return(headerLength, header);
            }

            case 3:     // Indexed Header Field With Post-Base Index
            default:    // Literal Header Field With Post-Base Name Reference (at least 4 zeroes, maybe more)
                throw new Exception("QPack dynamic table is not yet supported.");
            }
        }
예제 #2
0
        public static (int bytesConsumed, HttpHeaderData) DecodeHeader(ReadOnlySpan <byte> buffer)
        {
            int firstByte = buffer[0];

            // Indexed Header Field, dynamic.
            if ((firstByte & 0b1100_0000) == 0b1000_0000)
            {
                throw new Exception("QPack dynamic table is not yet supported.");
            }

            // Indexed Header Field, static.
            if ((firstByte & 0b1100_0000) == 0b1100_0000)
            {
                (int bytesConsumed, int staticIndex) = DecodeInteger(buffer, 0b1100_0000);

                var staticHeader = s_staticTable[staticIndex];
                var header       = new HttpHeaderData(staticHeader.Name, staticHeader.Value, raw: buffer.Slice(0, bytesConsumed).ToArray());

                return(bytesConsumed, header);
            }

            // Indexed Header Field With Post-Base Index
            if ((firstByte & 0b1111_0000) == 0b0001_0000)
            {
                throw new Exception("QPack dynamic table is not yet supported.");
            }

            // Literal Header Field With Name Reference
            if ((firstByte & 0b1100_0000) == 0b0100_0000)
            {
                if ((firstByte & 0b0001_0000) != 0)
                {
                    throw new Exception("QPack dynamic table is not yet supported.");
                }

                (int nameLength, int staticIndex) = DecodeInteger(buffer, 0b1111_0000);
                (int valueLength, string value)   = DecodeString(buffer.Slice(nameLength), 0b1000_0000);

                int headerLength = nameLength + valueLength;
                var header       = new HttpHeaderData(s_staticTable[staticIndex].Name, value, raw: buffer.Slice(0, headerLength).ToArray());

                return(headerLength, header);
            }

            // Literal Header Field With Post-Base Name Reference.
            if ((firstByte & 0b1111_0000) == 0b0000_0000)
            {
                throw new Exception("QPack dynamic table is not yet supported.");
            }

            // Literal Header Field Without Name Reference.
            if ((firstByte & 0b1110_0000) == 0b0010_0000)
            {
                (int nameLength, string name)   = DecodeString(buffer, 0b1111_1000);
                (int valueLength, string value) = DecodeString(buffer.Slice(nameLength), 0b1000_0000);

                int headerLength = nameLength + valueLength;
                var header       = new HttpHeaderData(name, value, raw: buffer.Slice(0, headerLength).ToArray());

                return(headerLength, header);
            }

            throw new Exception("Invalid QPack.");
        }