QPACK How-To
Using QPACK encoder
Firstly, create QPACK encoder by calling nghttp3_qpack_encoder_new()
.
It requires hard_max_dtable_size parameter. When in doubt, pass
4096 for this tutorial. Optionally, call
nghttp3_qpack_encoder_set_max_dtable_capacity()
to set the maximum
size of dynamic table. You can also call
nghttp3_qpack_encoder_set_max_blocked_streams()
to set the maximum
number of streams that can be blocked.
In order to encode HTTP header fields, they must be stored in an array
of nghttp3_nv
. Then call nghttp3_qpack_encoder_encode()
. It
writes 3 buffers; pbuf, rbuf, and ebuf. They are a header block
prefix, request stream, and encoder stream respectively. A header
block prefix and request stream must be sent in this order to a stream
denoted by stream_id passed to the function. Encoder stream must be
sent to the encoder stream you setup.
In order to read decoder stream, call
nghttp3_qpack_encoder_read_decoder()
.
Once QPACK encoder is no longer used, call nghttp3_qpack_encoder_del()
to free up memory allocated for it.
Using QPACK decoder
nghttp3_qpack_decoder_new()
will create new QPACK decoder. It
requires hard_max_dtable_size and max_blocked parameters. When in
doubt, pass 4096 and 0 respectively for this tutorial.
In order to read encoder stream, call
nghttp3_qpack_decoder_read_encoder()
. This might update dynamic
table, but does not emit any header fields.
In order to read request stream, call
nghttp3_qpack_decoder_read_request()
. This is the function to emit
header fields. sctx stores a per-stream decoder state and must be
created by nghttp3_qpack_stream_context_new()
. It identifies a single
encoded header block in a particular request stream. fin must be
nonzero if and only if a passed data contains the last part of encoded
header block.
The scope of nghttp3_qpack_stream_context
is per header block,
but nghttp3_qpack_stream_context_reset()
resets its state and can be
reused for an another header block in the same stream. In general,
you can reset it when you see that
NGHTTP3_QPACK_DECODE_FLAG_FINAL
is set in *pflags. When
nghttp3_qpack_stream_context
is no longer necessary, call
nghttp3_qpack_stream_context_del()
to free up its resource.
nghttp3_qpack_decoder_read_request()
succeeds, *pflags is assigned.
If it has NGHTTP3_QPACK_DECODE_FLAG_EMIT
set, a header field
is emitted and stored in the buffer pointed by nv. If *pflags
has NGHTTP3_QPACK_DECODE_FLAG_FINAL
set, all header fields
have been successfully decoded. If *pflags has
NGHTTP3_QPACK_DECODE_FLAG_BLOCKED
set, decoding is blocked
due to required insert count, which means that more data must be read
by nghttp3_qpack_decoder_read_encoder()
.
nghttp3_qpack_decoder_read_request()
returns the number of bytes read.
When a header field is emitted, it might read data partially.
Application has to call the function repeatedly by adjusting the
pointer to data and its length until the function consumes all data or
NGHTTP3_QPACK_DECODE_FLAG_BLOCKED
is set in *pflags.
If nv is assigned, its nv->name
and nv->value
are reference counted
and already incremented by 1. If application finishes processing
these values, it must call nghttp3_rcbuf_decref(nv->name)
and nghttp3_rcbuf_decref(nv->value)
.
If an application has no interest to decode header fields for a
particular stream, call nghttp3_qpack_decoder_cancel_stream()
.
In order to tell decoding state to an encoder, QPACK decoder has to
write decoder stream by calling nghttp3_qpack_decoder_write_decoder()
.
Once QPACK decoder is no longer used, call nghttp3_qpack_decoder_del()
to free up memory allocated for it.