Merge branch 'skip2-reword-hpac-tutorial'

This commit is contained in:
Tatsuhiro Tsujikawa 2015-08-11 00:24:50 +09:00
commit e5a9f6c163
1 changed files with 69 additions and 58 deletions

View File

@ -1,118 +1,129 @@
Tutorial: HPACK API Tutorial: HPACK API
=================== ===================
In this tutorial, we describe basic use of HPACK API in nghttp2 In this tutorial, we describe basic use of nghttp2's HPACK API. We
library. We briefly describe APIs for deflating and inflating header briefly describe the APIs for deflating and inflating header fields.
fields. The example of using these APIs are presented as complete The full example of using these APIs, `deflate.c`_, is attached at the
source code `deflate.c`_. end of this page. It also resides in the examples directory in the
archive or repository.
Deflating (encoding) headers Deflating (encoding) headers
---------------------------- ----------------------------
First we need to initialize :type:`nghttp2_hd_deflater` object using First we need to initialize a :type:`nghttp2_hd_deflater` object using
`nghttp2_hd_deflate_new()` function:: the `nghttp2_hd_deflate_new()` function::
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
size_t deflate_hd_table_bufsize_max); size_t deflate_hd_table_bufsize_max);
This function allocates :type:`nghttp2_hd_deflater` object and This function allocates a :type:`nghttp2_hd_deflater` object,
initializes it and assigns its pointer to ``*deflater_ptr`` passed by initializes it, and assigns its pointer to ``*deflater_ptr``. The
parameter. The *deflate_hd_table_bufsize_max* is the upper bound of *deflate_hd_table_bufsize_max* is the upper bound of header table size
header table size the deflater will use. This will limit the memory the deflater will use. This will limit the memory usage by the
usage in deflater object for dynamic header table. If you doubt, just deflater object for the dynamic header table. If in doubt, just
specify 4096 here, which is the default upper bound of dynamic header specify 4096 here, which is the default upper bound of dynamic header
table buffer size. table buffer size.
To encode header fields, `nghttp2_hd_deflate_hd()` function:: To encode header fields, use the `nghttp2_hd_deflate_hd()` function::
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
uint8_t *buf, size_t buflen, uint8_t *buf, size_t buflen,
const nghttp2_nv *nva, size_t nvlen); const nghttp2_nv *nva, size_t nvlen);
The *deflater* is the deflater object initialized by The *deflater* is the deflater object initialized by
`nghttp2_hd_deflate_new()` function described above. The *buf* is a `nghttp2_hd_deflate_new()` described above. The encoded byte string is
pointer to buffer to store encoded byte string. The *buflen* is written to the buffer *buf*, which has length *buflen*. The *nva* is
capacity of *buf*. The *nva* is a pointer to :type:`nghttp2_nv`, a pointer to an array of headers fields, each of type
which is an array of header fields to deflate. The *nvlen* is the :type:`nghttp2_nv`. *nvlen* is the number of header fields which
number of header fields which *nva* contains. *nva* contains.
It is important to initialize and assign all members of It is important to initialize and assign all members of
:type:`nghttp2_nv`. If a header field should not be inserted in :type:`nghttp2_nv`. For security sensitive header fields (such as
dynamic header table for a security reason, set cookies), set the :macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in
:macro:`NGHTTP2_NV_FLAG_NO_INDEX` flag in :member:`nghttp2_nv.flags`. :member:`nghttp2_nv.flags`. Setting this flag prevents recovery of
sensitive header fields by compression based attacks: This is achieved
by not inserting the header field into the dynamic header table.
`nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The `nghttp2_hd_deflate_hd()` processes all headers given in *nva*. The
*nva* must include all request or response header fields to be sent in *nva* must include all request or response header fields to be sent in
one HEADERS (or optionally following (multiple) CONTINUATION one HEADERS (or optionally following (multiple) CONTINUATION
frame(s)). The *buf* must have enough space to store the encoded frame(s)). The *buf* must have enough space to store the encoded
result. Otherwise, the function will fail. To estimate the upper result, otherwise the function will fail. To estimate the upper bound
bound of encoded result, use `nghttp2_hd_deflate_bound()` function:: of the encoded result length, use `nghttp2_hd_deflate_bound()`::
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nva, size_t nvlen); const nghttp2_nv *nva, size_t nvlen);
Pass this function with the same parameters *deflater*, *nva* and Pass this function the same parameters (*deflater*, *nva*, and
*nvlen* which will be passed to `nghttp2_hd_deflate_hd()`. *nvlen*) which will be passed to `nghttp2_hd_deflate_hd()`.
The subsequent call of `nghttp2_hd_deflate_hd()` will use current Subsequent calls to `nghttp2_hd_deflate_hd()` will use the current
encoder state and perform differential encoding which is the encoder state and perform differential encoding, which yields HPAC's
fundamental compression gain for HPACK. fundamental compression gain.
Once `nghttp2_hd_deflate_hd()` fails, it cannot be undone and its If `nghttp2_hd_deflate_hd()` fails, the failure is fatal and any
further call with the same deflater object shall fail. So it is very further calls with the same deflater object will fail. Thus it's very
important to use `nghttp2_hd_deflate_bound()` to know the required important to use `nghttp2_hd_deflate_bound()` to determine the
size of buffer. required size of the output buffer.
To delete :type:`nghttp2_hd_deflater` object, use `nghttp2_hd_deflate_del()` To delete a :type:`nghttp2_hd_deflater` object, use the
function. `nghttp2_hd_deflate_del()` function.
Inflating (decoding) headers Inflating (decoding) headers
---------------------------- ----------------------------
We use :type:`nghttp2_hd_inflater` object to inflate compressed header A :type:`nghttp2_hd_inflater` object is used to inflate compressed
data. To initialize the object, use `nghttp2_hd_inflate_new()`:: header data. To initialize the object, use
`nghttp2_hd_inflate_new()`::
int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr); int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr);
To inflate header data, use `nghttp2_hd_inflate_hd()` function:: To inflate header data, use `nghttp2_hd_inflate_hd()`::
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags, nghttp2_nv *nv_out, int *inflate_flags,
uint8_t *in, size_t inlen, int in_final); uint8_t *in, size_t inlen, int in_final);
`nghttp2_hd_inflate_hd()` reads a stream of bytes and outputs a single
header field at a time. Multiple calls are normally required to read a
full stream of bytes and output all of the header fields.
The *inflater* is the inflater object initialized above. The *nv_out* The *inflater* is the inflater object initialized above. The *nv_out*
is a pointer to :type:`nghttp2_nv` to store the result. The *in* is a is a pointer to a :type:`nghttp2_nv` into which one header field may
pointer to input data and *inlen* is its length. The caller is not be stored. The *in* is a pointer to input data, and *inlen* is its
required to specify whole deflated header data to *in* at once. It length. The caller is not required to specify the whole deflated
can call this function multiple times for portion of the data in header data via *in* at once: Instead it can call this function
streaming way. If *in_final* is nonzero, it tells the function that multiple times as additional data bytes become available. If
the passed data is the final sequence of deflated header data. The *in_final* is nonzero, it tells the function that the passed data is
*inflate_flags* is output parameter and successful call of this the final sequence of deflated header data.
function stores a set of flags in it. It will be described later.
The *inflate_flags* is an output parameter; on success the function
sets it to a bitset of flags. It will be described later.
This function returns when each header field is inflated. When this This function returns when each header field is inflated. When this
happens, the function sets :macro:`NGHTTP2_HD_INFLATE_EMIT` flag to happens, the function sets the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag
*inflate_flag* parameter and header field is stored in *nv_out*. The in *inflate_flags*, and a header field is stored in *nv_out*. The
return value indicates the number of data read from *in* to processed return value indicates the number of bytes read from *in* processed so
so far. It may be less than *inlen*. The caller should call the far, which may be less than *inlen*. The caller should call the
function repeatedly until all data are processed by adjusting *in* and function repeatedly until all bytes are processed. Processed bytes
*inlen* with the processed bytes. should be removed from *in*, and *inlen* should be adjusted
appropriately.
If *in_final* is nonzero and all given data was processed, the If *in_final* is nonzero and all given data was processed, the
function sets :macro:`NGHTTP2_HD_INFLATE_FINAL` flag to function sets the :macro:`NGHTTP2_HD_INFLATE_FINAL` flag in
*inflate_flag*. If the caller sees this flag set, call *inflate_flags*. When you see this flag set, call the
`nghttp2_hd_inflate_end_headers()` function. `nghttp2_hd_inflate_end_headers()` function.
If *in_final* is zero and :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is not If *in_final* is zero and the :macro:`NGHTTP2_HD_INFLATE_EMIT` flag is
set, it indicates that all given data was processed. The caller is not set, it indicates that all given data was processed. The caller
required to pass subsequent data. is required to pass additional data.
It is important to note that the function may produce one or more It is important to note that the function may produce one or more
header fields even if *inlen* is 0 when *in_final* is nonzero, due to header fields even if *inlen* is 0 when *in_final* is nonzero, due to
differential encoding. differential encoding.
The example use of `nghttp2_hd_inflate_hd()` is shown in Example usage of `nghttp2_hd_inflate_hd()` is shown in the
`inflate_header_block()` function in `deflate.c`_. `inflate_header_block()` function in `deflate.c`_.
To delete :type:`nghttp2_hd_inflater` object, use `nghttp2_hd_inflate_del()` Finally, to delete a :type:`nghttp2_hd_inflater` object, use
function. `nghttp2_hd_inflate_del()`.