Search in sources :

Example 1 with IndexType

use of io.netty.handler.codec.http2.HpackUtil.IndexType in project netty by netty.

the class HpackDecoder method decode.

/**
     * Decode the header block into header fields.
     * <p>
     * This method assumes the entire header block is contained in {@code in}.
     */
public void decode(int streamId, ByteBuf in, Http2Headers headers) throws Http2Exception {
    int index = 0;
    long headersLength = 0;
    int nameLength = 0;
    int valueLength = 0;
    byte state = READ_HEADER_REPRESENTATION;
    boolean huffmanEncoded = false;
    CharSequence name = null;
    IndexType indexType = IndexType.NONE;
    while (in.isReadable()) {
        switch(state) {
            case READ_HEADER_REPRESENTATION:
                byte b = in.readByte();
                if (maxDynamicTableSizeChangeRequired && (b & 0xE0) != 0x20) {
                    // HpackEncoder MUST signal maximum dynamic table size change
                    throw MAX_DYNAMIC_TABLE_SIZE_CHANGE_REQUIRED;
                }
                if (b < 0) {
                    // Indexed Header Field
                    index = b & 0x7F;
                    switch(index) {
                        case 0:
                            throw DECODE_ILLEGAL_INDEX_VALUE;
                        case 0x7F:
                            state = READ_INDEXED_HEADER;
                            break;
                        default:
                            headersLength = indexHeader(streamId, index, headers, headersLength);
                    }
                } else if ((b & 0x40) == 0x40) {
                    // Literal Header Field with Incremental Indexing
                    indexType = IndexType.INCREMENTAL;
                    index = b & 0x3F;
                    switch(index) {
                        case 0:
                            state = READ_LITERAL_HEADER_NAME_LENGTH_PREFIX;
                            break;
                        case 0x3F:
                            state = READ_INDEXED_HEADER_NAME;
                            break;
                        default:
                            // Index was stored as the prefix
                            name = readName(index);
                            state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
                    }
                } else if ((b & 0x20) == 0x20) {
                    // Dynamic Table Size Update
                    index = b & 0x1F;
                    if (index == 0x1F) {
                        state = READ_MAX_DYNAMIC_TABLE_SIZE;
                    } else {
                        setDynamicTableSize(index);
                        state = READ_HEADER_REPRESENTATION;
                    }
                } else {
                    // Literal Header Field without Indexing / never Indexed
                    indexType = ((b & 0x10) == 0x10) ? IndexType.NEVER : IndexType.NONE;
                    index = b & 0x0F;
                    switch(index) {
                        case 0:
                            state = READ_LITERAL_HEADER_NAME_LENGTH_PREFIX;
                            break;
                        case 0x0F:
                            state = READ_INDEXED_HEADER_NAME;
                            break;
                        default:
                            // Index was stored as the prefix
                            name = readName(index);
                            state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
                    }
                }
                break;
            case READ_MAX_DYNAMIC_TABLE_SIZE:
                setDynamicTableSize(decodeULE128(in, (long) index));
                state = READ_HEADER_REPRESENTATION;
                break;
            case READ_INDEXED_HEADER:
                headersLength = indexHeader(streamId, decodeULE128(in, index), headers, headersLength);
                state = READ_HEADER_REPRESENTATION;
                break;
            case READ_INDEXED_HEADER_NAME:
                // Header Name matches an entry in the Header Table
                name = readName(decodeULE128(in, index));
                state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
                break;
            case READ_LITERAL_HEADER_NAME_LENGTH_PREFIX:
                b = in.readByte();
                huffmanEncoded = (b & 0x80) == 0x80;
                index = b & 0x7F;
                if (index == 0x7f) {
                    state = READ_LITERAL_HEADER_NAME_LENGTH;
                } else {
                    if (index > maxHeaderListSizeGoAway - headersLength) {
                        headerListSizeExceeded(maxHeaderListSizeGoAway);
                    }
                    nameLength = index;
                    state = READ_LITERAL_HEADER_NAME;
                }
                break;
            case READ_LITERAL_HEADER_NAME_LENGTH:
                // Header Name is a Literal String
                nameLength = decodeULE128(in, index);
                if (nameLength > maxHeaderListSizeGoAway - headersLength) {
                    headerListSizeExceeded(maxHeaderListSizeGoAway);
                }
                state = READ_LITERAL_HEADER_NAME;
                break;
            case READ_LITERAL_HEADER_NAME:
                // Wait until entire name is readable
                if (in.readableBytes() < nameLength) {
                    throw notEnoughDataException(in);
                }
                name = readStringLiteral(in, nameLength, huffmanEncoded);
                state = READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX;
                break;
            case READ_LITERAL_HEADER_VALUE_LENGTH_PREFIX:
                b = in.readByte();
                huffmanEncoded = (b & 0x80) == 0x80;
                index = b & 0x7F;
                switch(index) {
                    case 0x7f:
                        state = READ_LITERAL_HEADER_VALUE_LENGTH;
                        break;
                    case 0:
                        headersLength = insertHeader(streamId, headers, name, EMPTY_STRING, indexType, headersLength);
                        state = READ_HEADER_REPRESENTATION;
                        break;
                    default:
                        // Check new header size against max header size
                        if ((long) index + nameLength > maxHeaderListSizeGoAway - headersLength) {
                            headerListSizeExceeded(maxHeaderListSizeGoAway);
                        }
                        valueLength = index;
                        state = READ_LITERAL_HEADER_VALUE;
                }
                break;
            case READ_LITERAL_HEADER_VALUE_LENGTH:
                // Header Value is a Literal String
                valueLength = decodeULE128(in, index);
                // Check new header size against max header size
                if ((long) valueLength + nameLength > maxHeaderListSizeGoAway - headersLength) {
                    headerListSizeExceeded(maxHeaderListSizeGoAway);
                }
                state = READ_LITERAL_HEADER_VALUE;
                break;
            case READ_LITERAL_HEADER_VALUE:
                // Wait until entire value is readable
                if (in.readableBytes() < valueLength) {
                    throw notEnoughDataException(in);
                }
                CharSequence value = readStringLiteral(in, valueLength, huffmanEncoded);
                headersLength = insertHeader(streamId, headers, name, value, indexType, headersLength);
                state = READ_HEADER_REPRESENTATION;
                break;
            default:
                throw new Error("should not reach here state: " + state);
        }
    }
    // corruption
    if (headersLength > maxHeaderListSize) {
        headerListSizeExceeded(streamId, maxHeaderListSize, true);
    }
}
Also used : Http2Exception.connectionError(io.netty.handler.codec.http2.Http2Exception.connectionError) IndexType(io.netty.handler.codec.http2.HpackUtil.IndexType)

Aggregations

IndexType (io.netty.handler.codec.http2.HpackUtil.IndexType)1 Http2Exception.connectionError (io.netty.handler.codec.http2.Http2Exception.connectionError)1