diff options
author | Alexis La Goutte <alexis.lagoutte@gmail.com> | 2015-01-07 21:32:47 +0100 |
---|---|---|
committer | Alexis La Goutte <alexis.lagoutte@gmail.com> | 2015-01-15 08:34:38 +0000 |
commit | adaa661b74b1b407341e67052fb430914cba127d (patch) | |
tree | 3b19913b04f10c369e5ea166c6e0130958070d96 | |
parent | 5b92ab9f97a4d1644218059e3b17097a02421bc4 (diff) |
Update to libnghttp2 0.7.1
Change-Id: Ib8d40586a3b95674447819f77eaaa69376dce6fd
Reviewed-on: https://code.wireshark.org/review/6411
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
-rw-r--r-- | epan/CMakeLists.txt | 1 | ||||
-rw-r--r-- | epan/nghttp2/Makefile.common | 4 | ||||
-rw-r--r-- | epan/nghttp2/README.nghttp2 | 1 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2.h | 245 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_buf.c | 62 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_buf.h | 21 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_hd.c | 187 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_hd.h | 15 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_hd_huffman.c | 107 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_helper.c | 93 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_helper.h | 11 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_mem.c | 61 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2_mem.h | 44 | ||||
-rw-r--r-- | epan/nghttp2/nghttp2ver.h | 4 |
14 files changed, 622 insertions, 234 deletions
diff --git a/epan/CMakeLists.txt b/epan/CMakeLists.txt index fe64bf921f..676b191f08 100644 --- a/epan/CMakeLists.txt +++ b/epan/CMakeLists.txt @@ -1518,6 +1518,7 @@ set(NGHTTP2_FILES nghttp2/nghttp2_hd_huffman.c nghttp2/nghttp2_hd_huffman_data.c nghttp2/nghttp2_helper.c + nghttp2/nghttp2_mem.c ) source_group(nghttp2 FILES ${NGHTTP2_FILES}) diff --git a/epan/nghttp2/Makefile.common b/epan/nghttp2/Makefile.common index a3893a34d8..3662118c4b 100644 --- a/epan/nghttp2/Makefile.common +++ b/epan/nghttp2/Makefile.common @@ -26,7 +26,8 @@ LIBNGHTTP2_SRC = \ nghttp2_hd.c \ nghttp2_hd_huffman.c \ nghttp2_hd_huffman_data.c \ - nghttp2_helper.c + nghttp2_helper.c \ + nghttp2_mem.c LIBNGHTTP2_INCLUDES = \ nghttp2_buf.h \ @@ -34,6 +35,7 @@ LIBNGHTTP2_INCLUDES = \ nghttp2_hd_huffman.h \ nghttp2_helper.h \ nghttp2_int.h \ + nghttp2_mem.h \ nghttp2_net.h \ nghttp2.h \ nghttp2ver.h diff --git a/epan/nghttp2/README.nghttp2 b/epan/nghttp2/README.nghttp2 index a0be9a3f45..e24040babc 100644 --- a/epan/nghttp2/README.nghttp2 +++ b/epan/nghttp2/README.nghttp2 @@ -10,6 +10,7 @@ cp ../../../nghttp2/lib/nghttp2_buf.[ch] . cp ../../../nghttp2/lib/nghttp2_hd*.[ch] . cp ../../../nghttp2/lib/nghttp2_helper.[ch] . cp ../../../nghttp2/lib/nghttp2_int.h . +cp ../../../nghttp2/lib/nghttp2_mem.[ch] . cp ../../../nghttp2/lib/nghttp2_net.h . cp ../../../nghttp2/lib/includes/nghttp2/nghttp2.h . cp ../../../nghttp2/lib/includes/nghttp2/nghttp2ver.h . diff --git a/epan/nghttp2/nghttp2.h b/epan/nghttp2/nghttp2.h index 3a7bcc2486..b05c44dbe2 100644 --- a/epan/nghttp2/nghttp2.h +++ b/epan/nghttp2/nghttp2.h @@ -1689,6 +1689,101 @@ void nghttp2_session_callbacks_set_on_begin_frame_callback( nghttp2_session_callbacks *cbs, nghttp2_on_begin_frame_callback on_begin_frame_callback); +/** + * @functypedef + * + * Custom memory allocator to replace malloc(). The |mem_user_data| + * is the mem_user_data member of :type:`nghttp2_mem` structure. + */ +typedef void *(*nghttp2_malloc)(size_t size, void *mem_user_data); + +/** + * @functypedef + * + * Custom memory allocator to replace free(). The |mem_user_data| is + * the mem_user_data member of :type:`nghttp2_mem` structure. + */ +typedef void (*nghttp2_free)(void *ptr, void *mem_user_data); + +/** + * @functypedef + * + * Custom memory allocator to replace calloc(). The |mem_user_data| + * is the mem_user_data member of :type:`nghttp2_mem` structure. + */ +typedef void *(*nghttp2_calloc)(size_t nmemb, size_t size, void *mem_user_data); + +/** + * @functypedef + * + * Custom memory allocator to replace realloc(). The |mem_user_data| + * is the mem_user_data member of :type:`nghttp2_mem` structure. + */ +typedef void *(*nghttp2_realloc)(void *ptr, size_t size, void *mem_user_data); + +/** + * @struct + * + * Custom memory allocator functions and user defined pointer. The + * |mem_user_data| member is passed to each allocator function. This + * can be used, for example, to achieve per-session memory pool. + * + * In the following example code, ``my_malloc``, ``my_free``, + * ``my_calloc`` and ``my_realloc`` are the replacement of the + * standard allocators ``malloc``, ``free``, ``calloc`` and + * ``realloc`` respectively:: + * + * void *my_malloc_cb(size_t size, void *mem_user_data) { + * return my_malloc(size); + * } + * + * void my_free_cb(void *ptr, void *mem_user_data) { my_free(ptr); } + * + * void *my_calloc_cb(size_t nmemb, size_t size, void *mem_user_data) { + * return my_calloc(nmemb, size); + * } + * + * void *my_realloc_cb(void *ptr, size_t size, void *mem_user_data) { + * return my_realloc(ptr, size); + * } + * + * void session_new() { + * nghttp2_session *session; + * nghttp2_session_callbacks *callbacks; + * nghttp2_mem mem = {NULL, my_malloc_cb, my_free_cb, my_calloc_cb, + * my_realloc_cb}; + * + * ... + * + * nghttp2_session_client_new3(&session, callbacks, NULL, NULL, &mem); + * + * ... + * } + */ +typedef struct { + /** + * An arbitrary user supplied data. This is passed to each + * allocator function. + */ + void *mem_user_data; + /** + * Custom allocator function to replace malloc(). + */ + nghttp2_malloc malloc; + /** + * Custom allocator function to replace free(). + */ + nghttp2_free free; + /** + * Custom allocator function to replace calloc(). + */ + nghttp2_calloc calloc; + /** + * Custom allocator function to replace realloc(). + */ + nghttp2_realloc realloc; +} nghttp2_mem; + struct nghttp2_option; /** @@ -1874,6 +1969,58 @@ int nghttp2_session_server_new2(nghttp2_session **session_ptr, /** * @function * + * Like `nghttp2_session_client_new2()`, but with additional custom + * memory allocator specified in the |mem|. + * + * The |mem| can be ``NULL`` and the call is equivalent to + * `nghttp2_session_client_new2()`. + * + * This function does not take ownership |mem|. The application is + * responsible for freeing |mem|. + * + * The library code does not refer to |mem| pointer after this + * function returns, so the application can safely free it. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`NGHTTP2_ERR_NOMEM` + * Out of memory. + */ +int nghttp2_session_client_new3(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, const nghttp2_option *option, + nghttp2_mem *mem); + +/** + * @function + * + * Like `nghttp2_session_server_new2()`, but with additional custom + * memory allocator specified in the |mem|. + * + * The |mem| can be ``NULL`` and the call is equivalent to + * `nghttp2_session_server_new2()`. + * + * This function does not take ownership |mem|. The application is + * responsible for freeing |mem|. + * + * The library code does not refer to |mem| pointer after this + * function returns, so the application can safely free it. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`NGHTTP2_ERR_NOMEM` + * Out of memory. + */ +int nghttp2_session_server_new3(nghttp2_session **session_ptr, + const nghttp2_session_callbacks *callbacks, + void *user_data, const nghttp2_option *option, + nghttp2_mem *mem); + +/** + * @function + * * Frees any resources allocated for |session|. If |session| is * ``NULL``, this function does nothing. */ @@ -2325,6 +2472,32 @@ uint32_t nghttp2_session_get_remote_settings(nghttp2_session *session, /** * @function * + * Tells the |session| that next stream ID is |next_stream_id|. The + * |next_stream_id| must be equal or greater than the value returned + * by `nghttp2_session_get_next_stream_id()`. + * + * This function returns 0 if it succeeds, or one of the following + * negative error codes: + * + * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` + * The |next_stream_id| is strictly less than the value + * `nghttp2_session_get_next_stream_id()` returns. + */ +int nghttp2_session_set_next_stream_id(nghttp2_session *session, + int32_t next_stream_id); + +/** + * @function + * + * Returns the next outgoing stream ID. Notice that return type is + * uint32_t. If we run out of stream ID for this session, this + * function returns 1 << 31. + */ +uint32_t nghttp2_session_get_next_stream_id(nghttp2_session *session); + +/** + * @function + * * Tells the |session| that |size| bytes for a stream denoted by * |stream_id| were consumed by application and are ready to * WINDOW_UPDATE. This function is intended to be used without @@ -2555,6 +2728,12 @@ int32_t nghttp2_submit_request(nghttp2_session *session, * Out of memory. * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * The |stream_id| is 0. + * + * .. warning:: + * + * Calling this function twice for the same stream ID may lead to + * program crash. It is generally considered to a programming error + * to commit response twice. */ int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen, @@ -2931,32 +3110,9 @@ int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags, /** * @function * - * Submits ALTSVC frame with given parameters. - * - * The |flags| is currently ignored and should be - * :enum:`NGHTTP2_FLAG_NONE`. - * - * Only the server can send the ALTSVC frame. If |session| is - * initialized as client, this function fails and returns - * :enum:`NGHTTP2_ERR_PROTO`. - * - * If the |protocol_id_len| is 0, the |protocol_id| could be ``NULL``. - * - * If the |host_len| is 0, the |host| could be ``NULL``. - * - * If the |origin_len| is 0, the |origin| could be ``NULL``. - * - * 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_PROTO` - * The function is invoked with |session| which was initialized as - * client. - * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` - * The combined length of |protocol_id_len|, |host_len| and - * |origin_len| is is too large. + * This function previously submits ALTSVC frame with given + * parameters, but is deprecated and will be removed in a future + * release. This function does nothing and just return 0. */ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags, int32_t stream_id, uint32_t max_age, uint16_t port, @@ -3107,6 +3263,25 @@ int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, /** * @function * + * Like `nghttp2_hd_deflate_new()`, but with additional custom memory + * allocator specified in the |mem|. + * + * The |mem| can be ``NULL`` and the call is equivalent to + * `nghttp2_hd_deflate_new()`. + * + * This function does not take ownership |mem|. The application is + * responsible for freeing |mem|. + * + * The library code does not refer to |mem| pointer after this + * function returns, so the application can safely free it. + */ +int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr, + size_t deflate_hd_table_bufsize_max, + nghttp2_mem *mem); + +/** + * @function + * * Deallocates any resources allocated for |deflater|. */ void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater); @@ -3204,6 +3379,24 @@ int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr); /** * @function * + * Like `nghttp2_hd_inflate_new()`, but with additional custom memory + * allocator specified in the |mem|. + * + * The |mem| can be ``NULL`` and the call is equivalent to + * `nghttp2_hd_inflate_new()`. + * + * This function does not take ownership |mem|. The application is + * responsible for freeing |mem|. + * + * The library code does not refer to |mem| pointer after this + * function returns, so the application can safely free it. + */ +int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr, + nghttp2_mem *mem); + +/** + * @function + * * Deallocates any resources allocated for |inflater|. */ void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater); diff --git a/epan/nghttp2/nghttp2_buf.c b/epan/nghttp2/nghttp2_buf.c index 4cff6fd82e..f747ae989a 100644 --- a/epan/nghttp2/nghttp2_buf.c +++ b/epan/nghttp2/nghttp2_buf.c @@ -36,21 +36,21 @@ void nghttp2_buf_init(nghttp2_buf *buf) { buf->mark = NULL; } -int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial) { +int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem) { nghttp2_buf_init(buf); - return nghttp2_buf_reserve(buf, initial); + return nghttp2_buf_reserve(buf, initial, mem); } -void nghttp2_buf_free(nghttp2_buf *buf) { +void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem) { if (buf == NULL) { return; } - free(buf->begin); + nghttp2_mem_free(mem, buf->begin); buf->begin = NULL; } -int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap) { +int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem) { uint8_t *ptr; size_t cap; @@ -62,7 +62,7 @@ int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap) { new_cap = nghttp2_max(new_cap, cap * 2); - ptr = (uint8_t *)realloc(buf->begin, new_cap); + ptr = (uint8_t *)nghttp2_mem_realloc(mem, buf->begin, new_cap); if (ptr == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -85,42 +85,45 @@ void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len) { buf->end = begin + len; } -static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length) { +static int buf_chain_new(nghttp2_buf_chain **chain, size_t chunk_length, + nghttp2_mem *mem) { int rv; - *chain = (nghttp2_buf_chain *)malloc(sizeof(nghttp2_buf_chain)); + *chain = (nghttp2_buf_chain *)nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain)); if (*chain == NULL) { return NGHTTP2_ERR_NOMEM; } (*chain)->next = NULL; - rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length); + rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length, mem); if (rv != 0) { - free(*chain); + nghttp2_mem_free(mem, *chain); return NGHTTP2_ERR_NOMEM; } return 0; } -static void buf_chain_del(nghttp2_buf_chain *chain) { - nghttp2_buf_free(&chain->buf); - free(chain); +static void buf_chain_del(nghttp2_buf_chain *chain, nghttp2_mem *mem) { + nghttp2_buf_free(&chain->buf, mem); + nghttp2_mem_free(mem, chain); } -int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk) { - return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0); +int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk, + nghttp2_mem *mem) { + return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0, mem); } int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk, size_t offset) { - return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset); + size_t max_chunk, size_t offset, nghttp2_mem *mem) { + return nghttp2_bufs_init3(bufs, chunk_length, max_chunk, max_chunk, offset, + mem); } int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk, size_t chunk_keep, size_t offset) { + size_t max_chunk, size_t chunk_keep, size_t offset, + nghttp2_mem *mem) { int rv; nghttp2_buf_chain *chain; @@ -128,11 +131,12 @@ int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length, return NGHTTP2_ERR_INVALID_ARGUMENT; } - rv = buf_chain_new(&chain, chunk_length); + rv = buf_chain_new(&chain, chunk_length, mem); if (rv != 0) { return rv; } + bufs->mem = mem; bufs->offset = offset; bufs->head = chain; @@ -156,7 +160,7 @@ int nghttp2_bufs_realloc(nghttp2_bufs *bufs, size_t chunk_length) { return NGHTTP2_ERR_INVALID_ARGUMENT; } - rv = buf_chain_new(&chain, chunk_length); + rv = buf_chain_new(&chain, chunk_length, bufs->mem); if (rv != 0) { return rv; } @@ -184,7 +188,7 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs) { for (chain = bufs->head; chain;) { next_chain = chain->next; - buf_chain_del(chain); + buf_chain_del(chain, bufs->mem); chain = next_chain; } @@ -192,10 +196,11 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs) { bufs->head = NULL; } -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_buf_chain *chain; - chain = (nghttp2_buf_chain *)malloc(sizeof(nghttp2_buf_chain)); + chain = (nghttp2_buf_chain *)nghttp2_mem_malloc(mem, sizeof(nghttp2_buf_chain)); if (chain == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -204,6 +209,7 @@ int nghttp2_bufs_wrap_init(nghttp2_bufs *bufs, uint8_t *begin, size_t len) { nghttp2_buf_wrap_init(&chain->buf, begin, len); + bufs->mem = mem; bufs->offset = 0; bufs->head = chain; @@ -222,7 +228,7 @@ void nghttp2_bufs_wrap_free(nghttp2_bufs *bufs) { return; } - free(bufs->head); + nghttp2_mem_free(bufs->mem, bufs->head); bufs->head = NULL; } @@ -270,7 +276,7 @@ static int bufs_alloc_chain(nghttp2_bufs *bufs) { return NGHTTP2_ERR_BUFFER_ERROR; } - rv = buf_chain_new(&chain, bufs->chunk_length); + rv = buf_chain_new(&chain, bufs->chunk_length, bufs->mem); if (rv != 0) { return rv; } @@ -407,7 +413,7 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) { if (!len) { res = NULL; } else { - res = (uint8_t *)malloc(len); + res = (uint8_t *)nghttp2_mem_malloc(bufs->mem, len); if (res == NULL) { return NGHTTP2_ERR_NOMEM; @@ -456,7 +462,7 @@ void nghttp2_bufs_reset(nghttp2_bufs *bufs) { for (ci = chain; ci;) { chain = ci->next; - buf_chain_del(ci); + buf_chain_del(ci, bufs->mem); ci = chain; } diff --git a/epan/nghttp2/nghttp2_buf.h b/epan/nghttp2/nghttp2_buf.h index 49eff4430a..108147e914 100644 --- a/epan/nghttp2/nghttp2_buf.h +++ b/epan/nghttp2/nghttp2_buf.h @@ -32,6 +32,7 @@ #include <nghttp2.h> #include "nghttp2_int.h" +#include "nghttp2_mem.h" typedef struct { /* This points to the beginning of the buffer. The effective range @@ -86,12 +87,12 @@ void nghttp2_buf_init(nghttp2_buf *buf); * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial); +int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial, nghttp2_mem *mem); /* * Frees buffer in |buf|. */ -void nghttp2_buf_free(nghttp2_buf *buf); +void nghttp2_buf_free(nghttp2_buf *buf, nghttp2_mem *mem); /* * Extends buffer so that nghttp2_buf_cap() returns at least @@ -104,7 +105,7 @@ void nghttp2_buf_free(nghttp2_buf *buf); * NGHTTP2_ERR_NOMEM * Out of memory */ -int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap); +int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap, nghttp2_mem *mem); /* * Resets pos, last, mark member of |buf| to buf->begin. @@ -135,6 +136,8 @@ typedef struct { nghttp2_buf_chain *head; /* Buffer pointer where write occurs. */ nghttp2_buf_chain *cur; + /* Memory allocator */ + nghttp2_mem *mem; /* The buffer capacity of each buf */ size_t chunk_length; /* The maximum number of nghttp2_buf_chain */ @@ -153,15 +156,15 @@ typedef struct { * This is the same as calling nghttp2_bufs_init2 with the given * arguments and offset = 0. */ -int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk); +int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length, size_t max_chunk, + nghttp2_mem *mem); /* * This is the same as calling nghttp2_bufs_init3 with the given * arguments and chunk_keep = max_chunk. */ int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk, size_t offset); + size_t max_chunk, size_t offset, nghttp2_mem *mem); /* * Initializes |bufs|. Each buffer size is given in the @@ -183,7 +186,8 @@ int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length, * long. */ int nghttp2_bufs_init3(nghttp2_bufs *bufs, size_t chunk_length, - size_t max_chunk, size_t chunk_keep, size_t offset); + size_t max_chunk, size_t chunk_keep, size_t offset, + nghttp2_mem *mem); /* * Frees any related resources to the |bufs|. @@ -203,7 +207,8 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs); * NGHTTP2_ERR_NOMEM * Out of memory. */ -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); /* * Frees any related resource to the |bufs|. This function does not diff --git a/epan/nghttp2/nghttp2_hd.c b/epan/nghttp2/nghttp2_hd.c index b9a28eff52..f4ef88eee0 100644 --- a/epan/nghttp2/nghttp2_hd.c +++ b/epan/nghttp2/nghttp2_hd.c @@ -141,7 +141,8 @@ static uint32_t hash(const uint8_t *s, size_t n) { int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name, size_t namelen, uint8_t *value, size_t valuelen, - uint32_t name_hash, uint32_t value_hash) { + uint32_t name_hash, uint32_t value_hash, + nghttp2_mem *mem) { int rv = 0; /* Since nghttp2_hd_entry is used for indexing, ent->nv.flags always @@ -154,7 +155,7 @@ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name, /* We should not allow empty header field name */ ent->nv.name = NULL; } else { - ent->nv.name = (uint8_t *)nghttp2_memdup(name, namelen); + ent->nv.name = (uint8_t *)nghttp2_memdup(name, namelen, mem); if (ent->nv.name == NULL) { rv = NGHTTP2_ERR_NOMEM; goto fail; @@ -168,7 +169,7 @@ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name, if (valuelen == 0) { ent->nv.value = NULL; } else { - ent->nv.value = (uint8_t *)nghttp2_memdup(value, valuelen); + ent->nv.value = (uint8_t *)nghttp2_memdup(value, valuelen, mem); if (ent->nv.value == NULL) { rv = NGHTTP2_ERR_NOMEM; goto fail2; @@ -189,27 +190,28 @@ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name, fail2: if (flags & NGHTTP2_HD_FLAG_NAME_ALLOC) { - free(ent->nv.name); + nghttp2_mem_free(mem, ent->nv.name); } fail: return rv; } -void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) { +void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem) { assert(ent->ref == 0); if (ent->flags & NGHTTP2_HD_FLAG_NAME_ALLOC) { - free(ent->nv.name); + nghttp2_mem_free(mem, ent->nv.name); } if (ent->flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) { - free(ent->nv.value); + nghttp2_mem_free(mem, ent->nv.value); } } -static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize) { +static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize, + nghttp2_mem *mem) { size_t size; for (size = 1; size < bufsize; size <<= 1) ; - ringbuf->buffer = (nghttp2_hd_entry**)malloc(sizeof(nghttp2_hd_entry *) * size); + ringbuf->buffer = (nghttp2_hd_entry **)nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size); if (ringbuf->buffer == NULL) { return NGHTTP2_ERR_NOMEM; } @@ -225,7 +227,8 @@ static nghttp2_hd_entry *hd_ringbuf_get(nghttp2_hd_ringbuf *ringbuf, return ringbuf->buffer[(ringbuf->first + idx) & ringbuf->mask]; } -static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize) { +static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize, + nghttp2_mem *mem) { size_t i; size_t size; nghttp2_hd_entry **buffer; @@ -235,21 +238,21 @@ static int hd_ringbuf_reserve(nghttp2_hd_ringbuf *ringbuf, size_t bufsize) { } for (size = 1; size < bufsize; size <<= 1) ; - buffer = (nghttp2_hd_entry **)malloc(sizeof(nghttp2_hd_entry *) * size); + buffer = (nghttp2_hd_entry **)nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry *) * size); if (buffer == NULL) { return NGHTTP2_ERR_NOMEM; } for (i = 0; i < ringbuf->len; ++i) { buffer[i] = hd_ringbuf_get(ringbuf, i); } - free(ringbuf->buffer); + nghttp2_mem_free(mem, ringbuf->buffer); ringbuf->buffer = buffer; ringbuf->mask = size - 1; ringbuf->first = 0; return 0; } -static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf) { +static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) { size_t i; if (ringbuf == NULL) { return; @@ -257,17 +260,17 @@ static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf) { for (i = 0; i < ringbuf->len; ++i) { nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i); --ent->ref; - nghttp2_hd_entry_free(ent); - free(ent); + nghttp2_hd_entry_free(ent, mem); + nghttp2_mem_free(mem, ent); } - free(ringbuf->buffer); + nghttp2_mem_free(mem, ringbuf->buffer); } static int hd_ringbuf_push_front(nghttp2_hd_ringbuf *ringbuf, - nghttp2_hd_entry *ent) { + nghttp2_hd_entry *ent, nghttp2_mem *mem) { int rv; - rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1); + rv = hd_ringbuf_reserve(ringbuf, ringbuf->len + 1, mem); if (rv != 0) { return rv; @@ -284,12 +287,14 @@ static void hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) { --ringbuf->len; } -static int hd_context_init(nghttp2_hd_context *context) { +static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) { int rv; + context->mem = mem; context->bad = 0; context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; rv = hd_ringbuf_init(&context->hd_table, context->hd_table_bufsize_max / - NGHTTP2_HD_ENTRY_OVERHEAD); + NGHTTP2_HD_ENTRY_OVERHEAD, + mem); if (rv != 0) { return rv; } @@ -299,18 +304,19 @@ static int hd_context_init(nghttp2_hd_context *context) { } static void hd_context_free(nghttp2_hd_context *context) { - hd_ringbuf_free(&context->hd_table); + hd_ringbuf_free(&context->hd_table, context->mem); } -int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater) { - return nghttp2_hd_deflate_init2(deflater, - NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE); +int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem) { + return nghttp2_hd_deflate_init2( + deflater, NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, mem); } int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater, - size_t deflate_hd_table_bufsize_max) { + size_t deflate_hd_table_bufsize_max, + nghttp2_mem *mem) { int rv; - rv = hd_context_init(&deflater->ctx); + rv = hd_context_init(&deflater->ctx, mem); if (rv != 0) { return rv; } @@ -328,10 +334,10 @@ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater, return 0; } -int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater) { +int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) { int rv; - rv = hd_context_init(&inflater->ctx); + rv = hd_context_init(&inflater->ctx, mem); if (rv != 0) { goto fail; } @@ -344,7 +350,8 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater) { inflater->opcode = NGHTTP2_HD_OPCODE_NONE; inflater->state = NGHTTP2_HD_STATE_OPCODE; - rv = nghttp2_bufs_init3(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 8, 8, 1, 0); + rv = nghttp2_bufs_init3(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 8, 8, 1, 0, + mem); if (rv != 0) { goto nvbufs_fail; @@ -367,15 +374,18 @@ fail: } static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) { + nghttp2_mem *mem; + + mem = inflater->ctx.mem; if (inflater->ent_keep) { if (inflater->ent_keep->ref == 0) { - nghttp2_hd_entry_free(inflater->ent_keep); - free(inflater->ent_keep); + nghttp2_hd_entry_free(inflater->ent_keep, mem); + nghttp2_mem_free(mem, inflater->ent_keep); } inflater->ent_keep = NULL; } - free(inflater->nv_keep); + nghttp2_mem_free(mem, inflater->nv_keep); inflater->nv_keep = NULL; } @@ -727,7 +737,9 @@ static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context, int rv; nghttp2_hd_entry *new_ent; size_t room; + nghttp2_mem *mem; + mem = context->mem; room = entry_room(nv->namelen, nv->valuelen); while (context->hd_table_bufsize + room > context->hd_table_bufsize_max && @@ -745,20 +757,21 @@ static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context, DEBUGF(fprintf(stderr, "\n")); hd_ringbuf_pop_back(&context->hd_table); if (--ent->ref == 0) { - nghttp2_hd_entry_free(ent); - free(ent); + nghttp2_hd_entry_free(ent, mem); + nghttp2_mem_free(mem, ent); } } - new_ent = (nghttp2_hd_entry *)malloc(sizeof(nghttp2_hd_entry)); + new_ent = (nghttp2_hd_entry *)nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry)); if (new_ent == NULL) { return NULL; } rv = nghttp2_hd_entry_init(new_ent, entry_flags, nv->name, nv->namelen, - nv->value, nv->valuelen, name_hash, value_hash); + nv->value, nv->valuelen, name_hash, value_hash, + mem); if (rv != 0) { - free(new_ent); + nghttp2_mem_free(mem, new_ent); return NULL; } @@ -767,19 +780,26 @@ static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context, immediately evicted. */ --new_ent->ref; } else { - rv = hd_ringbuf_push_front(&context->hd_table, new_ent); + rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem); if (rv != 0) { --new_ent->ref; - /* nv->name and nv->value are managed by caller. */ - new_ent->nv.name = NULL; - new_ent->nv.namelen = 0; - new_ent->nv.value = NULL; - new_ent->nv.valuelen = 0; + if ((entry_flags & NGHTTP2_HD_FLAG_NAME_ALLOC) && + (entry_flags & NGHTTP2_HD_FLAG_NAME_GIFT)) { + /* nv->name are managed by caller. */ + new_ent->nv.name = NULL; + new_ent->nv.namelen = 0; + } + if ((entry_flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) && + (entry_flags & NGHTTP2_HD_FLAG_VALUE_GIFT)) { + /* nv->value are managed by caller. */ + new_ent->nv.value = NULL; + new_ent->nv.valuelen = 0; + } - nghttp2_hd_entry_free(new_ent); - free(new_ent); + nghttp2_hd_entry_free(new_ent, mem); + nghttp2_mem_free(mem, new_ent); return NULL; } @@ -865,6 +885,10 @@ static search_result search_hd_table(nghttp2_hd_context *context, } static void hd_context_shrink_table_size(nghttp2_hd_context *context) { + nghttp2_mem *mem; + + mem = context->mem; + while (context->hd_table_bufsize > context->hd_table_bufsize_max && context->hd_table.len > 0) { size_t idx = context->hd_table.len - 1; @@ -872,8 +896,8 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context) { context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen); hd_ringbuf_pop_back(&context->hd_table); if (--ent->ref == 0) { - nghttp2_hd_entry_free(ent); - free(ent); + nghttp2_hd_entry_free(ent, mem); + nghttp2_mem_free(mem, ent); } } } @@ -949,6 +973,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, int incidx = 0; uint32_t name_hash = hash(nv->name, nv->namelen); uint32_t value_hash = hash(nv->value, nv->valuelen); + nghttp2_mem *mem; DEBUGF(fprintf(stderr, "deflatehd: deflating ")); DEBUGF(fwrite(nv->name, nv->namelen, 1, stderr)); @@ -956,6 +981,8 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, DEBUGF(fwrite(nv->value, nv->valuelen, 1, stderr)); DEBUGF(fprintf(stderr, "\n")); + mem = deflater->ctx.mem; + res = search_hd_table(&deflater->ctx, nv, name_hash, value_hash); idx = res.index; @@ -994,8 +1021,8 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs, return NGHTTP2_ERR_HEADER_COMP; } if (new_ent->ref == 0) { - nghttp2_hd_entry_free(new_ent); - free(new_ent); + nghttp2_hd_entry_free(new_ent, mem); + nghttp2_mem_free(mem, new_ent); } incidx = 1; } @@ -1068,8 +1095,11 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, uint8_t *buf, size_t nvlen) { nghttp2_bufs bufs; int rv; + nghttp2_mem *mem; + + mem = deflater->ctx.mem; - rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen); + rv = nghttp2_bufs_wrap_init(&bufs, buf, buflen, mem); if (rv != 0) { return rv; @@ -1120,19 +1150,30 @@ size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater _U_, int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, size_t deflate_hd_table_bufsize_max) { + return nghttp2_hd_deflate_new2(deflater_ptr, deflate_hd_table_bufsize_max, + NULL); +} + +int nghttp2_hd_deflate_new2(nghttp2_hd_deflater **deflater_ptr, + size_t deflate_hd_table_bufsize_max, + nghttp2_mem *mem) { int rv; nghttp2_hd_deflater *deflater; - deflater = (nghttp2_hd_deflater *)malloc(sizeof(nghttp2_hd_deflater)); + if (mem == NULL) { + mem = nghttp2_mem_default(); + } + + deflater = (nghttp2_hd_deflater *)nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_deflater)); if (deflater == NULL) { return NGHTTP2_ERR_NOMEM; } - rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max); + rv = nghttp2_hd_deflate_init2(deflater, deflate_hd_table_bufsize_max, mem); if (rv != 0) { - free(deflater); + nghttp2_mem_free(mem, deflater); return rv; } @@ -1143,9 +1184,13 @@ int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr, } void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) { + nghttp2_mem *mem; + + mem = deflater->ctx.mem; + nghttp2_hd_deflate_free(deflater); - free(deflater); + nghttp2_mem_free(mem, deflater); } static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater, @@ -1346,6 +1391,9 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out) { int rv; nghttp2_nv nv; + nghttp2_mem *mem; + + mem = inflater->ctx.mem; rv = hd_inflate_remove_bufs(inflater, &nv, 0 /* name and value */); if (rv != 0) { @@ -1378,7 +1426,7 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater, return 0; } - free(nv.name); + nghttp2_mem_free(mem, nv.name); return NGHTTP2_ERR_NOMEM; } @@ -1408,6 +1456,9 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater, int rv; nghttp2_nv nv; nghttp2_hd_entry *ent_name; + nghttp2_mem *mem; + + mem = inflater->ctx.mem; rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */); if (rv != 0) { @@ -1444,8 +1495,8 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater, hash(nv.value, nv.valuelen), ent_flags); if (!static_name && --ent_name->ref == 0) { - nghttp2_hd_entry_free(ent_name); - free(ent_name); + nghttp2_hd_entry_free(ent_name, mem); + nghttp2_mem_free(mem, ent_name); } if (new_ent) { @@ -1456,7 +1507,7 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater, return 0; } - free(nv.value); + nghttp2_mem_free(mem, nv.value); return NGHTTP2_ERR_NOMEM; } @@ -1812,19 +1863,28 @@ int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) { } int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) { + return nghttp2_hd_inflate_new2(inflater_ptr, NULL); +} + +int nghttp2_hd_inflate_new2(nghttp2_hd_inflater **inflater_ptr, + nghttp2_mem *mem) { int rv; nghttp2_hd_inflater *inflater; - inflater = (nghttp2_hd_inflater *)malloc(sizeof(nghttp2_hd_inflater)); + if (mem == NULL) { + mem = nghttp2_mem_default(); + } + + inflater = (nghttp2_hd_inflater *)nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_inflater)); if (inflater == NULL) { return NGHTTP2_ERR_NOMEM; } - rv = nghttp2_hd_inflate_init(inflater); + rv = nghttp2_hd_inflate_init(inflater, mem); if (rv != 0) { - free(inflater); + nghttp2_mem_free(mem, inflater); return rv; } @@ -1835,9 +1895,12 @@ int nghttp2_hd_inflate_new(nghttp2_hd_inflater **inflater_ptr) { } void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater) { + nghttp2_mem *mem; + + mem = inflater->ctx.mem; nghttp2_hd_inflate_free(inflater); - free(inflater); + nghttp2_mem_free(mem, inflater); } int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t idx, diff --git a/epan/nghttp2/nghttp2_hd.h b/epan/nghttp2/nghttp2_hd.h index aba0d9a5f6..1ed42c2ada 100644 --- a/epan/nghttp2/nghttp2_hd.h +++ b/epan/nghttp2/nghttp2_hd.h @@ -33,6 +33,7 @@ #include "nghttp2_hd_huffman.h" #include "nghttp2_buf.h" +#include "nghttp2_mem.h" #define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE #define NGHTTP2_HD_ENTRY_OVERHEAD 32 @@ -109,6 +110,8 @@ typedef enum { typedef struct { /* dynamic header table */ nghttp2_hd_ringbuf hd_table; + /* Memory allocator */ + nghttp2_mem *mem; /* Abstract buffer size of hd_table as described in the spec. This is the sum of length of name/value in hd_table + NGHTTP2_HD_ENTRY_OVERHEAD bytes overhead per each entry. */ @@ -185,9 +188,10 @@ struct nghttp2_hd_inflater { */ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name, size_t namelen, uint8_t *value, size_t valuelen, - uint32_t name_hash, uint32_t value_hash); + uint32_t name_hash, uint32_t value_hash, + nghttp2_mem *mem); -void nghttp2_hd_entry_free(nghttp2_hd_entry *ent); +void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem); /* * Initializes |deflater| for deflating name/values pairs. @@ -203,7 +207,7 @@ void nghttp2_hd_entry_free(nghttp2_hd_entry *ent); * NGHTTP2_ERR_NOMEM * Out of memory. */ -int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater); +int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_mem *mem); /* * Initializes |deflater| for deflating name/values pairs. @@ -219,7 +223,8 @@ int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater); * Out of memory. */ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater, - size_t deflate_hd_table_bufsize_max); + size_t deflate_hd_table_bufsize_max, + nghttp2_mem *mem); /* * Deallocates any resources allocated for |deflater|. @@ -259,7 +264,7 @@ int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater, * :enum:`NGHTTP2_ERR_NOMEM` * Out of memory. */ -int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater); +int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem); /* * Deallocates any resources allocated for |inflater|. diff --git a/epan/nghttp2/nghttp2_hd_huffman.c b/epan/nghttp2/nghttp2_hd_huffman.c index 1f5388c79b..6c4b2b64ce 100644 --- a/epan/nghttp2/nghttp2_hd_huffman.c +++ b/epan/nghttp2/nghttp2_hd_huffman.c @@ -44,56 +44,72 @@ static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr, size_t rembits, const nghttp2_huff_sym *sym) { int rv; size_t nbits = sym->nbits; + uint32_t code = sym->code; - for (;;) { - if (rembits > nbits) { - if (*avail_ptr) { - nghttp2_bufs_fast_orb_hold(bufs, sym->code << (rembits - nbits)); - } else { - rv = nghttp2_bufs_orb_hold(bufs, sym->code << (rembits - nbits)); - if (rv != 0) { - return rv; - } - - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - } + /* We assume that sym->nbits <= 32 */ + if (rembits > nbits) { + nghttp2_bufs_fast_orb_hold(bufs, code << (rembits - nbits)); + return (ssize_t)(rembits - nbits); + } - rembits -= nbits; + if (rembits == nbits) { + nghttp2_bufs_fast_orb(bufs, code); + --*avail_ptr; + return 8; + } - break; - } + nghttp2_bufs_fast_orb(bufs, code >> (nbits - rembits)); + --*avail_ptr; - if (*avail_ptr) { - nghttp2_bufs_fast_orb(bufs, sym->code >> (nbits - rembits)); - --*avail_ptr; - } else { - rv = nghttp2_bufs_orb(bufs, sym->code >> (nbits - rembits)); - if (rv != 0) { - return rv; - } + nbits -= rembits; + if (nbits & 0x7) { + /* align code to MSB byte boundary */ + code <<= 8 - (nbits & 0x7); + } - *avail_ptr = nghttp2_bufs_cur_avail(bufs); + /* we lose at most 3 bytes, but it is not critical in practice */ + if (*avail_ptr < (nbits + 7) / 8) { + rv = nghttp2_bufs_advance(bufs); + if (rv != 0) { + return rv; } + *avail_ptr = nghttp2_bufs_cur_avail(bufs); + /* we assume that we at least 3 buffer space available */ + assert(*avail_ptr >= 3); + } - nbits -= rembits; - rembits = 8; + /* fast path, since most code is less than 8 */ + if (nbits < 8) { + nghttp2_bufs_fast_addb_hold(bufs, code); + *avail_ptr = nghttp2_bufs_cur_avail(bufs); + return (ssize_t)(8 - nbits); + } - if (nbits == 0) { - break; - } + /* handle longer code path */ + if (nbits > 24) { + nghttp2_bufs_fast_addb(bufs, code >> 24); + nbits -= 8; + } - if (*avail_ptr) { - nghttp2_bufs_fast_addb_hold(bufs, 0); - } else { - rv = nghttp2_bufs_addb_hold(bufs, 0); - if (rv != 0) { - return rv; - } + if (nbits > 16) { + nghttp2_bufs_fast_addb(bufs, code >> 16); + nbits -= 8; + } - *avail_ptr = nghttp2_bufs_cur_avail(bufs); - } + if (nbits > 8) { + nghttp2_bufs_fast_addb(bufs, code >> 8); + nbits -= 8; } - return (ssize_t)rembits; + + if (nbits == 8) { + nghttp2_bufs_fast_addb(bufs, code); + *avail_ptr = nghttp2_bufs_cur_avail(bufs); + return 8; + } + + nghttp2_bufs_fast_addb_hold(bufs, code); + *avail_ptr = nghttp2_bufs_cur_avail(bufs); + return (ssize_t)(8 - nbits); } size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len) { @@ -136,17 +152,12 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src, } /* 256 is special terminal symbol, pad with its prefix */ if (rembits < 8) { + /* if rembits < 8, we should have at least 1 buffer space + available */ const nghttp2_huff_sym *sym = &huff_sym_table[256]; - + assert(avail); /* Caution we no longer adjust avail here */ - if (avail) { - nghttp2_bufs_fast_orb(bufs, sym->code >> (sym->nbits - rembits)); - } else { - rv = nghttp2_bufs_orb(bufs, sym->code >> (sym->nbits - rembits)); - if (rv != 0) { - return rv; - } - } + nghttp2_bufs_fast_orb(bufs, sym->code >> (sym->nbits - rembits)); } return 0; diff --git a/epan/nghttp2/nghttp2_helper.c b/epan/nghttp2/nghttp2_helper.c index 8244068f5e..1be8d0dc4d 100644 --- a/epan/nghttp2/nghttp2_helper.c +++ b/epan/nghttp2/nghttp2_helper.c @@ -51,14 +51,14 @@ uint32_t nghttp2_get_uint32(const uint8_t *data) { return ntohl(n); } -void *nghttp2_memdup(const void *src, size_t n) { +void *nghttp2_memdup(const void *src, size_t n, nghttp2_mem *mem) { void *dest; if (n == 0) { return NULL; } - dest = malloc(n); + dest = nghttp2_mem_malloc(mem, n); if (dest == NULL) { return NULL; } @@ -172,54 +172,59 @@ int nghttp2_adjust_local_window_size(int32_t *local_window_size_ptr, int32_t *recv_reduction_ptr, int32_t *delta_ptr) { if (*delta_ptr > 0) { + int32_t recv_reduction_delta; + int32_t delta; int32_t new_recv_window_size = nghttp2_max(0, *recv_window_size_ptr) - *delta_ptr; - if (new_recv_window_size < 0) { - /* The delta size is strictly more than received bytes. Increase - local_window_size by that difference. */ - int32_t recv_reduction_diff; - if (*local_window_size_ptr > - NGHTTP2_MAX_WINDOW_SIZE + new_recv_window_size) { - return NGHTTP2_ERR_FLOW_CONTROL; - } - *local_window_size_ptr -= new_recv_window_size; - /* If there is recv_reduction due to earlier window_size - reduction, we have to adjust it too. */ - recv_reduction_diff = - nghttp2_min(*recv_reduction_ptr, -new_recv_window_size); - *recv_reduction_ptr -= recv_reduction_diff; - if (*recv_window_size_ptr < 0) { - *recv_window_size_ptr += recv_reduction_diff; - } else { - /* If *recv_window_size_ptr > 0, then those bytes are going to - be backed to the remote peer (by WINDOW_UPDATE with the - adjusted *delta_ptr), so it is effectively 0 now. We set - to *recv_reduction_diff, because caller does not take into - account it in *delta_ptr. */ - *recv_window_size_ptr = recv_reduction_diff; - } - /* recv_reduction_diff must be paied from *delta_ptr, since it - was added in window size reduction (see below). */ - *delta_ptr -= recv_reduction_diff; - } else { + + if (new_recv_window_size >= 0) { *recv_window_size_ptr = new_recv_window_size; + return 0; } - return 0; - } else { - if (*local_window_size_ptr + *delta_ptr < 0 || - *recv_window_size_ptr < INT32_MIN - *delta_ptr || - *recv_reduction_ptr > INT32_MAX + *delta_ptr) { + + delta = -new_recv_window_size; + + /* The delta size is strictly more than received bytes. Increase + local_window_size by that difference |delta|. */ + if (*local_window_size_ptr > NGHTTP2_MAX_WINDOW_SIZE - delta) { return NGHTTP2_ERR_FLOW_CONTROL; } - /* Decreasing local window size. Note that we achieve this without - noticing to the remote peer. To do this, we cut - recv_window_size by -delta. This means that we don't send - WINDOW_UPDATE for -delta bytes. */ - *local_window_size_ptr += *delta_ptr; - *recv_window_size_ptr += *delta_ptr; - *recv_reduction_ptr -= *delta_ptr; - *delta_ptr = 0; + *local_window_size_ptr += delta; + /* If there is recv_reduction due to earlier window_size + reduction, we have to adjust it too. */ + recv_reduction_delta = nghttp2_min(*recv_reduction_ptr, delta); + *recv_reduction_ptr -= recv_reduction_delta; + if (*recv_window_size_ptr < 0) { + *recv_window_size_ptr += recv_reduction_delta; + } else { + /* If *recv_window_size_ptr > 0, then those bytes are going to + be returned to the remote peer (by WINDOW_UPDATE with the + adjusted *delta_ptr), so it is effectively 0 now. We set to + *recv_reduction_delta, because caller does not take into + account it in *delta_ptr. */ + *recv_window_size_ptr = recv_reduction_delta; + } + /* recv_reduction_delta must be paied from *delta_ptr, since it + was added in window size reduction (see below). */ + *delta_ptr -= recv_reduction_delta; + + return 0; } + + if (*local_window_size_ptr + *delta_ptr < 0 || + *recv_window_size_ptr < INT32_MIN - *delta_ptr || + *recv_reduction_ptr > INT32_MAX + *delta_ptr) { + return NGHTTP2_ERR_FLOW_CONTROL; + } + /* Decreasing local window size. Note that we achieve this without + noticing to the remote peer. To do this, we cut + recv_window_size by -delta. This means that we don't send + WINDOW_UPDATE for -delta bytes. */ + *local_window_size_ptr += *delta_ptr; + *recv_window_size_ptr += *delta_ptr; + *recv_reduction_ptr -= *delta_ptr; + *delta_ptr = 0; + return 0; } @@ -299,8 +304,6 @@ const char *nghttp2_strerror(int error_code) { } } -void nghttp2_free(void *ptr) { free(ptr); } - /* Generated by gennmchartbl.py */ static int VALID_HD_NAME_CHARS[] = { 0 /* NUL */, 0 /* SOH */, 0 /* STX */, 0 /* ETX */, 0 /* EOT */, diff --git a/epan/nghttp2/nghttp2_helper.h b/epan/nghttp2/nghttp2_helper.h index e21ec1ea75..0facb1ce41 100644 --- a/epan/nghttp2/nghttp2_helper.h +++ b/epan/nghttp2/nghttp2_helper.h @@ -28,6 +28,7 @@ #include <config.h> #include <nghttp2.h> +#include "nghttp2_mem.h" #define nghttp2_min(A, B) ((A) < (B) ? (A) : (B)) #define nghttp2_max(A, B) ((A) > (B) ? (A) : (B)) @@ -66,7 +67,7 @@ uint32_t nghttp2_get_uint32(const uint8_t *data); * NGHTTP2_ERR_NOMEM * Out of memory. */ -void *nghttp2_memdup(const void *src, size_t n); +void *nghttp2_memdup(const void *src, size_t n, nghttp2_mem *mem); void nghttp2_downcase(uint8_t *s, size_t len); @@ -98,14 +99,6 @@ int nghttp2_should_send_window_update(int32_t local_window_size, int32_t recv_window_size); /* - * Deallocates memory space pointed by |ptr|. This function exists for - * the application to free the memory space allocated by the library - * functions. Currently this function is hidden from the public API, - * but may be exposed as public API. - */ -void nghttp2_free(void *ptr); - -/* * Copies the buffer |src| of length |len| to the destination pointed * by the |dest|, assuming that the |dest| is at lest |len| bytes long * . Returns dest + len. diff --git a/epan/nghttp2/nghttp2_mem.c b/epan/nghttp2/nghttp2_mem.c new file mode 100644 index 0000000000..e7d5aae3b8 --- /dev/null +++ b/epan/nghttp2/nghttp2_mem.c @@ -0,0 +1,61 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#include "nghttp2_mem.h" + +static void *default_malloc(size_t size, void *mem_user_data _U_) { + return malloc(size); +} + +static void default_free(void *ptr, void *mem_user_data _U_) { free(ptr); } + +static void *default_calloc(size_t nmemb, size_t size, + void *mem_user_data _U_) { + return calloc(nmemb, size); +} + +static void *default_realloc(void *ptr, size_t size, void *mem_user_data _U_) { + return realloc(ptr, size); +} + +static nghttp2_mem mem_default = {NULL, default_malloc, default_free, + default_calloc, default_realloc}; + +nghttp2_mem *nghttp2_mem_default(void) { return &mem_default; } + +void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size) { + return mem->malloc(size, mem->mem_user_data); +} + +void nghttp2_mem_free(nghttp2_mem *mem, void *ptr) { + mem->free(ptr, mem->mem_user_data); +} + +void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size) { + return mem->calloc(nmemb, size, mem->mem_user_data); +} + +void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size) { + return mem->realloc(ptr, size, mem->mem_user_data); +} diff --git a/epan/nghttp2/nghttp2_mem.h b/epan/nghttp2/nghttp2_mem.h new file mode 100644 index 0000000000..47e3fcdfd0 --- /dev/null +++ b/epan/nghttp2/nghttp2_mem.h @@ -0,0 +1,44 @@ +/* + * nghttp2 - HTTP/2 C Library + * + * Copyright (c) 2014 Tatsuhiro Tsujikawa + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sublicense, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ +#ifndef NGHTTP2_MEM_H +#define NGHTTP2_MEM_H + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif /* HAVE_CONFIG_H */ + +#include <nghttp2.h> + +/* The default, system standard memory allocator */ +nghttp2_mem *nghttp2_mem_default(void); + +/* Convenient wrapper functions to call allocator function in + |mem|. */ +void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size); +void nghttp2_mem_free(nghttp2_mem *mem, void *ptr); +void *nghttp2_mem_calloc(nghttp2_mem *mem, size_t nmemb, size_t size); +void *nghttp2_mem_realloc(nghttp2_mem *mem, void *ptr, size_t size); + +#endif /* NGHTTP2_MEM_H */ diff --git a/epan/nghttp2/nghttp2ver.h b/epan/nghttp2/nghttp2ver.h index 04d405a1c0..d1bc38dbc6 100644 --- a/epan/nghttp2/nghttp2ver.h +++ b/epan/nghttp2/nghttp2ver.h @@ -29,7 +29,7 @@ * @macro * Version number of the nghttp2 library release */ -#define NGHTTP2_VERSION "0.6.7" +#define NGHTTP2_VERSION "0.7.1" /** * @macro @@ -37,6 +37,6 @@ * release. This is a 24 bit number with 8 bits for major number, 8 bits * for minor and 8 bits for patch. Version 1.2.3 becomes 0x010203. */ -#define NGHTTP2_VERSION_NUM 0x000607 +#define NGHTTP2_VERSION_NUM 0x000701 #endif /* NGHTTP2VER_H */ |