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 */ /* 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; 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) void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs)
{ {
nghttp2_buf_chain *ci; 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); 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 * 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 * 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; buf->last = buf->pos;
/* This call will adjust buf->last to the correct position */ /* 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) { if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
rv = NGHTTP2_ERR_HEADER_COMP; rv = NGHTTP2_ERR_HEADER_COMP;
@ -595,7 +595,7 @@ int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
buf->last = buf->pos; buf->last = buf->pos;
/* This call will adjust buf->last to the correct position */ /* 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) { if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
rv = NGHTTP2_ERR_HEADER_COMP; rv = NGHTTP2_ERR_HEADER_COMP;

View File

@ -1203,7 +1203,7 @@ static int deflate_post_process_hd_entry(nghttp2_hd_entry *ent,
return 0; return 0;
} }
int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs, nghttp2_bufs *bufs,
nghttp2_nv *nv, size_t nvlen) nghttp2_nv *nv, size_t nvlen)
{ {
@ -1259,6 +1259,87 @@ int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
return rv; 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, static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
const uint8_t *in) const uint8_t *in)
{ {

View File

@ -132,7 +132,7 @@ typedef struct {
uint8_t bad; uint8_t bad;
} nghttp2_hd_context; } nghttp2_hd_context;
typedef struct { struct nghttp2_hd_deflater {
nghttp2_hd_context ctx; nghttp2_hd_context ctx;
/* The upper limit of the header table size the deflater accepts. */ /* The upper limit of the header table size the deflater accepts. */
size_t deflate_hd_table_bufsize_max; size_t deflate_hd_table_bufsize_max;
@ -142,7 +142,7 @@ typedef struct {
/* If nonzero, send header table size using encoding context update /* If nonzero, send header table size using encoding context update
in the next deflate process */ in the next deflate process */
uint8_t notify_table_size_change; uint8_t notify_table_size_change;
} nghttp2_hd_deflater; };
struct nghttp2_hd_inflater { struct nghttp2_hd_inflater {
nghttp2_hd_context ctx; 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); 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 * Deflates the |nva|, which has the |nvlen| name/value pairs, into
* the |bufs|. * the |bufs|.
@ -285,7 +260,7 @@ int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
* NGHTTP2_ERR_BUFFER_ERROR * NGHTTP2_ERR_BUFFER_ERROR
* Out of buffer space. * Out of buffer space.
*/ */
int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs, nghttp2_bufs *bufs,
nghttp2_nv *nva, size_t nvlen); nghttp2_nv *nva, size_t nvlen);

View File

@ -247,6 +247,11 @@ cdef extern from 'nghttp2/nghttp2.h':
const char* nghttp2_strerror(int lib_error_code) 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, int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
size_t hd_table_bufsize_max) size_t hd_table_bufsize_max)
@ -302,13 +307,7 @@ cdef extern from 'nghttp2_hd.h':
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater)
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater, int nghttp2_hd_deflate_hd_bufs(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_bufs *bufs,
nghttp2_nv *nva, size_t nvlen) nghttp2_nv *nva, size_t nvlen)

View File

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

View File

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

View File

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

View File

@ -278,6 +278,9 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "hd_deflate_inflate", !CU_add_test(pSuite, "hd_deflate_inflate",
test_nghttp2_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_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", !CU_add_test(pSuite, "adjust_local_window_size",
test_nghttp2_adjust_local_window_size) || test_nghttp2_adjust_local_window_size) ||
!CU_add_test(pSuite, "check_header_name", !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_deflate_init(&deflater));
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater)); 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -77,7 +77,7 @@ void test_nghttp2_hd_deflate(void)
nghttp2_bufs_reset(&bufs); nghttp2_bufs_reset(&bufs);
/* Second headers */ /* 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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 /* Third headers, including same header field name, but value is not
the same. */ 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -106,7 +106,7 @@ void test_nghttp2_hd_deflate(void)
nghttp2_bufs_reset(&bufs); nghttp2_bufs_reset(&bufs);
/* Fourth headers, including duplicate header fields. */ /* 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -120,7 +120,7 @@ void test_nghttp2_hd_deflate(void)
nghttp2_bufs_reset(&bufs); nghttp2_bufs_reset(&bufs);
/* Fifth headers includes empty value */ /* 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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, /* Encode 2 same headers. cookie:alpha is not in the reference set,
so first emit literal repr and then 2 emits of indexed repr. */ 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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 /* Encode 3 same headers. This time, cookie:alpha is in the
reference set, so the encoder emits indexed repr 6 times */ 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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 /* First emit "h1: ..." to put it in the reference set (index
= 0). */ = 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -241,7 +241,7 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
/* Encode with second header */ /* 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -290,7 +290,7 @@ void test_nghttp2_hd_deflate_clear_refset(void)
nghttp2_hd_inflate_init(&inflater); nghttp2_hd_inflate_init(&inflater);
for(i = 0; i < 2; ++i) { 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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); CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
/* This will emit encoding context update with header table size 4096 */ /* 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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.ctx.hd_table_bufsize_max);
CU_ASSERT(1024 == inflater.settings_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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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.ctx.hd_table_bufsize_max);
CU_ASSERT(0 == inflater.settings_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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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.ctx.hd_table_bufsize_max);
CU_ASSERT(8000 == inflater.settings_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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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.ctx.hd_table_bufsize_max);
CU_ASSERT(16383 == inflater.settings_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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); 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); CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
/* This emits context update with buffer size 1024 */ /* 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -860,7 +860,7 @@ static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
frame_pack_bufs_init(&bufs); frame_pack_bufs_init(&bufs);
nva_out_init(&out); 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -1061,7 +1061,7 @@ void test_nghttp2_hd_no_index(void)
nghttp2_hd_deflate_init(&deflater); nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater); 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); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -1082,3 +1082,80 @@ void test_nghttp2_hd_no_index(void)
nghttp2_hd_inflate_free(&inflater); nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater); 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_change_table_size(void);
void test_nghttp2_hd_deflate_inflate(void); void test_nghttp2_hd_deflate_inflate(void);
void test_nghttp2_hd_no_index(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 */ #endif /* NGHTTP2_HD_TEST_H */