Add HPACK deflation API

This commit is contained in:
Tatsuhiro Tsujikawa 2014-05-13 23:42:55 +09:00
parent 03e2dabea9
commit 7b9a8acc22
13 changed files with 367 additions and 67 deletions

View File

@ -2716,6 +2716,117 @@ int nghttp2_check_header_value(const uint8_t *value, size_t len);
/* HPACK API */
struct nghttp2_hd_deflater;
/**
* @struct
*
* HPACK deflater object.
*/
typedef struct nghttp2_hd_deflater nghttp2_hd_deflater;
/**
* @function
*
* Initializes |*deflater_ptr| for deflating name/values pairs.
*
* The |deflate_hd_table_bufsize_max| is the upper bound of header
* table size the deflater will use.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
*/
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
size_t deflate_hd_table_bufsize_max);
/**
* @function
*
* Deallocates any resources allocated for |deflater|.
*/
void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater);
/**
* @function
*
* Sets the availability of reference set in the |deflater|. If
* |no_refset| is nonzero, the deflater will first emit "Reference Set
* Emptying" in the each subsequent invocation of
* `nghttp2_hd_deflate_hd()` to clear up reference set. By default,
* the deflater uses reference set.
*/
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset);
/**
* @function
*
* Changes header table size of the |deflater| to
* |settings_hd_table_bufsize_max| bytes. This may trigger eviction
* in the dynamic table.
*
* The |settings_hd_table_bufsize_max| should be the value received in
* SETTINGS_HEADER_TABLE_SIZE.
*
* The deflater never uses more memory than
* ``deflate_hd_table_bufsize_max`` bytes specified in
* `nghttp2_hd_deflate_new()`. Therefore, if
* |settings_hd_table_bufsize_max| > ``deflate_hd_table_bufsize_max``,
* resulting maximum table size becomes
* ``deflate_hd_table_bufsize_max``.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
*/
int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t settings_hd_table_bufsize_max);
/**
* @function
*
* Deflates the |nva|, which has the |nvlen| name/value pairs, into
* the |buf| of length |buflen|.
*
* If |buf| is not large enough to store the deflated header block,
* this function fails with :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`. The
* caller should use `nghttp2_hd_deflate_bound()` to know the upper
* bound of buffer size required to deflate given header name/value
* pairs.
*
* Once this function fails, subsequent call of this function always
* returns :enum:`NGHTTP2_ERR_HEADER_COMP`.
*
* After this function returns, it is safe to delete the |nva|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
* :enum:`NGHTTP2_ERR_HEADER_COMP`
* Deflation process has failed.
* :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE`
* The provided |buflen| size is too small to hold the output.
*/
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
uint8_t *buf, size_t buflen,
nghttp2_nv *nva, size_t nvlen);
/**
* @function
*
* Returns an upper bound on the compressed size after deflation of
* |nva| of length |nvlen|.
*/
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nva, size_t nvlen);
struct nghttp2_hd_inflater;
/**

View File

@ -177,6 +177,37 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs)
}
}
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len)
{
nghttp2_buf_chain *chain;
chain = malloc(sizeof(nghttp2_buf_chain));
if(chain == NULL) {
return NGHTTP2_ERR_NOMEM;
}
chain->next = NULL;
nghttp2_buf_wrap_init(&chain->buf, begin, len);
bufs->offset = 0;
bufs->head = chain;
bufs->cur = bufs->head;
bufs->chunk_length = len;
bufs->chunk_used = 1;
bufs->max_chunk = 1;
bufs->chunk_keep = 1;
return 0;
}
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs)
{
free(bufs->head);
}
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs)
{
nghttp2_buf_chain *ci;

View File

@ -207,6 +207,27 @@ int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length,
*/
void nghttp2_bufs_free(nghttp2_bufs *bufs);
/*
* Initializes |bufs| using supplied buffer |begin| of length |len|.
* The first buffer bufs->head uses buffer |begin|. The buffer size
* is fixed and no allocate extra chunk buffer is allocated. In other
* words, max_chunk = chunk_keep = 1. To free the resource allocated
* for |bufs|, use nghttp2_bufs_wrap_free().
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len);
/*
* Frees any related resource to the |bufs|. This function does not
* free supplied buffer provided in nghttp2_bufs_wrap_init().
*/
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs);
/*
* Appends the |data| of length |len| to the |bufs|. The write starts
* at bufs->cur->buf.last. A new buffers will be allocated to store

View File

@ -364,7 +364,7 @@ int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
buf->last = buf->pos;
/* This call will adjust buf->last to the correct position */
rv = nghttp2_hd_deflate_hd(deflater, bufs, frame->nva, frame->nvlen);
rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
rv = NGHTTP2_ERR_HEADER_COMP;
@ -595,7 +595,7 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
buf->last = buf->pos;
/* This call will adjust buf->last to the correct position */
rv = nghttp2_hd_deflate_hd(deflater, bufs, frame->nva, frame->nvlen);
rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, frame->nva, frame->nvlen);
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
rv = NGHTTP2_ERR_HEADER_COMP;

