lib: Add nghttp2_hd_deflate_hd_vec() deflate API to support multiple bufs input

This commit is contained in:
Wenfeng Liu 2016-08-15 10:28:45 +00:00
parent 65cc2f0515
commit abf81b5bb7
4 changed files with 155 additions and 4 deletions

View File

@ -4516,6 +4516,39 @@ NGHTTP2_EXTERN ssize_t
nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
size_t buflen, const nghttp2_nv *nva, size_t nvlen); size_t buflen, const nghttp2_nv *nva, size_t nvlen);
/**
* @function
*
* Deflates the |nva|, which has the |nvlen| name/value pairs, into
* the |inlen| size of buf vector |bufsin|, each buf has length |buflen|.
* |buflens| is a |inlen| size of array, which will be used to store the writen
* size of each chunk. If one chunk is filled up, next chunk will be used.
* If |bufsin| 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.
*/
NGHTTP2_EXTERN ssize_t
nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, uint8_t **bufsin,
size_t inlen, size_t buflen, size_t *buflens,
const nghttp2_nv *nva, size_t nvlen);
/** /**
* @function * @function
* *

View File

@ -223,13 +223,62 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
return 0; return 0;
} }
int nghttp2_bufs_wrap_init2(nghttp2_bufs *bufs, uint8_t **bufs_in, size_t in_len,
size_t buf_len, nghttp2_mem *mem) {
size_t i = 0;
nghttp2_buf_chain *cur_chain;
nghttp2_buf_chain *pre_chain = NULL;
nghttp2_buf_chain *head_chain = NULL;
for (i = 0; i < in_len; ++i) {
uint8_t *begin = bufs_in[i];
cur_chain = nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain));
if (cur_chain == NULL) {
while (head_chain) {
nghttp2_buf_chain *tmp_chain = head_chain->next;
nghttp2_mem_free(mem, head_chain);
head_chain = tmp_chain;
}
return NGHTTP2_ERR_NOMEM;
}
cur_chain->next = NULL;
nghttp2_buf_wrap_init(&cur_chain->buf, begin, buf_len);
if (pre_chain) {
pre_chain->next = cur_chain;
} else {
head_chain = cur_chain;
}
pre_chain = cur_chain;
}
bufs->mem = mem;
bufs->offset = 0;
bufs->head = head_chain;
bufs->cur = bufs->head;
bufs->chunk_length = buf_len;
bufs->chunk_used = in_len;
bufs->max_chunk = in_len;
bufs->chunk_keep = in_len;
return 0;
}
void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) { void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) {
if (bufs == NULL) { if (bufs == NULL) {
return; return;
} }
nghttp2_mem_free(bufs->mem, bufs->head); while (bufs->head) {
bufs->head = NULL; nghttp2_buf_chain *tmp_chain = bufs->head->next;
nghttp2_mem_free(bufs->mem, bufs->head);
bufs->head = tmp_chain;
}
} }
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) { void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
@ -256,6 +305,20 @@ size_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
return len; return len;
} }
size_t nghttp2_bufs_len_vec(nghttp2_bufs *bufs, size_t *buflens) {
nghttp2_buf_chain *ci;
size_t len, total_len = 0;
int i = 0;
for (ci = bufs->head; ci; ci = ci->next) {
len = nghttp2_buf_len(&ci->buf);
total_len += len;
buflens[i++] = len;
}
return total_len;
}
static size_t bufs_avail(nghttp2_bufs *bufs) { static size_t bufs_avail(nghttp2_bufs *bufs) {
return nghttp2_buf_avail(&bufs->cur->buf) + return nghttp2_buf_avail(&bufs->cur->buf) +
(bufs->chunk_length - bufs->offset) * (bufs->chunk_length - bufs->offset) *

View File

@ -197,7 +197,7 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs);
/* /*
* Initializes |bufs| using supplied buffer |begin| of length |len|. * Initializes |bufs| using supplied buffer |begin| of length |len|.
* The first buffer bufs->head uses buffer |begin|. The buffer size * The first buffer bufs->head uses buffer |begin|. The buffer size
* is fixed and no allocate extra chunk buffer is allocated. In other * is fixed and no extra chunk buffer is allocated. In other
* words, max_chunk = chunk_keep = 1. To free the resource allocated * words, max_chunk = chunk_keep = 1. To free the resource allocated
* for |bufs|, use nghttp2_bufs_wrap_free(). * for |bufs|, use nghttp2_bufs_wrap_free().
* *
@ -210,6 +210,22 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs);
int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len, int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len,
nghttp2_mem *mem); nghttp2_mem *mem);
/*
* Initializes |bufs| using supplied |in_len| size of buf vector |bufs_in|,
* each buf has length |buf_len|.
* 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().
*
* 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_init2(nghttp2_bufs *bufs, uint8_t **bufs_in, size_t in_len,
size_t buf_len, nghttp2_mem *mem);
/* /*
* Frees any related resource to the |bufs|. This function does not * Frees any related resource to the |bufs|. This function does not
* free supplied buffer provided in nghttp2_bufs_wrap_init(). * free supplied buffer provided in nghttp2_bufs_wrap_init().
@ -381,8 +397,13 @@ int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
#define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf) #define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
/* /*
* Returns the buffer length of |bufs|. * Returns the total buffer length of |bufs|.
*/ */
size_t nghttp2_bufs_len(nghttp2_bufs *bufs); size_t nghttp2_bufs_len(nghttp2_bufs *bufs);
/*
* Returns the total buffer length of |bufs|, and each buffer length in |buflens|.
*/
size_t nghttp2_bufs_len_vec(nghttp2_bufs *bufs, size_t *buflens);
#endif /* NGHTTP2_BUF_H */ #endif /* NGHTTP2_BUF_H */

View File

@ -1503,6 +1503,40 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf,
return (ssize_t)buflen; return (ssize_t)buflen;
} }
ssize_t nghttp2_hd_deflate_hd_vec(nghttp2_hd_deflater *deflater, uint8_t **bufsin,
size_t inlen, size_t buflen, size_t *buflens,
const nghttp2_nv *nv, size_t nvlen) {
nghttp2_bufs bufs;
int rv;
nghttp2_mem *mem;
memset(buflens, 0, sizeof(size_t) * inlen);
mem = deflater->ctx.mem;
rv = nghttp2_bufs_wrap_init2(&bufs, bufsin, inlen, buflen, mem);
if (rv != 0) {
return rv;
}
rv = nghttp2_hd_deflate_hd_bufs(deflater, &bufs, nv, nvlen);
buflen = nghttp2_bufs_len_vec(&bufs, buflens);
nghttp2_bufs_wrap_free(&bufs);
if (rv == NGHTTP2_ERR_BUFFER_ERROR) {
return NGHTTP2_ERR_INSUFF_BUFSIZE;
}
if (rv != 0) {
return rv;
}
return (ssize_t)buflen;
}
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater _U_, size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater _U_,
const nghttp2_nv *nva, size_t nvlen) { const nghttp2_nv *nva, size_t nvlen) {
size_t n = 0; size_t n = 0;