From d0fea96e6959131e3bbcbaa499521a0e1cee2a21 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 18 Aug 2016 21:23:17 +0900 Subject: [PATCH] Allow nonuniform buffer size in nghttp2_hd_deflate_hd_vec() --- lib/includes/nghttp2/nghttp2.h | 16 ++++++---------- lib/nghttp2_buf.c | 7 ++++--- lib/nghttp2_buf.h | 10 +++++----- lib/nghttp2_hd.c | 16 +--------------- tests/nghttp2_hd_test.c | 14 ++++++++++++-- 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index 207048c2..730b7410 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -4604,14 +4604,12 @@ nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, * * Deflates the |nva|, which has the |nvlen| name/value pairs, into * the |veclen| size of buf vector |vec|. The each size of buffer - * must be set in len field of :type:`nghttp2_vec`, and this function - * assumes all buffer size is equal. The application is responsible - * to make sure that this assumption holds. If one chunk is filled - * up, next chunk will be used. If |vec| 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. + * must be set in len field of :type:`nghttp2_vec`. If and only if + * one chunk is filled up completely, next chunk will be used. If + * |vec| 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`. @@ -4627,8 +4625,6 @@ nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, * Deflation process has failed. * :enum:`NGHTTP2_ERR_INSUFF_BUFSIZE` * The provided |buflen| size is too small to hold the output. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The size of each buffer in |nva| is not the same. */ NGHTTP2_EXTERN ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, const nghttp2_vec *vec, diff --git a/lib/nghttp2_buf.c b/lib/nghttp2_buf.c index b5021a27..1fc26753 100644 --- a/lib/nghttp2_buf.c +++ b/lib/nghttp2_buf.c @@ -224,13 +224,13 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len, } int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec, - size_t veclen, size_t chunklen, nghttp2_mem *mem) { + size_t veclen, nghttp2_mem *mem) { size_t i = 0; nghttp2_buf_chain *cur_chain; nghttp2_buf_chain *head_chain; nghttp2_buf_chain **dst_chain = &head_chain; - if (veclen == 0 || chunklen == 0) { + if (veclen == 0) { return nghttp2_bufs_wrap_init(bufs, NULL, 0, mem); } @@ -254,7 +254,8 @@ int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec, bufs->head = head_chain; bufs->cur = bufs->head; - bufs->chunk_length = chunklen; + /* We don't use chunk_length since no allocation is expected. */ + bufs->chunk_length = 0; bufs->chunk_used = veclen; bufs->max_chunk = veclen; bufs->chunk_keep = veclen; diff --git a/lib/nghttp2_buf.h b/lib/nghttp2_buf.h index 2b39f17f..22b7d072 100644 --- a/lib/nghttp2_buf.h +++ b/lib/nghttp2_buf.h @@ -212,10 +212,10 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len, /* * Initializes |bufs| using supplied |veclen| size of buf vector - * |vec|, assuming that each buffer has length |chunklen|. The buffer - * size is fixed and no extra chunk buffer is allocated. In other - * words, max_chunk = chunk_keep = |in_len|. To free the resource - * allocated for |bufs|, use nghttp2_bufs_wrap_free(). + * |vec|. The number of buffers is fixed and no extra chunk buffer is + * allocated. In other words, max_chunk = chunk_keep = |in_len|. 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: @@ -224,7 +224,7 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len, * Out of memory. */ int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, const nghttp2_vec *vec, - size_t veclen, size_t chunklen, nghttp2_mem *mem); + size_t veclen, nghttp2_mem *mem); /* * Frees any related resource to the |bufs|. This function does not diff --git a/lib/nghttp2_hd.c b/lib/nghttp2_hd.c index 3df36c44..f8dba5c0 100644 --- a/lib/nghttp2_hd.c +++ b/lib/nghttp2_hd.c @@ -1509,25 +1509,11 @@ ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, nghttp2_bufs bufs; int rv; nghttp2_mem *mem; - size_t i; size_t buflen; - size_t chunklen; - - if (veclen == 0) { - chunklen = 0; - } else { - for (i = 1; i < veclen; ++i) { - if (vec[0].len != vec[i].len) { - return NGHTTP2_ERR_INVALID_ARGUMENT; - } - } - - chunklen = vec[0].len; - } mem = deflater->ctx.mem; - rv = nghttp2_bufs_wrap_init2(&bufs, vec, veclen, chunklen, mem); + rv = nghttp2_bufs_wrap_init2(&bufs, vec, veclen, mem); if (rv != 0) { return rv; diff --git a/tests/nghttp2_hd_test.c b/tests/nghttp2_hd_test.c index 32676f78..cb7bdef5 100644 --- a/tests/nghttp2_hd_test.c +++ b/tests/nghttp2_hd_test.c @@ -1352,14 +1352,24 @@ void test_nghttp2_hd_deflate_hd_vec(void) { vec[0].base = &buf[0]; vec[0].len = buflen / 2; vec[1].base = &buf[buflen / 2]; - vec[1].len = (buflen / 2) - 1; + vec[1].len = (buflen / 2) + 1; blocklen = nghttp2_hd_deflate_hd_vec(deflater, vec, 2, nva, ARRLEN(nva)); - CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == blocklen); + CU_ASSERT(blocklen > 0); + + nghttp2_bufs_wrap_init(&bufs, buf, (size_t)blocklen, mem); + bufs.head->buf.last += blocklen; + + CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0, mem)); + CU_ASSERT(ARRLEN(nva) == out.nvlen); + assert_nv_equal(nva, out.nva, ARRLEN(nva), mem); + + nghttp2_bufs_wrap_free(&bufs); nghttp2_hd_inflate_del(inflater); nghttp2_hd_deflate_del(deflater); + nva_out_reset(&out, mem); /* check the case where chunk size is 1 */ nghttp2_hd_deflate_new(&deflater, 4096);