Class QpackDecoder
ReentrantLock, say, or one thread).
QpackDecoder qpack = new QpackDecoder(4096, 16); // what our SETTINGS advertise
// HEADERS on a request stream:
List<HeaderField> fields = qpack.decode(streamId, headers.fieldSection());
if (fields == null) { ... blocked: wait for the encoder stream ... }
// Bytes from the peer's QPACK encoder stream:
for (long ready : qpack.onEncoderStream(bytes)) resumeStream(ready, qpack.resume(ready));
// Then send what the peer's encoder needs to hear on our QPACK decoder stream:
decoderStream.write(qpack.decoderStreamBytes());
The decoder handles every field line representation (§4.5): indexed (static, dynamic
relative and post-base), literal with a name reference (static, dynamic and post-base) and
literal with a literal name. A literal's 'N' bit comes back as HeaderField.sensitive().
A field section whose Required Insert Count is above the number of entries received so far is
blocked: decode(long, byte[]) keeps it and returns null, and onEncoderStream(byte[]) reports
its stream once enough entries have arrived, after which resume(long) decodes it. At most
maxBlockedStreams streams may be blocked (our SETTINGS_QPACK_BLOCKED_STREAMS); one more
is a connection error QPACK_DECOMPRESSION_FAILED (§2.2.1).
The decoder queues the decoder-stream instructions the encoder needs (§4.4): a Section
Acknowledgment for each decoded section that used the dynamic table, a Stream Cancellation for
each cancelStream(long), and an Insert Count Increment for entries not otherwise
acknowledged, all returned by decoderStreamBytes().
Limits: setMaxFieldSectionSize(long) (our SETTINGS_MAX_FIELD_SECTION_SIZE, default 64
KiB) bounds a decoded section, counting name + value + 32 per field; a larger one raises
FieldSectionSizeException, a stream error, after the section has been processed and
acknowledged, keeping only the fields within the limit. The table capacity bounds the encoder
stream's instructions: an entry that cannot fit is an error as soon as its length is read.
Any other malformed field section is a connection error QPACK_DECOMPRESSION_FAILED, and any
malformed encoder instruction a connection error QPACK_ENCODER_STREAM_ERROR; the decoder must not
be used after a connection error.
-
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final longThe default limit on a decoded field section, 64 KiB. -
Constructor Summary
ConstructorsConstructorDescriptionA static-table-only decoder: SETTINGS_QPACK_MAX_TABLE_CAPACITY and BLOCKED_STREAMS of 0.QpackDecoder(long maxTableCapacity, int maxBlockedStreams) A decoder for the given settings, which this endpoint must advertise in its SETTINGS. -
Method Summary
Modifier and TypeMethodDescriptionintThe number of streams with a blocked field section.voidcancelStream(long streamId) Reports that a stream was reset, or that its reading was abandoned, before all its field sections were decoded.decode(long streamId, byte[] section) Decodes one encoded field section (the payload of a HEADERS or PUSH_PROMISE frame).byte[]Takes the decoder-stream instructions queued so far, ending with an Insert Count Increment for any entries received but not yet acknowledged; send them on the QPACK decoder stream.longThe current capacity of the dynamic table, as last set by the peer's encoder.dynamicTableEntry(long absoluteIndex) The dynamic table entry with this absolute index (0 is the first ever inserted), or null if absent.intThe number of entries in the dynamic table.longThe current size of the dynamic table in octets (entries plus 32 each).longThe number of entries inserted so far (the Insert Count).booleanisBlocked(long streamId) Whether a field section of this stream is waiting for encoder-stream updates.intHow many streams may wait for the encoder stream: our SETTINGS_QPACK_BLOCKED_STREAMS.longThe largest decoded field section accepted.longThe largest dynamic table the encoder may use: our SETTINGS_QPACK_MAX_TABLE_CAPACITY.onEncoderStream(byte[] data) Processes bytes from the peer's QPACK encoder stream; seeonEncoderStream(byte[], int, int).onEncoderStream(byte[] data, int offset, int length) Processes bytes from the peer's QPACK encoder stream (§4.3), in any pieces: an instruction split between calls is completed by the next.resume(long streamId) Decodes the blocked field section of a stream thatonEncoderStream(byte[])reported as ready.voidsetMaxFieldSectionSize(long maxFieldSectionSize) SETTINGS_MAX_FIELD_SECTION_SIZE: the largest decoded field section accepted.
-
Field Details
-
DEFAULT_MAX_FIELD_SECTION_SIZE
public static final long DEFAULT_MAX_FIELD_SECTION_SIZEThe default limit on a decoded field section, 64 KiB.- See Also:
-
-
Constructor Details
-
QpackDecoder
public QpackDecoder()A static-table-only decoder: SETTINGS_QPACK_MAX_TABLE_CAPACITY and BLOCKED_STREAMS of 0. -
QpackDecoder
public QpackDecoder(long maxTableCapacity, int maxBlockedStreams) A decoder for the given settings, which this endpoint must advertise in its SETTINGS.- Parameters:
maxTableCapacity- SETTINGS_QPACK_MAX_TABLE_CAPACITY: the largest dynamic table the peer's encoder may usemaxBlockedStreams- SETTINGS_QPACK_BLOCKED_STREAMS: how many streams may wait for encoder-stream updates at once
-
-
Method Details
-
setMaxFieldSectionSize
public void setMaxFieldSectionSize(long maxFieldSectionSize) SETTINGS_MAX_FIELD_SECTION_SIZE: the largest decoded field section accepted.- Parameters:
maxFieldSectionSize- the limit in octets
-
maxFieldSectionSize
public long maxFieldSectionSize()The largest decoded field section accepted.- Returns:
- the limit in octets
-
maxTableCapacity
public long maxTableCapacity()The largest dynamic table the encoder may use: our SETTINGS_QPACK_MAX_TABLE_CAPACITY.- Returns:
- the capacity in octets
-
maxBlockedStreams
public int maxBlockedStreams()How many streams may wait for the encoder stream: our SETTINGS_QPACK_BLOCKED_STREAMS.- Returns:
- the number of streams
-
insertCount
public long insertCount()The number of entries inserted so far (the Insert Count).- Returns:
- the Insert Count
-
dynamicTableSize
public long dynamicTableSize()The current size of the dynamic table in octets (entries plus 32 each).- Returns:
- the size in octets
-
dynamicTableCapacity
public long dynamicTableCapacity()The current capacity of the dynamic table, as last set by the peer's encoder.- Returns:
- the capacity in octets
-
dynamicTableLength
public int dynamicTableLength()The number of entries in the dynamic table.- Returns:
- the number of entries
-
dynamicTableEntry
The dynamic table entry with this absolute index (0 is the first ever inserted), or null if absent.- Parameters:
absoluteIndex- the absolute index- Returns:
- the entry, or null
-
isBlocked
public boolean isBlocked(long streamId) Whether a field section of this stream is waiting for encoder-stream updates.- Parameters:
streamId- the stream- Returns:
- whether it is blocked
-
blockedStreams
public int blockedStreams()The number of streams with a blocked field section.- Returns:
- the number of blocked streams
-
decode
Decodes one encoded field section (the payload of a HEADERS or PUSH_PROMISE frame).- Parameters:
streamId- the stream the section came onsection- the encoded field section- Returns:
- the fields in order, with never-indexed literals marked
HeaderField.sensitive(); or null if the section is blocked, in which case the decoder keeps a copy of it - Throws:
FieldSectionSizeException- if the section is larger than the limit (a stream error)Http3Exception- a connection error QPACK_DECOMPRESSION_FAILED if the section is malformed or one stream too many would be blockedIllegalStateException- if a section of this stream is already blocked
-
resume
Decodes the blocked field section of a stream thatonEncoderStream(byte[])reported as ready.- Parameters:
streamId- the stream- Returns:
- the decoded fields
- Throws:
IllegalStateException- if the stream has no blocked section, or it is still blockedHttp3Exception- asdecode(long, byte[])
-
cancelStream
public void cancelStream(long streamId) Reports that a stream was reset, or that its reading was abandoned, before all its field sections were decoded. Drops any blocked section and queues a Stream Cancellation (§4.4.2), unless the table capacity is 0 and the encoder cannot have referenced the table.- Parameters:
streamId- the stream
-
decoderStreamBytes
public byte[] decoderStreamBytes()Takes the decoder-stream instructions queued so far, ending with an Insert Count Increment for any entries received but not yet acknowledged; send them on the QPACK decoder stream.- Returns:
- the bytes, possibly none
-
onEncoderStream
Processes bytes from the peer's QPACK encoder stream; seeonEncoderStream(byte[], int, int).- Parameters:
data- the bytes- Returns:
- the streams that can now be resumed
- Throws:
Http3Exception- a connection error QPACK_ENCODER_STREAM_ERROR for an invalid instruction
-
onEncoderStream
Processes bytes from the peer's QPACK encoder stream (§4.3), in any pieces: an instruction split between calls is completed by the next.- Parameters:
data- the bytesoffset- where they start indatalength- how many- Returns:
- the streams whose blocked field sections can now be decoded with
resume(long), each reported once, in the order they blocked - Throws:
Http3Exception- a connection error QPACK_ENCODER_STREAM_ERROR for an invalid instruction
-