View File

@ -1203,9 +1203,9 @@ static int deflate_post_process_hd_entry(nghttp2_hd_entry *ent,
return 0;
}
int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs,
nghttp2_nv *nv, size_t nvlen)
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs,
nghttp2_nv *nv, size_t nvlen)
{
size_t i;
int rv = 0;
@ -1259,6 +1259,87 @@ int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
return rv;
}
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
uint8_t *buf, size_t buflen,
nghttp2_nv *nv, size_t nvlen)
{
nghttp2_bufs bufs;
int rv;
rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen);
if(rv != 0) {
return rv;
}
rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
buflen = nghttp2_bufs_len(&bufs);
nghttp2_bufs_wrap_free(&bufs);
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
return NGHTTP2_ERR_INSUFF_BUFSIZE;
}
if(rv != 0) {
return rv;
}
return buflen;
}
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nva, size_t nvlen)
{
size_t n;
size_t i;
/* Possible Reference Set Emptying */
n = 1;
/* Possible Maximum Header Table Size Change. Encoding (1u << 31) -
1 using 4 bit prefix requires 6 bytes. */
n += 6;
/* Use Literal Header Field without indexing - New Name, since it is
most space consuming format. Also we choose the less one between
non-huffman and huffman, so using literal byte count is
sufficient for upper bound.
Encoding (1u << 31) - 1 using 7 bit prefix requires 6 bytes. We
need 2 of this for |nvlen| header fields. */
n += 6 * 2 * nvlen;
for(i = 0; i < nvlen; ++i) {
n += nva[i].namelen + nva[i].valuelen;
}
/* Add possible reference set toggle off */
n += deflater->ctx.hd_table.len;
return n;
}
int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
size_t deflate_hd_table_bufsize_max)
{
*deflater_ptr = malloc(sizeof(nghttp2_hd_deflater));
if(*deflater_ptr == NULL) {
return NGHTTP2_ERR_NOMEM;
}
return nghttp2_hd_deflate_init2(*deflater_ptr, deflate_hd_table_bufsize_max);
}
void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater)
{
nghttp2_hd_deflate_free(deflater);
free(deflater);
}
static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
const uint8_t *in)
{

View File

@ -132,7 +132,7 @@ typedef struct {
uint8_t bad;
} nghttp2_hd_context;
typedef struct {
struct nghttp2_hd_deflater {
nghttp2_hd_context ctx;
/* The upper limit of the header table size the deflater accepts. */
size_t deflate_hd_table_bufsize_max;
@ -142,7 +142,7 @@ typedef struct {
/* If nonzero, send header table size using encoding context update
in the next deflate process */
uint8_t notify_table_size_change;
} nghttp2_hd_deflater;
};
struct nghttp2_hd_inflater {
nghttp2_hd_context ctx;
@ -240,31 +240,6 @@ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
*/
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater);
/*
* Sets the availability of reference set in the |deflater|. If
* |no_refset| is nonzero, the deflater will first emit index=0 in the
* each invocation of nghttp2_hd_deflate_hd() to clear up reference
* set. By default, the deflater uses reference set.
*/
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset);
/*
* Changes header table size of the |deflater|. This may trigger
* eviction in the dynamic table.
*
* The |settings_hd_table_bufsize_max| should be the value received in
* SETTINGS_HEADER_TABLE_SIZE.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t settings_hd_table_bufsize_max);
/*
* Deflates the |nva|, which has the |nvlen| name/value pairs, into
* the |bufs|.
@ -285,9 +260,9 @@ int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
* NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space.
*/
int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs,
nghttp2_nv *nva, size_t nvlen);
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs,
nghttp2_nv *nva, size_t nvlen);
/*
* Initializes |inflater| for inflating name/values pairs.

View File

@ -247,6 +247,11 @@ cdef extern from 'nghttp2/nghttp2.h':
const char* nghttp2_strerror(int lib_error_code)
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset)
int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t hd_table_bufsize_max)
int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
size_t hd_table_bufsize_max)
@ -302,15 +307,9 @@ cdef extern from 'nghttp2_hd.h':
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater)
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset)
int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t hd_table_bufsize_max)
int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs,
nghttp2_nv *nva, size_t nvlen)
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs,
nghttp2_nv *nva, size_t nvlen)
nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
size_t index)

View File

@ -122,8 +122,8 @@ cdef class HDDeflater:
cnghttp2.nghttp2_bufs_init(&bufs, 4096, 16)
rv = cnghttp2.nghttp2_hd_deflate_hd(&self._deflater, &bufs,
nva, len(headers))
rv = cnghttp2.nghttp2_hd_deflate_hd_bufs(&self._deflater, &bufs,
nva, len(headers))
free(nva)
if rv < 0:

View File

@ -130,8 +130,8 @@ static void deflate_hd(nghttp2_hd_deflater *deflater,
nghttp2_bufs_init2(&bufs, 4096, 16, 0);
rv = nghttp2_hd_deflate_hd(deflater, &bufs,
(nghttp2_nv*)nva.data(), nva.size());
rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs,
(nghttp2_nv*)nva.data(), nva.size());
if(rv < 0) {
fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq);
exit(EXIT_FAILURE);

View File

@ -453,7 +453,7 @@ static int deflate_inflate(nghttp2_hd_deflater *deflater,
{
int rv;
rv = nghttp2_hd_deflate_hd(deflater, bufs, nva, nvlen);
rv = nghttp2_hd_deflate_hd_bufs(deflater, bufs, nva, nvlen);
if(rv != 0) {
return rv;

View File

@ -278,6 +278,9 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "hd_deflate_inflate",
test_nghttp2_hd_deflate_inflate) ||
!CU_add_test(pSuite, "hd_no_index", test_nghttp2_hd_no_index) ||
!CU_add_test(pSuite, "hd_deflate_bound",
test_nghttp2_hd_deflate_bound) ||
!CU_add_test(pSuite, "hd_public_api", test_nghttp2_hd_public_api) ||
!CU_add_test(pSuite, "adjust_local_window_size",
test_nghttp2_adjust_local_window_size) ||
!CU_add_test(pSuite, "check_header_name",

View File

@ -63,7 +63,7 @@ void test_nghttp2_hd_deflate(void)
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater));
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater));
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva1, ARRLEN(nva1));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -77,7 +77,7 @@ void test_nghttp2_hd_deflate(void)
nghttp2_bufs_reset(&bufs);
/* Second headers */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva2, ARRLEN(nva2));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -92,7 +92,7 @@ void test_nghttp2_hd_deflate(void)
/* Third headers, including same header field name, but value is not
the same. */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva3, ARRLEN(nva3));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva3, ARRLEN(nva3));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -106,7 +106,7 @@ void test_nghttp2_hd_deflate(void)
nghttp2_bufs_reset(&bufs);
/* Fourth headers, including duplicate header fields. */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva4, ARRLEN(nva4));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva4, ARRLEN(nva4));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -120,7 +120,7 @@ void test_nghttp2_hd_deflate(void)
nghttp2_bufs_reset(&bufs);
/* Fifth headers includes empty value */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva5, ARRLEN(nva5));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva5, ARRLEN(nva5));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -161,7 +161,7 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
/* Encode 2 same headers. cookie:alpha is not in the reference set,
so first emit literal repr and then 2 emits of indexed repr. */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva1, ARRLEN(nva1));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -176,7 +176,7 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
/* Encode 3 same headers. This time, cookie:alpha is in the
reference set, so the encoder emits indexed repr 6 times */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva2, ARRLEN(nva2));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -225,7 +225,7 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
/* First emit "h1: ..." to put it in the reference set (index
= 0). */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 1);
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 1);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -241,7 +241,7 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
/* Encode with second header */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -290,7 +290,7 @@ void test_nghttp2_hd_deflate_clear_refset(void)
nghttp2_hd_inflate_init(&inflater);
for(i = 0; i < 2; ++i) {
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nv, ARRLEN(nv));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nv, ARRLEN(nv));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -671,7 +671,7 @@ void test_nghttp2_hd_change_table_size(void)
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
/* This will emit encoding context update with header table size 4096 */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -698,7 +698,7 @@ void test_nghttp2_hd_change_table_size(void)
CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -727,7 +727,7 @@ void test_nghttp2_hd_change_table_size(void)
CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -764,7 +764,7 @@ void test_nghttp2_hd_change_table_size(void)
CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -790,7 +790,7 @@ void test_nghttp2_hd_change_table_size(void)
CU_ASSERT(16383 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -827,7 +827,7 @@ void test_nghttp2_hd_change_table_size(void)
CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
/* This emits context update with buffer size 1024 */
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -860,7 +860,7 @@ static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
frame_pack_bufs_init(&bufs);
nva_out_init(&out);
rv = nghttp2_hd_deflate_hd(deflater, &bufs, nva, nvlen);
rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nva, nvlen);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -1061,7 +1061,7 @@ void test_nghttp2_hd_no_index(void)
nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater);
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, ARRLEN(nva));
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
@ -1082,3 +1082,80 @@ void test_nghttp2_hd_no_index(void)
nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater);
}
void test_nghttp2_hd_deflate_bound(void)
{
nghttp2_hd_deflater deflater;
nghttp2_nv nva[] = {
MAKE_NV(":method", "GET"),
MAKE_NV("alpha", "bravo")
};
nghttp2_bufs bufs;
size_t bound, bound2;
frame_pack_bufs_init(&bufs);
nghttp2_hd_deflate_init(&deflater);
bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
CU_ASSERT(1 + 6 + 6 * 2 * 2 +
nva[0].namelen + nva[0].valuelen +
nva[1].namelen + nva[1].valuelen
== bound);
nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, ARRLEN(nva));
CU_ASSERT(bound > (size_t)nghttp2_bufs_len(&bufs));
bound2 = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
CU_ASSERT(bound + 2 == bound2);
nghttp2_bufs_free(&bufs);
nghttp2_hd_deflate_free(&deflater);
}
void test_nghttp2_hd_public_api(void)
{
nghttp2_hd_deflater *deflater;
nghttp2_hd_inflater *inflater;
nghttp2_nv nva[] = {
MAKE_NV("alpha", "bravo"),
MAKE_NV("charlie", "delta")
};
uint8_t buf[4096];
size_t buflen;
ssize_t blocklen;
nghttp2_bufs bufs;
CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096));
CU_ASSERT(0 == nghttp2_hd_inflate_new(&inflater));
buflen = nghttp2_hd_deflate_bound(deflater, nva, ARRLEN(nva));
blocklen = nghttp2_hd_deflate_hd(deflater, buf, buflen, nva, ARRLEN(nva));
CU_ASSERT(blocklen > 0);
nghttp2_bufs_wrap_init(&bufs, buf, blocklen);
bufs.head->buf.last += blocklen;
CU_ASSERT(blocklen == inflate_hd(inflater, NULL, &bufs, 0));
nghttp2_bufs_wrap_free(&bufs);
nghttp2_hd_inflate_del(inflater);
nghttp2_hd_deflate_del(deflater);
/* See NGHTTP2_ERR_INSUFF_BUFSIZE */
CU_ASSERT(0 == nghttp2_hd_deflate_new(&deflater, 4096));
blocklen = nghttp2_hd_deflate_hd(deflater, buf, blocklen - 1,
nva, ARRLEN(nva));
CU_ASSERT(NGHTTP2_ERR_INSUFF_BUFSIZE == blocklen);
nghttp2_hd_deflate_del(deflater);
}

View File

@ -40,5 +40,7 @@ void test_nghttp2_hd_inflate_zero_length_huffman(void);
void test_nghttp2_hd_change_table_size(void);
void test_nghttp2_hd_deflate_inflate(void);
void test_nghttp2_hd_no_index(void);
void test_nghttp2_hd_deflate_bound(void);
void test_nghttp2_hd_public_api(void);
#endif /* NGHTTP2_HD_TEST_H */