aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--epan/CMakeLists.txt1
-rw-r--r--epan/nghttp2/Makefile.common4
-rw-r--r--epan/nghttp2/README.nghttp21
-rw-r--r--epan/nghttp2/nghttp2.h245
-rw-r--r--epan/nghttp2/nghttp2_buf.c62
-rw-r--r--epan/nghttp2/nghttp2_buf.h21
-rw-r--r--epan/nghttp2/nghttp2_hd.c187
-rw-r--r--epan/nghttp2/nghttp2_hd.h15
-rw-r--r--epan/nghttp2/nghttp2_hd_huffman.c107
-rw-r--r--epan/nghttp2/nghttp2_helper.c93
-rw-r--r--epan/nghttp2/nghttp2_helper.h11
-rw-r--r--epan/nghttp2/nghttp2_mem.c61
-rw-r--r--epan/nghttp2/nghttp2_mem.h44
-rw-r--r--epan/nghttp2/nghttp2ver.h4
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 */