aboutsummaryrefslogtreecommitdiffstats
path: root/epan
diff options
context:
space:
mode:
authorAlexis La Goutte <alexis.lagoutte@gmail.com>2016-05-26 23:05:33 +0200
committerPascal Quantin <pascal.quantin@gmail.com>2016-05-31 07:18:25 +0000
commit68903e7b934ddeb909899ac7aa1249adfed69d8f (patch)
tree216c50d862b914929e787d49747504ad21fbcf7c /epan
parent7723ed6494498726feafe47858038d569cc82203 (diff)
Update to nghttp2 1.11.1
Change-Id: I308b4db02b1501f38b2693b45b2b9bd6054376d1 Reviewed-on: https://code.wireshark.org/review/15579 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com> Reviewed-by: Pascal Quantin <pascal.quantin@gmail.com>
Diffstat (limited to 'epan')
-rw-r--r--epan/nghttp2/CMakeLists.txt1
-rw-r--r--epan/nghttp2/Makefile.common4
-rw-r--r--epan/nghttp2/README.nghttp21
-rw-r--r--epan/nghttp2/nghttp2.h345
-rw-r--r--epan/nghttp2/nghttp2_buf.h6
-rw-r--r--epan/nghttp2/nghttp2_hd.c1030
-rw-r--r--epan/nghttp2/nghttp2_hd.h180
-rw-r--r--epan/nghttp2/nghttp2_hd_huffman.c29
-rw-r--r--epan/nghttp2/nghttp2_helper.c35
-rw-r--r--epan/nghttp2/nghttp2_mem.c4
-rw-r--r--epan/nghttp2/nghttp2_mem.h1
-rw-r--r--epan/nghttp2/nghttp2_rcbuf.c99
-rw-r--r--epan/nghttp2/nghttp2_rcbuf.h80
-rw-r--r--epan/nghttp2/nghttp2ver.h4
14 files changed, 889 insertions, 930 deletions
diff --git a/epan/nghttp2/CMakeLists.txt b/epan/nghttp2/CMakeLists.txt
index f3f35c1b36..7a4851a3a9 100644
--- a/epan/nghttp2/CMakeLists.txt
+++ b/epan/nghttp2/CMakeLists.txt
@@ -31,6 +31,7 @@ set(NGHTTP2_FILES
nghttp2_hd_huffman_data.c
nghttp2_helper.c
nghttp2_mem.c
+ nghttp2_rcbuf.c
)
source_group(nghttp2 FILES ${NGHTTP2_FILES})
diff --git a/epan/nghttp2/Makefile.common b/epan/nghttp2/Makefile.common
index 5ff688188d..277993be72 100644
--- a/epan/nghttp2/Makefile.common
+++ b/epan/nghttp2/Makefile.common
@@ -27,7 +27,8 @@ LIBNGHTTP2_SRC = \
nghttp2_hd_huffman.c \
nghttp2_hd_huffman_data.c \
nghttp2_helper.c \
- nghttp2_mem.c
+ nghttp2_mem.c \
+ nghttp2_rcbuf.c
LIBNGHTTP2_INCLUDES = \
nghttp2_buf.h \
@@ -36,6 +37,7 @@ LIBNGHTTP2_INCLUDES = \
nghttp2_helper.h \
nghttp2_int.h \
nghttp2_mem.h \
+ nghttp2_rcbuf.h \
nghttp2.h \
nghttp2ver.h
diff --git a/epan/nghttp2/README.nghttp2 b/epan/nghttp2/README.nghttp2
index 6fb82c1a2a..4c77a872ab 100644
--- a/epan/nghttp2/README.nghttp2
+++ b/epan/nghttp2/README.nghttp2
@@ -11,6 +11,7 @@ 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_rcbuf.[ch] .
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 87472fa9ad..2fbcfb9aa0 100644
--- a/epan/nghttp2/nghttp2.h
+++ b/epan/nghttp2/nghttp2.h
@@ -432,6 +432,55 @@ typedef enum {
} nghttp2_error;
/**
+ * @struct
+ *
+ * The object representing single contiguous buffer.
+ */
+typedef struct {
+ /**
+ * The pointer to the buffer.
+ */
+ uint8_t *base;
+ /**
+ * The length of the buffer.
+ */
+ size_t len;
+} nghttp2_vec;
+
+struct nghttp2_rcbuf;
+
+/**
+ * @typedef
+ *
+ * The object representing reference counted buffer. The details of
+ * this structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_rcbuf nghttp2_rcbuf;
+
+/**
+ * @function
+ *
+ * Increments the reference count of |rcbuf| by 1.
+ */
+NGHTTP2_EXTERN void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf);
+
+/**
+ * @function
+ *
+ * Decrements the reference count of |rcbuf| by 1. If the reference
+ * count becomes zero, the object pointed by |rcbuf| will be freed.
+ * In this case, application must not use |rcbuf| again.
+ */
+NGHTTP2_EXTERN void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf);
+
+/**
+ * @function
+ *
+ * Returns the underlying buffer managed by |rcbuf|.
+ */
+NGHTTP2_EXTERN nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf);
+
+/**
* @enum
*
* The flags for header field name/value pair.
@@ -554,7 +603,12 @@ typedef enum {
* callbacks because the library processes this frame type and its
* preceding HEADERS/PUSH_PROMISE as a single frame.
*/
- NGHTTP2_CONTINUATION = 0x09
+ NGHTTP2_CONTINUATION = 0x09,
+ /**
+ * The ALTSVC frame, which is defined in `RFC 7383
+ * <https://tools.ietf.org/html/rfc7838#section-4>`_.
+ */
+ NGHTTP2_ALTSVC = 0x0a
} nghttp2_frame_type;
/**
@@ -1642,6 +1696,32 @@ typedef int (*nghttp2_on_header_callback)(nghttp2_session *session,
/**
* @functypedef
*
+ * Callback function invoked when a header name/value pair is received
+ * for the |frame|. The |name| is header name. The |value| is header
+ * value. The |flags| is bitwise OR of one or more of
+ * :type:`nghttp2_nv_flag`.
+ *
+ * This callback behaves like :type:`nghttp2_on_header_callback`,
+ * except that |name| and |value| are stored in reference counted
+ * buffer. If application wishes to keep these references without
+ * copying them, use `nghttp2_rcbuf_incref()` to increment their
+ * reference count. It is the application's responsibility to call
+ * `nghttp2_rcbuf_decref()` if they called `nghttp2_rcbuf_incref()` so
+ * as not to leak memory. If the |session| is created by
+ * `nghttp2_session_server_new3()` or `nghttp2_session_client_new3()`,
+ * the function to free memory is the one belongs to the mem
+ * parameter. As long as this free function alives, |name| and
+ * |value| can live after |session| was destroyed.
+ */
+typedef int (*nghttp2_on_header_callback2)(nghttp2_session *session,
+ const nghttp2_frame *frame,
+ nghttp2_rcbuf *name,
+ nghttp2_rcbuf *value, uint8_t flags,
+ void *user_data);
+
+/**
+ * @functypedef
+ *
* Callback function invoked when the library asks application how
* many padding bytes are required for the transmission of the
* |frame|. The application must choose the total length of payload
@@ -1809,6 +1889,31 @@ typedef ssize_t (*nghttp2_pack_extension_callback)(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data);
+/**
+ * @functypedef
+ *
+ * Callback function invoked when library provides the error message
+ * intended for human consumption. This callback is solely for
+ * debugging purpose. The |msg| is typically NULL-terminated string
+ * of length |len|. |len| does not include the sentinel NULL
+ * character.
+ *
+ * The format of error message may change between nghttp2 library
+ * versions. The application should not depend on the particular
+ * format.
+ *
+ * Normally, application should return 0 from this callback. If fatal
+ * error occurred while doing something in this callback, application
+ * should return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. In this case,
+ * library will return immediately with return value
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. Currently, if nonzero value
+ * is returned from this callback, they are treated as
+ * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`, but application should not
+ * rely on this details.
+ */
+typedef int (*nghttp2_error_callback)(nghttp2_session *session, const char *msg,
+ size_t len, void *user_data);
+
struct nghttp2_session_callbacks;
/**
@@ -1953,7 +2058,10 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_begin_headers_callback(
* @function
*
* Sets callback function invoked when a header name/value pair is
- * received.
+ * received. If both
+ * `nghttp2_session_callbacks_set_on_header_callback()` and
+ * `nghttp2_session_callbacks_set_on_header_callback2()` are used to
+ * set callbacks, the latter has the precedence.
*/
NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback(
nghttp2_session_callbacks *cbs,
@@ -1962,6 +2070,16 @@ NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback(
/**
* @function
*
+ * Sets callback function invoked when a header name/value pair is
+ * received.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_on_header_callback2(
+ nghttp2_session_callbacks *cbs,
+ nghttp2_on_header_callback2 on_header_callback2);
+
+/**
+ * @function
+ *
* Sets callback function invoked when the library asks application
* how many padding bytes are required for the transmission of the
* given frame.
@@ -2033,6 +2151,15 @@ nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
nghttp2_on_extension_chunk_recv_callback on_extension_chunk_recv_callback);
/**
+ * @function
+ *
+ * Sets callback function invoked when library tells error message to
+ * the application.
+ */
+NGHTTP2_EXTERN void nghttp2_session_callbacks_set_error_callback(
+ nghttp2_session_callbacks *cbs, nghttp2_error_callback error_callback);
+
+/**
* @functypedef
*
* Custom memory allocator to replace malloc(). The |mem_user_data|
@@ -2266,6 +2393,40 @@ nghttp2_option_set_user_recv_extension_type(nghttp2_option *option,
/**
* @function
*
+ * Sets extension frame type the application is willing to receive
+ * using builtin handler. The |type| is the extension frame type to
+ * receive, and must be strictly greater than 0x9. Otherwise, this
+ * function does nothing. The application can call this function
+ * multiple times to set more than one frame type to receive. The
+ * application does not have to call this function if it just sends
+ * extension frames.
+ *
+ * If same frame type is passed to both
+ * `nghttp2_option_set_builtin_recv_extension_type()` and
+ * `nghttp2_option_set_user_recv_extension_type()`, the latter takes
+ * precedence.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_builtin_recv_extension_type(nghttp2_option *option,
+ uint8_t type);
+
+/**
+ * @function
+ *
+ * This option prevents the library from sending PING frame with ACK
+ * flag set automatically when PING frame without ACK flag set is
+ * received. If this option is set to nonzero, the library won't send
+ * PING frame with ACK flag set in the response for incoming PING
+ * frame. The application can send PING frame with ACK flag set using
+ * `nghttp2_submit_ping()` with :enum:`NGHTTP2_FLAG_ACK` as flags
+ * parameter.
+ */
+NGHTTP2_EXTERN void nghttp2_option_set_no_auto_ping_ack(nghttp2_option *option,
+ int val);
+
+/**
+ * @function
+ *
* Initializes |*session_ptr| for client use. The all members of
* |callbacks| are copied to |*session_ptr|. Therefore |*session_ptr|
* does not store |callbacks|. The |user_data| is an arbitrary user
@@ -3239,6 +3400,16 @@ NGHTTP2_EXTERN const char *nghttp2_strerror(int lib_error_code);
/**
* @function
*
+ * Returns string representation of HTTP/2 error code |error_code|
+ * (e.g., ``PROTOCOL_ERROR`` is returned if ``error_code ==
+ * NGHTTP2_PROTOCOL_ERROR``). If string representation is unknown for
+ * given |error_code|, this function returns string ``unknown``.
+ */
+NGHTTP2_EXTERN const char *nghttp2_http2_strerror(uint32_t error_code);
+
+/**
+ * @function
+ *
* Initializes |pri_spec| with the |stream_id| of the stream to depend
* on with |weight| and its exclusive flag. If |exclusive| is
* nonzero, exclusive flag is set.
@@ -3785,8 +3956,12 @@ nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
* received PING frame. The library automatically submits PING frame
* in this case.
*
- * The |flags| is currently ignored and should be
- * :enum:`NGHTTP2_FLAG_NONE`.
+ * The |flags| is bitwise OR of 0 or more of the following value.
+ *
+ * * :enum:`NGHTTP2_FLAG_ACK`
+ *
+ * Unless `nghttp2_option_set_no_auto_ping_ack()` is used, the |flags|
+ * should be :enum:`NGHTTP2_FLAG_NONE`.
*
* If the |opaque_data| is non ``NULL``, then it should point to the 8
* bytes array of memory to specify opaque data to send with PING
@@ -3976,6 +4151,80 @@ NGHTTP2_EXTERN int nghttp2_submit_extension(nghttp2_session *session,
int32_t stream_id, void *payload);
/**
+ * @struct
+ *
+ * The payload of ALTSVC frame. ALTSVC frame is a non-critical
+ * extension to HTTP/2. If this frame is received, and
+ * `nghttp2_option_set_user_recv_extension_type()` is not set, and
+ * `nghttp2_option_set_builtin_recv_extension_type()` is set for
+ * :enum:`NGHTTP2_ALTSVC`, ``nghttp2_extension.payload`` will point to
+ * this struct.
+ *
+ * It has the following members:
+ */
+typedef struct {
+ /**
+ * The pointer to origin which this alternative service is
+ * associated with. This is not necessarily NULL-terminated.
+ */
+ uint8_t *origin;
+ /**
+ * The length of the |origin|.
+ */
+ size_t origin_len;
+ /**
+ * The pointer to Alt-Svc field value contained in ALTSVC frame.
+ * This is not necessarily NULL-terminated.
+ */
+ uint8_t *field_value;
+ /**
+ * The length of the |field_value|.
+ */
+ size_t field_value_len;
+} nghttp2_ext_altsvc;
+
+/**
+ * @function
+ *
+ * Submits ALTSVC frame.
+ *
+ * ALTSVC frame is a non-critical extension to HTTP/2, and defined in
+ * is defined in `RFC 7383
+ * <https://tools.ietf.org/html/rfc7838#section-4>`_.
+ *
+ * The |flags| is currently ignored and should be
+ * :enum:`NGHTTP2_FLAG_NONE`.
+ *
+ * The |origin| points to the origin this alternative service is
+ * associated with. The |origin_len| is the length of the origin. If
+ * |stream_id| is 0, the origin must be specified. If |stream_id| is
+ * not zero, the origin must be empty (in other words, |origin_len|
+ * must be 0).
+ *
+ * The ALTSVC frame is only usable from server side. If this function
+ * is invoked with client side session, this function returns
+ * :enum:`NGHTTP2_ERR_INVALID_STATE`.
+ *
+ * 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_INVALID_STATE`
+ * The function is called from client side session
+ * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
+ * The sum of |origin_len| and |field_value_len| is larger than
+ * 16382; or |origin_len| is 0 while |stream_id| is 0; or
+ * |origin_len| is not 0 while |stream_id| is not 0.
+ */
+NGHTTP2_EXTERN int nghttp2_submit_altsvc(nghttp2_session *session,
+ uint8_t flags, int32_t stream_id,
+ const uint8_t *origin,
+ size_t origin_len,
+ const uint8_t *field_value,
+ size_t field_value_len);
+
+/**
* @function
*
* Compares ``lhs->name`` of length ``lhs->namelen`` bytes and
@@ -4316,7 +4565,7 @@ NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater);
* This function must not be called while header block is being
* inflated. In other words, this function must be called after
* initialization of |inflater|, but before calling
- * `nghttp2_hd_inflate_hd()`, or after
+ * `nghttp2_hd_inflate_hd2()`, or after
* `nghttp2_hd_inflate_end_headers()`. Otherwise,
* `NGHTTP2_ERR_INVALID_STATE` was returned.
*
@@ -4357,6 +4606,10 @@ typedef enum {
/**
* @function
*
+ * .. warning::
+ *
+ * Deprecated. Use `nghttp2_hd_inflate_hd2()` instead.
+ *
* Inflates name/value block stored in |in| with length |inlen|. This
* function performs decompression. For each successful emission of
* header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in
@@ -4439,6 +4692,88 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
/**
* @function
*
+ * Inflates name/value block stored in |in| with length |inlen|. This
+ * function performs decompression. For each successful emission of
+ * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in
+ * |*inflate_flags| and name/value pair is assigned to the |nv_out|
+ * and the function returns. The caller must not free the members of
+ * |nv_out|.
+ *
+ * The |nv_out| may include pointers to the memory region in the |in|.
+ * The caller must retain the |in| while the |nv_out| is used.
+ *
+ * The application should call this function repeatedly until the
+ * ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and
+ * return value is non-negative. This means the all input values are
+ * processed successfully. Then the application must call
+ * `nghttp2_hd_inflate_end_headers()` to prepare for the next header
+ * block input.
+ *
+ * The caller can feed complete compressed header block. It also can
+ * feed it in several chunks. The caller must set |in_final| to
+ * nonzero if the given input is the last block of the compressed
+ * header.
+ *
+ * This function returns the number of bytes processed if it succeeds,
+ * or one of the following negative error codes:
+ *
+ * :enum:`NGHTTP2_ERR_NOMEM`
+ * Out of memory.
+ * :enum:`NGHTTP2_ERR_HEADER_COMP`
+ * Inflation process has failed.
+ * :enum:`NGHTTP2_ERR_BUFFER_ERROR`
+ * The header field name or value is too large.
+ *
+ * Example follows::
+ *
+ * int inflate_header_block(nghttp2_hd_inflater *hd_inflater,
+ * uint8_t *in, size_t inlen, int final)
+ * {
+ * ssize_t rv;
+ *
+ * for(;;) {
+ * nghttp2_nv nv;
+ * int inflate_flags = 0;
+ *
+ * rv = nghttp2_hd_inflate_hd2(hd_inflater, &nv, &inflate_flags,
+ * in, inlen, final);
+ *
+ * if(rv < 0) {
+ * fprintf(stderr, "inflate failed with error code %zd", rv);
+ * return -1;
+ * }
+ *
+ * in += rv;
+ * inlen -= rv;
+ *
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
+ * fwrite(nv.name, nv.namelen, 1, stderr);
+ * fprintf(stderr, ": ");
+ * fwrite(nv.value, nv.valuelen, 1, stderr);
+ * fprintf(stderr, "\n");
+ * }
+ * if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
+ * nghttp2_hd_inflate_end_headers(hd_inflater);
+ * break;
+ * }
+ * if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
+ * inlen == 0) {
+ * break;
+ * }
+ * }
+ *
+ * return 0;
+ * }
+ *
+ */
+NGHTTP2_EXTERN ssize_t
+nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
+ int *inflate_flags, const uint8_t *in, size_t inlen,
+ int in_final);
+
+/**
+ * @function
+ *
* Signals the end of decompression for one header block.
*
* This function returns 0 if it succeeds. Currently this function
diff --git a/epan/nghttp2/nghttp2_buf.h b/epan/nghttp2/nghttp2_buf.h
index 072e835ec1..fcb4b64416 100644
--- a/epan/nghttp2/nghttp2_buf.h
+++ b/epan/nghttp2/nghttp2_buf.h
@@ -73,7 +73,7 @@ typedef struct {
/*
* Initializes the |buf|. No memory is allocated in this function. Use
- * nghttp2_buf_reserve() or nghttp2_buf_reserve2() to allocate memory.
+ * nghttp2_buf_reserve() to allocate memory.
*/
void nghttp2_buf_init(nghttp2_buf *buf);
@@ -312,8 +312,8 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
} while (0)
/*
- * Copies all data stored in |bufs| to the contagious buffer. This
- * function allocates the contagious memory to store all data in
+ * Copies all data stored in |bufs| to the contiguous buffer. This
+ * function allocates the contiguous memory to store all data in
* |bufs| and assigns it to |*out|.
*
* The contents of |bufs| is left unchanged.
diff --git a/epan/nghttp2/nghttp2_hd.c b/epan/nghttp2/nghttp2_hd.c
index 28598554bc..377067db1f 100644
--- a/epan/nghttp2/nghttp2_hd.c
+++ b/epan/nghttp2/nghttp2_hd.c
@@ -34,15 +34,17 @@
/* Make scalar initialization form of nghttp2_hd_entry */
#define MAKE_STATIC_ENT(N, V, T, H) \
{ \
- { (uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0 } \
- , NULL, 0, (H), (T), 1, NGHTTP2_HD_FLAG_NONE \
+ { NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1 } \
+ , {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
+ {(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
+ T, H \
}
/* Generated by mkstatictbl.py */
/* 3rd parameter is nghttp2_token value for header field name. We use
first enum value if same header names are repeated (e.g.,
:status). */
-static nghttp2_hd_entry static_table[] = {
+static nghttp2_hd_static_entry static_table[] = {
MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
@@ -114,7 +116,7 @@ static int memeq(const void *s1, const void *s2, size_t n) {
* This function was generated by genlibtokenlookup.py. Inspired by
* h2o header lookup. https://github.com/h2o/h2o
*/
-static int lookup_token(const uint8_t *name, size_t namelen) {
+static int32_t lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {
case 2:
switch (name[1]) {
@@ -137,26 +139,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
return NGHTTP2_TOKEN_AGE;
}
break;
- case 'n':
- if (lstreq("tc", name, 2)) {
- return NGHTTP2_TOKEN_TCN;
- }
- break;
- case 'p':
- if (lstreq("p3", name, 2)) {
- return NGHTTP2_TOKEN_P3P;
- }
- break;
- case 't':
- if (lstreq("dn", name, 2)) {
- return NGHTTP2_TOKEN_DNT;
- }
- break;
- case 'v':
- if (lstreq("ts", name, 2)) {
- return NGHTTP2_TOKEN_TSV;
- }
- break;
}
break;
case 4:
@@ -217,31 +199,16 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
break;
case 6:
switch (name[5]) {
- case 'a':
- if (lstreq("pragm", name, 5)) {
- return NGHTTP2_TOKEN_PRAGMA;
- }
- break;
case 'e':
if (lstreq("cooki", name, 5)) {
return NGHTTP2_TOKEN_COOKIE;
}
break;
- case 'n':
- if (lstreq("origi", name, 5)) {
- return NGHTTP2_TOKEN_ORIGIN;
- }
- break;
case 'r':
if (lstreq("serve", name, 5)) {
return NGHTTP2_TOKEN_SERVER;
}
break;
- case 's':
- if (lstreq("statu", name, 5)) {
- return NGHTTP2_TOKEN_STATUS;
- }
- break;
case 't':
if (lstreq("accep", name, 5)) {
return NGHTTP2_TOKEN_ACCEPT;
@@ -254,11 +221,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
break;
case 7:
switch (name[6]) {
- case 'c':
- if (lstreq("alt-sv", name, 6)) {
- return NGHTTP2_TOKEN_ALT_SVC;
- }
- break;
case 'd':
if (lstreq(":metho", name, 6)) {
return NGHTTP2_TOKEN__METHOD;
@@ -277,14 +239,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
if (lstreq("upgrad", name, 6)) {
return NGHTTP2_TOKEN_UPGRADE;
}
- if (lstreq("x-cach", name, 6)) {
- return NGHTTP2_TOKEN_X_CACHE;
- }
- break;
- case 'g':
- if (lstreq("warnin", name, 6)) {
- return NGHTTP2_TOKEN_WARNING;
- }
break;
case 'h':
if (lstreq("refres", name, 6)) {
@@ -295,9 +249,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
if (lstreq("refere", name, 6)) {
return NGHTTP2_TOKEN_REFERER;
}
- if (lstreq("traile", name, 6)) {
- return NGHTTP2_TOKEN_TRAILER;
- }
break;
case 's':
if (lstreq(":statu", name, 6)) {
@@ -346,25 +297,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
break;
}
break;
- case 9:
- switch (name[8]) {
- case 'd':
- if (lstreq("forwarde", name, 8)) {
- return NGHTTP2_TOKEN_FORWARDED;
- }
- break;
- case 'e':
- if (lstreq("negotiat", name, 8)) {
- return NGHTTP2_TOKEN_NEGOTIATE;
- }
- break;
- case 'h':
- if (lstreq("accept-c", name, 8)) {
- return NGHTTP2_TOKEN_ACCEPT_CH;
- }
- break;
- }
- break;
case 10:
switch (name[9]) {
case 'e':
@@ -380,11 +312,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
return NGHTTP2_TOKEN_CONNECTION;
}
break;
- case 's':
- if (lstreq("alternate", name, 9)) {
- return NGHTTP2_TOKEN_ALTERNATES;
- }
- break;
case 't':
if (lstreq("user-agen", name, 9)) {
return NGHTTP2_TOKEN_USER_AGENT;
@@ -399,16 +326,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
break;
case 11:
switch (name[10]) {
- case '2':
- if (lstreq("set-cookie", name, 10)) {
- return NGHTTP2_TOKEN_SET_COOKIE2;
- }
- break;
- case '5':
- if (lstreq("content-md", name, 10)) {
- return NGHTTP2_TOKEN_CONTENT_MD5;
- }
- break;
case 'r':
if (lstreq("retry-afte", name, 10)) {
return NGHTTP2_TOKEN_RETRY_AFTER;
@@ -423,37 +340,16 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
return NGHTTP2_TOKEN_CONTENT_TYPE;
}
break;
- case 'h':
- if (lstreq("accept-patc", name, 11)) {
- return NGHTTP2_TOKEN_ACCEPT_PATCH;
- }
- break;
- case 'p':
- if (lstreq("x-webkit-cs", name, 11)) {
- return NGHTTP2_TOKEN_X_WEBKIT_CSP;
- }
- break;
case 's':
if (lstreq("max-forward", name, 11)) {
return NGHTTP2_TOKEN_MAX_FORWARDS;
}
break;
- case 'y':
- if (lstreq("variant-var", name, 11)) {
- return NGHTTP2_TOKEN_VARIANT_VARY;
- }
- if (lstreq("x-powered-b", name, 11)) {
- return NGHTTP2_TOKEN_X_POWERED_BY;
- }
- break;
}
break;
case 13:
switch (name[12]) {
case 'd':
- if (lstreq("last-event-i", name, 12)) {
- return NGHTTP2_TOKEN_LAST_EVENT_ID;
- }
if (lstreq("last-modifie", name, 12)) {
return NGHTTP2_TOKEN_LAST_MODIFIED;
}
@@ -462,9 +358,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
if (lstreq("content-rang", name, 12)) {
return NGHTTP2_TOKEN_CONTENT_RANGE;
}
- if (lstreq("x-wap-profil", name, 12)) {
- return NGHTTP2_TOKEN_X_WAP_PROFILE;
- }
break;
case 'h':
if (lstreq("if-none-matc", name, 12)) {
@@ -480,9 +373,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
if (lstreq("authorizatio", name, 12)) {
return NGHTTP2_TOKEN_AUTHORIZATION;
}
- if (lstreq("x-api-versio", name, 12)) {
- return NGHTTP2_TOKEN_X_API_VERSION;
- }
break;
case 's':
if (lstreq("accept-range", name, 12)) {
@@ -493,21 +383,11 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
break;
case 14:
switch (name[13]) {
- case 'd':
- if (lstreq("x-att-devicei", name, 13)) {
- return NGHTTP2_TOKEN_X_ATT_DEVICEID;
- }
- break;
case 'h':
if (lstreq("content-lengt", name, 13)) {
return NGHTTP2_TOKEN_CONTENT_LENGTH;
}
break;
- case 'p':
- if (lstreq("x-cache-looku", name, 13)) {
- return NGHTTP2_TOKEN_X_CACHE_LOOKUP;
- }
- break;
case 't':
if (lstreq("accept-charse", name, 13)) {
return NGHTTP2_TOKEN_ACCEPT_CHARSET;
@@ -518,40 +398,15 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
case 15:
switch (name[14]) {
case 'e':
- if (lstreq("accept-datetim", name, 14)) {
- return NGHTTP2_TOKEN_ACCEPT_DATETIME;
- }
if (lstreq("accept-languag", name, 14)) {
return NGHTTP2_TOKEN_ACCEPT_LANGUAGE;
}
- if (lstreq("x-ua-compatibl", name, 14)) {
- return NGHTTP2_TOKEN_X_UA_COMPATIBLE;
- }
break;
case 'g':
if (lstreq("accept-encodin", name, 14)) {
return NGHTTP2_TOKEN_ACCEPT_ENCODING;
}
break;
- case 'r':
- if (lstreq("x-forwarded-fo", name, 14)) {
- return NGHTTP2_TOKEN_X_FORWARDED_FOR;
- }
- break;
- case 's':
- if (lstreq("accept-feature", name, 14)) {
- return NGHTTP2_TOKEN_ACCEPT_FEATURES;
- }
- if (lstreq("front-end-http", name, 14)) {
- return NGHTTP2_TOKEN_FRONT_END_HTTPS;
- }
- if (lstreq("public-key-pin", name, 14)) {
- return NGHTTP2_TOKEN_PUBLIC_KEY_PINS;
- }
- if (lstreq("x-frame-option", name, 14)) {
- return NGHTTP2_TOKEN_X_FRAME_OPTIONS;
- }
- break;
}
break;
case 16:
@@ -569,11 +424,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
return NGHTTP2_TOKEN_CONTENT_ENCODING;
}
break;
- case 'h':
- if (lstreq("x-requested-wit", name, 15)) {
- return NGHTTP2_TOKEN_X_REQUESTED_WITH;
- }
- break;
case 'n':
if (lstreq("content-locatio", name, 15)) {
return NGHTTP2_TOKEN_CONTENT_LOCATION;
@@ -581,14 +431,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
if (lstreq("proxy-connectio", name, 15)) {
return NGHTTP2_TOKEN_PROXY_CONNECTION;
}
- if (lstreq("x-xss-protectio", name, 15)) {
- return NGHTTP2_TOKEN_X_XSS_PROTECTION;
- }
- break;
- case 't':
- if (lstreq("x-forwarded-hos", name, 15)) {
- return NGHTTP2_TOKEN_X_FORWARDED_HOST;
- }
break;
}
break;
@@ -604,16 +446,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
return NGHTTP2_TOKEN_TRANSFER_ENCODING;
}
break;
- case 'o':
- if (lstreq("x-forwarded-prot", name, 16)) {
- return NGHTTP2_TOKEN_X_FORWARDED_PROTO;
- }
- break;
- case 'y':
- if (lstreq("sec-websocket-ke", name, 16)) {
- return NGHTTP2_TOKEN_SEC_WEBSOCKET_KEY;
- }
- break;
}
break;
case 18:
@@ -623,11 +455,6 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
return NGHTTP2_TOKEN_PROXY_AUTHENTICATE;
}
break;
- case 'n':
- if (lstreq("x-content-duratio", name, 17)) {
- return NGHTTP2_TOKEN_X_CONTENT_DURATION;
- }
- break;
}
break;
case 19:
@@ -647,80 +474,12 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
break;
}
break;
- case 20:
- switch (name[19]) {
- case 'n':
- if (lstreq("sec-websocket-origi", name, 19)) {
- return NGHTTP2_TOKEN_SEC_WEBSOCKET_ORIGIN;
- }
- break;
- }
- break;
- case 21:
- switch (name[20]) {
- case 'l':
- if (lstreq("x-dnsprefetch-contro", name, 20)) {
- return NGHTTP2_TOKEN_X_DNSPREFETCH_CONTROL;
- }
- break;
- case 'n':
- if (lstreq("sec-websocket-versio", name, 20)) {
- return NGHTTP2_TOKEN_SEC_WEBSOCKET_VERSION;
- }
- break;
- }
- break;
- case 22:
- switch (name[21]) {
- case 'e':
- if (lstreq("access-control-max-ag", name, 21)) {
- return NGHTTP2_TOKEN_ACCESS_CONTROL_MAX_AGE;
- }
- break;
- case 'l':
- if (lstreq("sec-websocket-protoco", name, 21)) {
- return NGHTTP2_TOKEN_SEC_WEBSOCKET_PROTOCOL;
- }
- break;
- case 's':
- if (lstreq("x-content-type-option", name, 21)) {
- return NGHTTP2_TOKEN_X_CONTENT_TYPE_OPTIONS;
- }
- break;
- }
- break;
- case 23:
- switch (name[22]) {
- case 'y':
- if (lstreq("content-security-polic", name, 22)) {
- return NGHTTP2_TOKEN_CONTENT_SECURITY_POLICY;
- }
- break;
- }
- break;
- case 24:
- switch (name[23]) {
- case 's':
- if (lstreq("sec-websocket-extension", name, 23)) {
- return NGHTTP2_TOKEN_SEC_WEBSOCKET_EXTENSIONS;
- }
- break;
- }
- break;
case 25:
switch (name[24]) {
- case 's':
- if (lstreq("upgrade-insecure-request", name, 24)) {
- return NGHTTP2_TOKEN_UPGRADE_INSECURE_REQUESTS;
- }
- break;
case 'y':
if (lstreq("strict-transport-securit", name, 24)) {
return NGHTTP2_TOKEN_STRICT_TRANSPORT_SECURITY;
}
- if (lstreq("x-content-security-polic", name, 24)) {
- return NGHTTP2_TOKEN_X_CONTENT_SECURITY_POLICY;
- }
break;
}
break;
@@ -733,143 +492,37 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
break;
}
break;
- case 28:
- switch (name[27]) {
- case 's':
- if (lstreq("access-control-allow-header", name, 27)) {
- return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS;
- }
- if (lstreq("access-control-allow-method", name, 27)) {
- return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_METHODS;
- }
- break;
- }
- break;
- case 29:
- switch (name[28]) {
- case 'd':
- if (lstreq("access-control-request-metho", name, 28)) {
- return NGHTTP2_TOKEN_ACCESS_CONTROL_REQUEST_METHOD;
- }
- break;
- case 's':
- if (lstreq("access-control-expose-header", name, 28)) {
- return NGHTTP2_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS;
- }
- break;
- }
- break;
- case 30:
- switch (name[29]) {
- case 's':
- if (lstreq("access-control-request-header", name, 29)) {
- return NGHTTP2_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS;
- }
- break;
- }
- break;
- case 32:
- switch (name[31]) {
- case 's':
- if (lstreq("access-control-allow-credential", name, 31)) {
- return NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS;
- }
- break;
- }
- break;
- case 35:
- switch (name[34]) {
- case 'y':
- if (lstreq("content-security-policy-report-onl", name, 34)) {
- return NGHTTP2_TOKEN_CONTENT_SECURITY_POLICY_REPORT_ONLY;
- }
- break;
- }
- break;
}
return -1;
}
-int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
- size_t namelen, uint8_t *value, size_t valuelen,
- int token, nghttp2_mem *mem) {
- int rv = 0;
-
- /* Since nghttp2_hd_entry is used for indexing, ent->nv.flags always
- NGHTTP2_NV_FLAG_NONE */
- ent->nv.flags = NGHTTP2_NV_FLAG_NONE;
-
- if ((flags & NGHTTP2_HD_FLAG_NAME_ALLOC) &&
- (flags & NGHTTP2_HD_FLAG_NAME_GIFT) == 0) {
- if (namelen == 0) {
- flags = (uint8_t)(flags & ~NGHTTP2_HD_FLAG_NAME_ALLOC);
- ent->nv.name = (uint8_t *)"";
- } else {
- /* name may not be NULL terminated on compression. */
- ent->nv.name = (uint8_t *)nghttp2_mem_malloc(mem, namelen + 1);
- if (ent->nv.name == NULL) {
- rv = NGHTTP2_ERR_NOMEM;
- goto fail;
- }
- memcpy(ent->nv.name, name, namelen);
- ent->nv.name[namelen] = '\0';
- }
- } else {
- ent->nv.name = name;
- }
- if ((flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) &&
- (flags & NGHTTP2_HD_FLAG_VALUE_GIFT) == 0) {
- if (valuelen == 0) {
- flags = (uint8_t)(flags & ~NGHTTP2_HD_FLAG_VALUE_ALLOC);
- ent->nv.value = (uint8_t *)"";
- } else {
- /* value may not be NULL terminated on compression. */
- ent->nv.value = (uint8_t *)nghttp2_mem_malloc(mem, valuelen + 1);
- if (ent->nv.value == NULL) {
- rv = NGHTTP2_ERR_NOMEM;
- goto fail2;
- }
- memcpy(ent->nv.value, value, valuelen);
- ent->nv.value[valuelen] = '\0';
- }
- } else {
- ent->nv.value = value;
- }
- ent->nv.namelen = namelen;
- ent->nv.valuelen = valuelen;
- ent->token = token;
- ent->ref = 1;
- ent->flags = flags;
+void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv) {
+ ent->nv = *nv;
+ ent->cnv.name = nv->name->base;
+ ent->cnv.namelen = nv->name->len;
+ ent->cnv.value = nv->value->base;
+ ent->cnv.valuelen = nv->value->len;
+ ent->cnv.flags = nv->flags;
ent->next = NULL;
ent->hash = 0;
- return 0;
-
-fail2:
- if ((flags & NGHTTP2_HD_FLAG_NAME_ALLOC) &&
- (flags & NGHTTP2_HD_FLAG_NAME_GIFT) == 0) {
- nghttp2_mem_free(mem, ent->nv.name);
- }
-fail:
- return rv;
+ nghttp2_rcbuf_incref(ent->nv.name);
+ nghttp2_rcbuf_incref(ent->nv.value);
}
-void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem) {
- assert(ent->ref == 0);
- if (ent->flags & NGHTTP2_HD_FLAG_NAME_ALLOC) {
- nghttp2_mem_free(mem, ent->nv.name);
- }
- if (ent->flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) {
- nghttp2_mem_free(mem, ent->nv.value);
- }
+void nghttp2_hd_entry_free(nghttp2_hd_entry *ent) {
+ nghttp2_rcbuf_decref(ent->nv.value);
+ nghttp2_rcbuf_decref(ent->nv.name);
}
-static int name_eq(const nghttp2_nv *a, const nghttp2_nv *b) {
- return a->namelen == b->namelen && memeq(a->name, b->name, a->namelen);
+static int name_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
+ return a->name->len == b->namelen &&
+ memeq(a->name->base, b->name, b->namelen);
}
-static int value_eq(const nghttp2_nv *a, const nghttp2_nv *b) {
- return a->valuelen == b->valuelen && memeq(a->value, b->value, a->valuelen);
+static int value_eq(const nghttp2_hd_nv *a, const nghttp2_nv *b) {
+ return a->value->len == b->valuelen &&
+ memeq(a->value->base, b->value, b->valuelen);
}
static uint32_t name_hash(const nghttp2_nv *nv) {
@@ -905,7 +558,7 @@ static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
}
static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
- const nghttp2_nv *nv, int token,
+ const nghttp2_nv *nv, int32_t token,
uint32_t hash) {
nghttp2_hd_entry *p;
nghttp2_hd_entry *res = NULL;
@@ -913,7 +566,7 @@ static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
*exact_match = 0;
for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
- if (token != p->token ||
+ if (token != p->nv.token ||
(token == -1 && (hash != p->hash || !name_eq(&p->nv, nv)))) {
continue;
}
@@ -931,28 +584,19 @@ static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
}
static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
- nghttp2_hd_entry **bucket;
- nghttp2_hd_entry *p;
+ nghttp2_hd_entry **dst;
- bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
+ dst = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
- if (*bucket == NULL) {
- return;
- }
+ for (; *dst; dst = &(*dst)->next) {
+ if (*dst != ent) {
+ continue;
+ }
- if (*bucket == ent) {
- *bucket = ent->next;
+ *dst = ent->next;
ent->next = NULL;
return;
}
-
- for (p = *bucket; p; p = p->next) {
- if (p->next == ent) {
- p->next = ent->next;
- ent->next = NULL;
- return;
- }
- }
}
static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
@@ -1008,8 +652,8 @@ static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
}
for (i = 0; i < ringbuf->len; ++i) {
nghttp2_hd_entry *ent = hd_ringbuf_get(ringbuf, i);
- --ent->ref;
- nghttp2_hd_entry_free(ent, mem);
+
+ nghttp2_hd_entry_free(ent);
nghttp2_mem_free(mem, ent);
}
nghttp2_mem_free(mem, ringbuf->buffer);
@@ -1098,49 +742,37 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
inflater->settings_hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
inflater->min_hd_table_bufsize_max = UINT32_MAX;
- inflater->ent_keep = NULL;
- inflater->nv_keep = NULL;
+ inflater->nv_name_keep = NULL;
+ inflater->nv_value_keep = NULL;
inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
- rv = nghttp2_bufs_init3(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 8, 8, 1, 0,
- mem);
+ nghttp2_buf_init(&inflater->namebuf);
+ nghttp2_buf_init(&inflater->valuebuf);
- if (rv != 0) {
- goto nvbufs_fail;
- }
+ inflater->namercbuf = NULL;
+ inflater->valuercbuf = NULL;
inflater->huffman_encoded = 0;
inflater->index = 0;
inflater->left = 0;
inflater->shift = 0;
- inflater->newnamelen = 0;
inflater->index_required = 0;
inflater->no_index = 0;
return 0;
-nvbufs_fail:
- hd_context_free(&inflater->ctx);
fail:
return rv;
}
static void hd_inflate_keep_free(nghttp2_hd_inflater *inflater) {
- nghttp2_mem *mem;
+ nghttp2_rcbuf_decref(inflater->nv_value_keep);
+ nghttp2_rcbuf_decref(inflater->nv_name_keep);
- mem = inflater->ctx.mem;
- if (inflater->ent_keep) {
- if (inflater->ent_keep->ref == 0) {
- nghttp2_hd_entry_free(inflater->ent_keep, mem);
- nghttp2_mem_free(mem, inflater->ent_keep);
- }
- inflater->ent_keep = NULL;
- }
-
- nghttp2_mem_free(mem, inflater->nv_keep);
- inflater->nv_keep = NULL;
+ inflater->nv_value_keep = NULL;
+ inflater->nv_name_keep = NULL;
}
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
@@ -1149,7 +781,10 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) {
hd_inflate_keep_free(inflater);
- nghttp2_bufs_free(&inflater->nvbufs);
+
+ nghttp2_rcbuf_decref(inflater->valuercbuf);
+ nghttp2_rcbuf_decref(inflater->namercbuf);
+
hd_context_free(&inflater->ctx);
}
@@ -1157,23 +792,13 @@ static size_t entry_room(size_t namelen, size_t valuelen) {
return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
}
-static int emit_indexed_header(nghttp2_nv *nv_out, int *token_out,
- nghttp2_hd_entry *ent) {
- DEBUGF(fprintf(stderr, "inflatehd: header emission: %s: %s\n", ent->nv.name,
- ent->nv.value));
+static int emit_header(nghttp2_hd_nv *nv_out, nghttp2_hd_nv *nv) {
+ DEBUGF(fprintf(stderr, "inflatehd: header emission: %s: %s\n", nv->name->base,
+ nv->value->base));
/* ent->ref may be 0. This happens if the encoder emits literal
block larger than header table capacity with indexing. */
- *nv_out = ent->nv;
- *token_out = ent->token;
- return 0;
-}
-
-static int emit_literal_header(nghttp2_nv *nv_out, int *token_out,
- nghttp2_nv *nv) {
- DEBUGF(fprintf(stderr, "inflatehd: header emission: %s: %s\n", nv->name,
- nv->value));
*nv_out = *nv;
- *token_out = lookup_token(nv->name, nv->namelen);
+
return 0;
}
@@ -1237,11 +862,11 @@ static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
* of bytes processed, or returns -1, indicating decoding error.
*/
static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *final,
- uint32_t initial, size_t shift, uint8_t *in,
- uint8_t *last, size_t prefix) {
+ uint32_t initial, size_t shift, const uint8_t *in,
+ const uint8_t *last, size_t prefix) {
uint32_t k = (uint8_t)((1 << prefix) - 1);
uint32_t n = initial;
- uint8_t *start = in;
+ const uint8_t *start = in;
*shift_ptr = 0;
*final = 0;
@@ -1481,17 +1106,16 @@ static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
return 0;
}
-static nghttp2_hd_entry *
-add_hd_table_incremental(nghttp2_hd_context *context, const nghttp2_nv *nv,
- int token, uint8_t entry_flags, nghttp2_hd_map *map,
- uint32_t hash) {
+static int add_hd_table_incremental(nghttp2_hd_context *context,
+ nghttp2_hd_nv *nv, nghttp2_hd_map *map,
+ uint32_t hash) {
int rv;
nghttp2_hd_entry *new_ent;
size_t room;
nghttp2_mem *mem;
mem = context->mem;
- room = entry_room(nv->namelen, nv->valuelen);
+ room = entry_room(nv->name->len, nv->value->len);
while (context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
context->hd_table.len > 0) {
@@ -1499,72 +1123,53 @@ add_hd_table_incremental(nghttp2_hd_context *context, const nghttp2_nv *nv,
size_t idx = context->hd_table.len - 1;
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
- context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen);
+ context->hd_table_bufsize -=
+ entry_room(ent->nv.name->len, ent->nv.value->len);
DEBUGF(fprintf(stderr, "hpack: remove item from header table: %s: %s\n",
- ent->nv.name, ent->nv.value));
+ (char *)ent->nv.name->base, (char *)ent->nv.value->base));
hd_ringbuf_pop_back(&context->hd_table);
if (map) {
hd_map_remove(map, ent);
}
- if (--ent->ref == 0) {
- nghttp2_hd_entry_free(ent, mem);
- nghttp2_mem_free(mem, ent);
- }
- }
- 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, token, mem);
- if (rv != 0) {
- nghttp2_mem_free(mem, new_ent);
- return NULL;
+ nghttp2_hd_entry_free(ent);
+ nghttp2_mem_free(mem, ent);
}
if (room > context->hd_table_bufsize_max) {
/* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
- immediately evicted. */
- --new_ent->ref;
- } else {
- rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
+ immediately evicted. So we don't allocate memory for it. */
+ return 0;
+ }
- if (rv != 0) {
- --new_ent->ref;
+ new_ent = (nghttp2_hd_entry *)nghttp2_mem_malloc(mem, sizeof(nghttp2_hd_entry));
+ if (new_ent == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
- 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_init(new_ent, nv);
- nghttp2_hd_entry_free(new_ent, mem);
- nghttp2_mem_free(mem, new_ent);
+ rv = hd_ringbuf_push_front(&context->hd_table, new_ent, mem);
- return NULL;
- }
+ if (rv != 0) {
+ nghttp2_hd_entry_free(new_ent);
+ nghttp2_mem_free(mem, new_ent);
- new_ent->seq = context->next_seq++;
- new_ent->hash = hash;
+ return rv;
+ }
- if (map) {
- hd_map_insert(map, new_ent);
- }
+ new_ent->seq = context->next_seq++;
+ new_ent->hash = hash;
- context->hd_table_bufsize += room;
+ if (map) {
+ hd_map_insert(map, new_ent);
}
- return new_ent;
+
+ context->hd_table_bufsize += room;
+
+ return 0;
}
typedef struct {
@@ -1573,10 +1178,11 @@ typedef struct {
uint8_t name_value_match;
} search_result;
-static search_result search_static_table(const nghttp2_nv *nv, int token,
+static search_result search_static_table(const nghttp2_nv *nv, int32_t token,
int indexing_mode) {
search_result res = {token, 0};
int i;
+ nghttp2_hd_static_entry *ent;
if (indexing_mode == NGHTTP2_HD_NEVER_INDEXING) {
return res;
@@ -1585,7 +1191,9 @@ static search_result search_static_table(const nghttp2_nv *nv, int token,
for (i = token;
i <= NGHTTP2_TOKEN_WWW_AUTHENTICATE && static_table[i].token == token;
++i) {
- if (value_eq(&static_table[i].nv, nv)) {
+ ent = &static_table[i];
+ if (ent->value.len == nv->valuelen &&
+ memcmp(ent->value.base, nv->value, nv->valuelen) == 0) {
res.index = i;
res.name_value_match = 1;
return res;
@@ -1595,7 +1203,7 @@ static search_result search_static_table(const nghttp2_nv *nv, int token,
}
static search_result search_hd_table(nghttp2_hd_context *context,
- const nghttp2_nv *nv, int token,
+ const nghttp2_nv *nv, int32_t token,
int indexing_mode, nghttp2_hd_map *map,
uint32_t hash) {
search_result res = {-1, 0};
@@ -1639,15 +1247,15 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context,
context->hd_table.len > 0) {
size_t idx = context->hd_table.len - 1;
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
- context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen);
+ context->hd_table_bufsize -=
+ entry_room(ent->nv.name->len, ent->nv.value->len);
hd_ringbuf_pop_back(&context->hd_table);
if (map) {
hd_map_remove(map, ent);
}
- if (--ent->ref == 0) {
- nghttp2_hd_entry_free(ent, mem);
- nghttp2_mem_free(mem, ent);
- }
+
+ nghttp2_hd_entry_free(ent);
+ nghttp2_mem_free(mem, ent);
}
}
@@ -1706,19 +1314,32 @@ static size_t get_max_index(nghttp2_hd_context *context) {
return context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH - 1;
}
-nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context,
- size_t idx) {
+nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t idx) {
assert(INDEX_RANGE_VALID(context, idx));
if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
- return hd_ringbuf_get(&context->hd_table,
- idx - NGHTTP2_STATIC_TABLE_LENGTH);
+ return hd_ringbuf_get(&context->hd_table, idx - NGHTTP2_STATIC_TABLE_LENGTH)
+ ->nv;
} else {
- return &static_table[idx];
+ nghttp2_hd_static_entry *ent = &static_table[idx];
+ nghttp2_hd_nv nv = {&ent->name, &ent->value, ent->token,
+ NGHTTP2_NV_FLAG_NONE};
+ return nv;
+ }
+}
+
+static const nghttp2_nv *nghttp2_hd_table_get2(nghttp2_hd_context *context,
+ size_t idx) {
+ assert(INDEX_RANGE_VALID(context, idx));
+ if (idx >= NGHTTP2_STATIC_TABLE_LENGTH) {
+ return &hd_ringbuf_get(&context->hd_table,
+ idx - NGHTTP2_STATIC_TABLE_LENGTH)->cnv;
}
+
+ return &static_table[idx].cnv;
}
static int hd_deflate_decide_indexing(nghttp2_hd_deflater *deflater,
- const nghttp2_nv *nv, int token) {
+ const nghttp2_nv *nv, int32_t token) {
if (token == NGHTTP2_TOKEN__PATH || token == NGHTTP2_TOKEN_AGE ||
token == NGHTTP2_TOKEN_CONTENT_LENGTH || token == NGHTTP2_TOKEN_ETAG ||
token == NGHTTP2_TOKEN_IF_MODIFIED_SINCE ||
@@ -1738,7 +1359,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
search_result res;
ssize_t idx;
int indexing_mode;
- int token;
+ int32_t token;
nghttp2_mem *mem;
uint32_t hash = 0;
@@ -1787,27 +1408,35 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
}
if (indexing_mode == NGHTTP2_HD_WITH_INDEXING) {
- nghttp2_hd_entry *new_ent;
+ nghttp2_hd_nv hd_nv;
+
if (idx != -1 && idx < (ssize_t)NGHTTP2_STATIC_TABLE_LENGTH) {
- nghttp2_nv nv_indname;
- nv_indname = *nv;
- nv_indname.name =
- nghttp2_hd_table_get(&deflater->ctx, (size_t)idx)->nv.name;
- new_ent = add_hd_table_incremental(&deflater->ctx, &nv_indname, token,
- NGHTTP2_HD_FLAG_VALUE_ALLOC,
- &deflater->map, hash);
+ hd_nv.name = nghttp2_hd_table_get(&deflater->ctx, (size_t)idx).name;
+ nghttp2_rcbuf_incref(hd_nv.name);
} else {
- new_ent = add_hd_table_incremental(&deflater->ctx, nv, token,
- NGHTTP2_HD_FLAG_NAME_ALLOC |
- NGHTTP2_HD_FLAG_VALUE_ALLOC,
- &deflater->map, hash);
+ rv = nghttp2_rcbuf_new2(&hd_nv.name, nv->name, nv->namelen, mem);
+ if (rv != 0) {
+ return rv;
+ }
}
- if (!new_ent) {
- return NGHTTP2_ERR_HEADER_COMP;
+
+ rv = nghttp2_rcbuf_new2(&hd_nv.value, nv->value, nv->valuelen, mem);
+
+ if (rv != 0) {
+ nghttp2_rcbuf_decref(hd_nv.name);
+ return rv;
}
- if (new_ent->ref == 0) {
- nghttp2_hd_entry_free(new_ent, mem);
- nghttp2_mem_free(mem, new_ent);
+
+ hd_nv.token = token;
+ hd_nv.flags = NGHTTP2_NV_FLAG_NONE;
+
+ rv = add_hd_table_incremental(&deflater->ctx, &hd_nv, &deflater->map, hash);
+
+ nghttp2_rcbuf_decref(hd_nv.value);
+ nghttp2_rcbuf_decref(hd_nv.name);
+
+ if (rv != 0) {
+ return NGHTTP2_ERR_HEADER_COMP;
}
}
if (idx == -1) {
@@ -1996,8 +1625,8 @@ static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
* Integer decoding failed
*/
static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
- uint8_t *in, uint8_t *last, size_t prefix,
- size_t maxlen) {
+ const uint8_t *in, const uint8_t *last,
+ size_t prefix, size_t maxlen) {
ssize_t rv;
uint32_t out;
@@ -2036,19 +1665,17 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
* Out of memory
* NGHTTP2_ERR_HEADER_COMP
* Huffman decoding failed
- * NGHTTP2_ERR_BUFFER_ERROR
- * Out of buffer space.
*/
static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
- nghttp2_bufs *bufs, uint8_t *in,
- uint8_t *last) {
+ nghttp2_buf *buf, const uint8_t *in,
+ const uint8_t *last) {
ssize_t readlen;
int final = 0;
if ((size_t)(last - in) >= inflater->left) {
last = in + inflater->left;
final = 1;
}
- readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, bufs, in,
+ readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buf, in,
(size_t)(last - in), final);
if (readlen < 0) {
@@ -2070,17 +1697,13 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
* Out of memory
* NGHTTP2_ERR_HEADER_COMP
* Header decompression failed
- * NGHTTP2_ERR_BUFFER_ERROR
- * Out of buffer space.
*/
-static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater,
- nghttp2_bufs *bufs, uint8_t *in, uint8_t *last) {
- int rv;
+static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
+ const uint8_t *in, const uint8_t *last) {
size_t len = nghttp2_min((size_t)(last - in), inflater->left);
- rv = nghttp2_bufs_add(bufs, in, len);
- if (rv != 0) {
- return rv;
- }
+
+ buf->last = nghttp2_cpymem(buf->last, in, len);
+
inflater->left -= len;
return (ssize_t)len;
}
@@ -2097,116 +1720,10 @@ static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater,
* Out of memory
*/
static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
- nghttp2_nv *nv_out, int *token_out) {
- nghttp2_hd_entry *ent = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
-
- emit_indexed_header(nv_out, token_out, ent);
-
- return 0;
-}
-
-static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, nghttp2_nv *nv,
- int value_only) {
- ssize_t rv;
- size_t buflen;
- uint8_t *buf;
- nghttp2_buf *pbuf;
-
- if (inflater->index_required ||
- inflater->nvbufs.head != inflater->nvbufs.cur) {
-
- rv = nghttp2_bufs_remove(&inflater->nvbufs, &buf);
-
- if (rv < 0) {
- return NGHTTP2_ERR_NOMEM;
- }
-
- nghttp2_bufs_reset(&inflater->nvbufs);
-
- buflen = (size_t)rv;
-
- if (value_only) {
- /* we don't use this value, so no need to NULL-terminate */
- nv->name = NULL;
- nv->namelen = 0;
-
- nv->value = buf;
- nv->valuelen = buflen - 1;
- } else {
- nv->name = buf;
- nv->namelen = inflater->newnamelen;
-
- nv->value = buf + nv->namelen + 1;
- nv->valuelen = buflen - nv->namelen - 2;
- }
-
- return 0;
- }
-
- /* If we are not going to store header in header table and
- name/value are in first chunk, we just refer them from nv,
- instead of mallocing another memory. */
-
- pbuf = &inflater->nvbufs.head->buf;
-
- if (value_only) {
- /* we don't use this value, so no need to NULL-terminate */
- nv->name = NULL;
- nv->namelen = 0;
-
- nv->value = pbuf->pos;
- nv->valuelen = nghttp2_buf_len(pbuf) - 1;
- } else {
- nv->name = pbuf->pos;
- nv->namelen = inflater->newnamelen;
-
- nv->value = pbuf->pos + nv->namelen + 1;
- nv->valuelen = nghttp2_buf_len(pbuf) - nv->namelen - 2;
- }
-
- /* Resetting does not change the content of first buffer */
- nghttp2_bufs_reset(&inflater->nvbufs);
-
- return 0;
-}
-
-static int hd_inflate_remove_bufs_with_name(nghttp2_hd_inflater *inflater,
- nghttp2_nv *nv,
- nghttp2_hd_entry *ent_name) {
-#ifndef NDEBUG
- size_t rv;
-#endif
- size_t buflen;
- uint8_t *buf;
- nghttp2_mem *mem;
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
- mem = inflater->ctx.mem;
-
- /* Allocate buffer including name in ent_name, plus terminating
- NULL. */
- buflen = ent_name->nv.namelen + 1 + nghttp2_bufs_len(&inflater->nvbufs);
-
- buf = (uint8_t *)nghttp2_mem_malloc(mem, buflen);
- if (buf == NULL) {
- return NGHTTP2_ERR_NOMEM;
- }
-
- /* Copy including terminal NULL */
- memcpy(buf, ent_name->nv.name, ent_name->nv.namelen + 1);
-#ifndef NDEBUG
- rv =
-#endif
- nghttp2_bufs_remove_copy(&inflater->nvbufs,
- buf + ent_name->nv.namelen + 1);
- assert(ent_name->nv.namelen + 1 + rv == buflen);
-
- nghttp2_bufs_reset(&inflater->nvbufs);
-
- nv->name = buf;
- nv->namelen = ent_name->nv.namelen;
-
- nv->value = buf + nv->namelen + 1;
- nv->valuelen = buflen - nv->namelen - 2;
+ emit_header(nv_out, &nv);
return 0;
}
@@ -2223,17 +1740,9 @@ static int hd_inflate_remove_bufs_with_name(nghttp2_hd_inflater *inflater,
* Out of memory
*/
static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
- nghttp2_nv *nv_out, int *token_out) {
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv;
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) {
- return NGHTTP2_ERR_NOMEM;
- }
if (inflater->no_index) {
nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
@@ -2241,36 +1750,25 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
nv.flags = NGHTTP2_NV_FLAG_NONE;
}
- if (inflater->index_required) {
- nghttp2_hd_entry *new_ent;
- uint8_t ent_flags;
-
- /* nv->value points to the middle of the buffer pointed by
- nv->name. So we just need to keep track of nv->name for memory
- management. */
- ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
-
- new_ent = add_hd_table_incremental(&inflater->ctx, &nv,
- lookup_token(nv.name, nv.namelen),
- ent_flags, NULL, 0);
+ nv.name = inflater->namercbuf;
+ nv.value = inflater->valuercbuf;
+ nv.token = lookup_token(inflater->namercbuf->base, inflater->namercbuf->len);
- if (new_ent) {
- emit_indexed_header(nv_out, token_out, new_ent);
- inflater->ent_keep = new_ent;
+ if (inflater->index_required) {
+ rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
- return 0;
+ if (rv != 0) {
+ return rv;
}
-
- nghttp2_mem_free(mem, nv.name);
-
- return NGHTTP2_ERR_NOMEM;
}
- emit_literal_header(nv_out, token_out, &nv);
+ emit_header(nv_out, &nv);
- if (nv.name != inflater->nvbufs.head->buf.pos) {
- inflater->nv_keep = nv.name;
- }
+ inflater->nv_name_keep = nv.name;
+ inflater->nv_value_keep = nv.value;
+
+ inflater->namercbuf = NULL;
+ inflater->valuercbuf = NULL;
return 0;
}
@@ -2287,13 +1785,11 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
* Out of memory
*/
static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
- nghttp2_nv *nv_out, int *token_out) {
+ nghttp2_hd_nv *nv_out) {
+ nghttp2_hd_nv nv;
int rv;
- nghttp2_nv nv;
- nghttp2_hd_entry *ent_name;
- nghttp2_mem *mem;
- mem = inflater->ctx.mem;
+ nv = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
if (inflater->no_index) {
nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
@@ -2301,88 +1797,73 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
nv.flags = NGHTTP2_NV_FLAG_NONE;
}
- ent_name = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
-
- if (inflater->index_required) {
- nghttp2_hd_entry *new_ent;
- uint8_t ent_flags;
+ nghttp2_rcbuf_incref(nv.name);
- if (inflater->index < NGHTTP2_STATIC_TABLE_LENGTH) {
- /* We don't copy name in static table */
- rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
- if (rv != 0) {
- return NGHTTP2_ERR_NOMEM;
- }
- nv.name = ent_name->nv.name;
- nv.namelen = ent_name->nv.namelen;
+ nv.value = inflater->valuercbuf;
- ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
- } else {
- rv = hd_inflate_remove_bufs_with_name(inflater, &nv, ent_name);
- if (rv != 0) {
- return NGHTTP2_ERR_NOMEM;
- }
- /* nv->name and nv->value are in the same buffer. */
- ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
+ if (inflater->index_required) {
+ rv = add_hd_table_incremental(&inflater->ctx, &nv, NULL, 0);
+ if (rv != 0) {
+ nghttp2_rcbuf_decref(nv.name);
+ return NGHTTP2_ERR_NOMEM;
}
+ }
- new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->token,
- ent_flags, NULL, 0);
+ emit_header(nv_out, &nv);
- /* At this point, ent_name might be deleted. */
+ inflater->nv_name_keep = nv.name;
+ inflater->nv_value_keep = nv.value;
- if (new_ent) {
- emit_indexed_header(nv_out, token_out, new_ent);
+ inflater->valuercbuf = NULL;
- inflater->ent_keep = new_ent;
+ return 0;
+}
- return 0;
- }
+ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
+ int *inflate_flags, uint8_t *in, size_t inlen,
+ int in_final) {
+ return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
+ in_final);
+}
- if (inflater->index < NGHTTP2_STATIC_TABLE_LENGTH) {
- nghttp2_mem_free(mem, nv.value);
- } else {
- nghttp2_mem_free(mem, nv.name);
- }
+ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
+ nghttp2_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen, int in_final) {
+ ssize_t rv;
+ nghttp2_hd_nv hd_nv;
- return NGHTTP2_ERR_NOMEM;
- }
+ rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
+ in_final);
- rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
- if (rv != 0) {
- return NGHTTP2_ERR_NOMEM;
+ if (rv < 0) {
+ return rv;
}
- nv.name = ent_name->nv.name;
- nv.namelen = ent_name->nv.namelen;
+ if (*inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
+ nv_out->name = hd_nv.name->base;
+ nv_out->namelen = hd_nv.name->len;
- emit_literal_header(nv_out, token_out, &nv);
+ nv_out->value = hd_nv.value->base;
+ nv_out->valuelen = hd_nv.value->len;
- if (nv.value != inflater->nvbufs.head->buf.pos) {
- inflater->nv_keep = nv.value;
+ nv_out->flags = hd_nv.flags;
}
- return 0;
-}
-
-ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
- int *inflate_flags, uint8_t *in, size_t inlen,
- int in_final) {
- int token;
-
- return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, &token, in,
- inlen, in_final);
+ return rv;
}
-ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
- nghttp2_nv *nv_out, int *inflate_flags,
- int *token_out, uint8_t *in, size_t inlen,
- int in_final) {
+ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen,
+ int in_final) {
ssize_t rv = 0;
- uint8_t *first = in;
- uint8_t *last = in + inlen;
+ const uint8_t *first = in;
+ const uint8_t *last = in + inlen;
int rfin = 0;
int busy = 0;
+ nghttp2_mem *mem;
+
+ mem = inflater->ctx.mem;
if (inflater->ctx.bad) {
return NGHTTP2_ERR_HEADER_COMP;
@@ -2390,7 +1871,6 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
DEBUGF(fprintf(stderr, "inflatehd: start state=%d\n", inflater->state));
hd_inflate_keep_free(inflater);
- *token_out = -1;
*inflate_flags = NGHTTP2_HD_INFLATE_NONE;
for (; in != last || busy;) {
busy = 0;
@@ -2496,7 +1976,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
inflater->index = inflater->left;
--inflater->index;
- rv = hd_inflate_commit_indexed(inflater, nv_out, token_out);
+ rv = hd_inflate_commit_indexed(inflater, nv_out);
if (rv < 0) {
goto fail;
}
@@ -2541,12 +2021,24 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
+
+ rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left * 2 + 1,
+ mem);
} else {
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
+ rv = nghttp2_rcbuf_new(&inflater->namercbuf, inflater->left + 1, mem);
}
+
+ if (rv != 0) {
+ goto fail;
+ }
+
+ nghttp2_buf_wrap_init(&inflater->namebuf, inflater->namercbuf->base,
+ inflater->namercbuf->len);
+
break;
case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
- rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last);
+ rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last);
if (rv < 0) {
goto fail;
}
@@ -2562,18 +2054,14 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
goto almost_ok;
}
- inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs);
-
- rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
- if (rv != 0) {
- goto fail;
- }
+ *inflater->namebuf.last = '\0';
+ inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
break;
case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
- rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last);
+ rv = hd_inflate_read(inflater, &inflater->namebuf, in, last);
if (rv < 0) {
goto fail;
}
@@ -2588,12 +2076,8 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
goto almost_ok;
}
- inflater->newnamelen = nghttp2_bufs_len(&inflater->nvbufs);
-
- rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
- if (rv != 0) {
- goto fail;
- }
+ *inflater->namebuf.last = '\0';
+ inflater->namercbuf->len = nghttp2_buf_len(&inflater->namebuf);
inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
@@ -2625,15 +2109,27 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
+
+ rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left * 2 + 1,
+ mem);
} else {
inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
+
+ rv = nghttp2_rcbuf_new(&inflater->valuercbuf, inflater->left + 1, mem);
+ }
+
+ if (rv != 0) {
+ goto fail;
}
+ nghttp2_buf_wrap_init(&inflater->valuebuf, inflater->valuercbuf->base,
+ inflater->valuercbuf->len);
+
busy = 1;
break;
case NGHTTP2_HD_STATE_READ_VALUEHUFF:
- rv = hd_inflate_read_huff(inflater, &inflater->nvbufs, in, last);
+ rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last);
if (rv < 0) {
goto fail;
}
@@ -2649,15 +2145,13 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
goto almost_ok;
}
- rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
- if (rv != 0) {
- goto fail;
- }
+ *inflater->valuebuf.last = '\0';
+ inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
- rv = hd_inflate_commit_newname(inflater, nv_out, token_out);
+ rv = hd_inflate_commit_newname(inflater, nv_out);
} else {
- rv = hd_inflate_commit_indname(inflater, nv_out, token_out);
+ rv = hd_inflate_commit_indname(inflater, nv_out);
}
if (rv != 0) {
@@ -2669,7 +2163,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
return (ssize_t)(in - first);
case NGHTTP2_HD_STATE_READ_VALUE:
- rv = hd_inflate_read(inflater, &inflater->nvbufs, in, last);
+ rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last);
if (rv < 0) {
DEBUGF(fprintf(stderr, "inflatehd: value read failure %zd: %s\n", rv,
nghttp2_strerror((int)rv)));
@@ -2686,15 +2180,13 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
goto almost_ok;
}
- rv = nghttp2_bufs_addb(&inflater->nvbufs, '\0');
- if (rv != 0) {
- goto fail;
- }
+ *inflater->valuebuf.last = '\0';
+ inflater->valuercbuf->len = nghttp2_buf_len(&inflater->valuebuf);
if (inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
- rv = hd_inflate_commit_newname(inflater, nv_out, token_out);
+ rv = hd_inflate_commit_newname(inflater, nv_out);
} else {
- rv = hd_inflate_commit_indname(inflater, nv_out, token_out);
+ rv = hd_inflate_commit_indname(inflater, nv_out);
}
if (rv != 0) {
@@ -2828,7 +2320,7 @@ static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
return NULL;
}
- return &nghttp2_hd_table_get(context, idx)->nv;
+ return nghttp2_hd_table_get2(context, idx);
}
size_t nghttp2_hd_deflate_get_num_table_entries(nghttp2_hd_deflater *deflater) {
diff --git a/epan/nghttp2/nghttp2_hd.h b/epan/nghttp2/nghttp2_hd.h
index b942d93c23..6fb0083dc8 100644
--- a/epan/nghttp2/nghttp2_hd.h
+++ b/epan/nghttp2/nghttp2_hd.h
@@ -34,6 +34,7 @@
#include "nghttp2_hd_huffman.h"
#include "nghttp2_buf.h"
#include "nghttp2_mem.h"
+#include "nghttp2_rcbuf.h"
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
@@ -105,88 +106,36 @@ typedef enum {
NGHTTP2_TOKEN_VARY = 58,
NGHTTP2_TOKEN_VIA = 59,
NGHTTP2_TOKEN_WWW_AUTHENTICATE = 60,
- NGHTTP2_TOKEN_ACCEPT_CH,
- NGHTTP2_TOKEN_ACCEPT_DATETIME,
- NGHTTP2_TOKEN_ACCEPT_FEATURES,
- NGHTTP2_TOKEN_ACCEPT_PATCH,
- NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_CREDENTIALS,
- NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_HEADERS,
- NGHTTP2_TOKEN_ACCESS_CONTROL_ALLOW_METHODS,
- NGHTTP2_TOKEN_ACCESS_CONTROL_EXPOSE_HEADERS,
- NGHTTP2_TOKEN_ACCESS_CONTROL_MAX_AGE,
- NGHTTP2_TOKEN_ACCESS_CONTROL_REQUEST_HEADERS,
- NGHTTP2_TOKEN_ACCESS_CONTROL_REQUEST_METHOD,
- NGHTTP2_TOKEN_ALT_SVC,
- NGHTTP2_TOKEN_ALTERNATES,
+ NGHTTP2_TOKEN_TE,
NGHTTP2_TOKEN_CONNECTION,
- NGHTTP2_TOKEN_CONTENT_MD5,
- NGHTTP2_TOKEN_CONTENT_SECURITY_POLICY,
- NGHTTP2_TOKEN_CONTENT_SECURITY_POLICY_REPORT_ONLY,
- NGHTTP2_TOKEN_DNT,
- NGHTTP2_TOKEN_FORWARDED,
- NGHTTP2_TOKEN_FRONT_END_HTTPS,
NGHTTP2_TOKEN_KEEP_ALIVE,
- NGHTTP2_TOKEN_LAST_EVENT_ID,
- NGHTTP2_TOKEN_NEGOTIATE,
- NGHTTP2_TOKEN_ORIGIN,
- NGHTTP2_TOKEN_P3P,
- NGHTTP2_TOKEN_PRAGMA,
NGHTTP2_TOKEN_PROXY_CONNECTION,
- NGHTTP2_TOKEN_PUBLIC_KEY_PINS,
- NGHTTP2_TOKEN_SEC_WEBSOCKET_EXTENSIONS,
- NGHTTP2_TOKEN_SEC_WEBSOCKET_KEY,
- NGHTTP2_TOKEN_SEC_WEBSOCKET_ORIGIN,
- NGHTTP2_TOKEN_SEC_WEBSOCKET_PROTOCOL,
- NGHTTP2_TOKEN_SEC_WEBSOCKET_VERSION,
- NGHTTP2_TOKEN_SET_COOKIE2,
- NGHTTP2_TOKEN_STATUS,
- NGHTTP2_TOKEN_TCN,
- NGHTTP2_TOKEN_TE,
- NGHTTP2_TOKEN_TRAILER,
- NGHTTP2_TOKEN_TSV,
NGHTTP2_TOKEN_UPGRADE,
- NGHTTP2_TOKEN_UPGRADE_INSECURE_REQUESTS,
- NGHTTP2_TOKEN_VARIANT_VARY,
- NGHTTP2_TOKEN_WARNING,
- NGHTTP2_TOKEN_X_API_VERSION,
- NGHTTP2_TOKEN_X_ATT_DEVICEID,
- NGHTTP2_TOKEN_X_CACHE,
- NGHTTP2_TOKEN_X_CACHE_LOOKUP,
- NGHTTP2_TOKEN_X_CONTENT_DURATION,
- NGHTTP2_TOKEN_X_CONTENT_SECURITY_POLICY,
- NGHTTP2_TOKEN_X_CONTENT_TYPE_OPTIONS,
- NGHTTP2_TOKEN_X_DNSPREFETCH_CONTROL,
- NGHTTP2_TOKEN_X_FORWARDED_FOR,
- NGHTTP2_TOKEN_X_FORWARDED_HOST,
- NGHTTP2_TOKEN_X_FORWARDED_PROTO,
- NGHTTP2_TOKEN_X_FRAME_OPTIONS,
- NGHTTP2_TOKEN_X_POWERED_BY,
- NGHTTP2_TOKEN_X_REQUESTED_WITH,
- NGHTTP2_TOKEN_X_UA_COMPATIBLE,
- NGHTTP2_TOKEN_X_WAP_PROFILE,
- NGHTTP2_TOKEN_X_WEBKIT_CSP,
- NGHTTP2_TOKEN_X_XSS_PROTECTION,
} nghttp2_token;
-typedef enum {
- NGHTTP2_HD_FLAG_NONE = 0,
- /* Indicates name was dynamically allocated and must be freed */
- NGHTTP2_HD_FLAG_NAME_ALLOC = 1,
- /* Indicates value was dynamically allocated and must be freed */
- NGHTTP2_HD_FLAG_VALUE_ALLOC = 1 << 1,
- /* Indicates that the name was gifted to the entry and no copying
- necessary. */
- NGHTTP2_HD_FLAG_NAME_GIFT = 1 << 2,
- /* Indicates that the value was gifted to the entry and no copying
- necessary. */
- NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 3
-} nghttp2_hd_flags;
-
struct nghttp2_hd_entry;
typedef struct nghttp2_hd_entry nghttp2_hd_entry;
+typedef struct {
+ /* The buffer containing header field name. NULL-termination is
+ guaranteed. */
+ nghttp2_rcbuf *name;
+ /* The buffer containing header field value. NULL-termination is
+ guaranteed. */
+ nghttp2_rcbuf *value;
+ /* nghttp2_token value for name. It could be -1 if we have no token
+ for that header field name. */
+ int32_t token;
+ /* Bitwise OR of one or more of nghttp2_nv_flag. */
+ uint8_t flags;
+} nghttp2_hd_nv;
+
struct nghttp2_hd_entry {
- nghttp2_nv nv;
+ /* The header field name/value pair */
+ nghttp2_hd_nv nv;
+ /* This is solely for nghttp2_hd_{deflate,inflate}_get_table_entry
+ APIs to keep backward compatibility. */
+ nghttp2_nv cnv;
/* The next entry which shares same bucket in hash table. */
nghttp2_hd_entry *next;
/* The sequence number. We will increment it by one whenever we
@@ -194,14 +143,17 @@ struct nghttp2_hd_entry {
uint32_t seq;
/* The hash value for header name (nv.name). */
uint32_t hash;
- /* nghttp2_token value for nv.name. It could be -1 if we have no
- token for that header field name. */
- int token;
- /* Reference count */
- uint8_t ref;
- uint8_t flags;
};
+/* The entry used for static header table. */
+typedef struct {
+ nghttp2_rcbuf name;
+ nghttp2_rcbuf value;
+ nghttp2_nv cnv;
+ int32_t token;
+ uint32_t hash;
+} nghttp2_hd_static_entry;
+
typedef struct {
nghttp2_hd_entry **buffer;
size_t mask;
@@ -275,24 +227,18 @@ struct nghttp2_hd_deflater {
struct nghttp2_hd_inflater {
nghttp2_hd_context ctx;
- /* header buffer */
- nghttp2_bufs nvbufs;
/* Stores current state of huffman decoding */
nghttp2_hd_huff_decode_context huff_decode_ctx;
- /* Pointer to the nghttp2_hd_entry which is used current header
- emission. This is required because in some cases the
- ent_keep->ref == 0 and we have to keep track of it. */
- nghttp2_hd_entry *ent_keep;
- /* Pointer to the name/value pair buffer which is used in the
- current header emission. */
- uint8_t *nv_keep;
+ /* header buffer */
+ nghttp2_buf namebuf, valuebuf;
+ nghttp2_rcbuf *namercbuf, *valuercbuf;
+ /* Pointer to the name/value pair which are used in the current
+ header emission. */
+ nghttp2_rcbuf *nv_name_keep, *nv_value_keep;
/* The number of bytes to read */
size_t left;
/* The index in indexed repr or indexed name */
size_t index;
- /* The length of new name encoded in literal. For huffman encoded
- string, this is the length after it is decoded. */
- size_t newnamelen;
/* The maximum header table size the inflater supports. This is the
same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
size_t settings_hd_table_bufsize_max;
@@ -312,24 +258,16 @@ struct nghttp2_hd_inflater {
};
/*
- * Initializes the |ent| members. If NGHTTP2_HD_FLAG_NAME_ALLOC bit
- * set in the |flags|, the content pointed by the |name| with length
- * |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit
- * set in the |flags|, the content pointed by the |value| with length
- * |valuelen| is copied. The |token| is enum number looked up by
- * |name|. It could be -1 if we don't have that enum value.
- *
- * This function returns 0 if it succeeds, or one of the following
- * negative error codes:
- *
- * NGHTTP2_ERR_NOMEM
- * Out of memory.
+ * Initializes the |ent| members. The reference counts of nv->name
+ * and nv->value are increased by one for each.
*/
-int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
- size_t namelen, uint8_t *value, size_t valuelen,
- int token, nghttp2_mem *mem);
+void nghttp2_hd_entry_init(nghttp2_hd_entry *ent, nghttp2_hd_nv *nv);
-void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem);
+/*
+ * This function decreases the reference counts of nv->name and
+ * nv->value.
+ */
+void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
/*
* Initializes |deflater| for deflating name/values pairs.
@@ -410,16 +348,14 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
/*
- * Similar to nghttp2_hd_inflate_hd(), but this takes additional
- * output parameter |token|. On successful header emission, it
- * contains nghttp2_token value for nv_out->name. It could be -1 if
- * we don't have enum value for the name. Other than that return
- * values and semantics are the same as nghttp2_hd_inflate_hd().
+ * Similar to nghttp2_hd_inflate_hd(), but this takes nghttp2_hd_nv
+ * instead of nghttp2_nv as output parameter |nv_out|. Other than
+ * that return values and semantics are the same as
+ * nghttp2_hd_inflate_hd().
*/
-ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
- nghttp2_nv *nv_out, int *inflate_flags,
- int *token, uint8_t *in, size_t inlen,
- int in_final);
+ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
+ nghttp2_hd_nv *nv_out, int *inflate_flags,
+ const uint8_t *in, size_t inlen, int in_final);
/* For unittesting purpose */
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
@@ -433,8 +369,7 @@ int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
/* For unittesting purpose */
-nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context,
- size_t index);
+nghttp2_hd_nv nghttp2_hd_table_get(nghttp2_hd_context *context, size_t index);
/* For unittesting purpose */
ssize_t nghttp2_hd_decode_length(uint32_t *res, size_t *shift_ptr, int *final,
@@ -470,11 +405,10 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
/*
- * Decodes the given data |src| with length |srclen|. The |ctx| must
+ * Decodes the given data |src| with length |srclen|. The |ctx| must
* be initialized by nghttp2_hd_huff_decode_context_init(). The result
- * will be added to |dest|. This function may expand |dest| as
- * needed. The caller is responsible to release the memory of |dest|
- * by calling nghttp2_bufs_free().
+ * will be written to |buf|. This function assumes that |buf| has the
+ * enough room to store the decoded byte string.
*
* The caller must set the |final| to nonzero if the given input is
* the final block.
@@ -486,13 +420,11 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
- * NGHTTP2_ERR_BUFFER_ERROR
- * Maximum buffer capacity size exceeded.
* NGHTTP2_ERR_HEADER_COMP
* Decoding process has failed.
*/
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
- nghttp2_bufs *bufs, const uint8_t *src,
+ nghttp2_buf *buf, const uint8_t *src,
size_t srclen, int final);
#endif /* NGHTTP2_HD_H */
diff --git a/epan/nghttp2/nghttp2_hd_huffman.c b/epan/nghttp2/nghttp2_hd_huffman.c
index 48638b7527..3fb0d8863d 100644
--- a/epan/nghttp2/nghttp2_hd_huffman.c
+++ b/epan/nghttp2/nghttp2_hd_huffman.c
@@ -166,31 +166,10 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx) {
ctx->accept = 1;
}
-/* Use macro to make the code simpler..., but error case is tricky.
- We spent most of the CPU in decoding, so we are doing this
- thing. */
-#define hd_huff_decode_sym_emit(bufs, sym, avail) \
- do { \
- if ((avail)) { \
- nghttp2_bufs_fast_addb((bufs), (sym)); \
- --(avail); \
- } else { \
- rv = nghttp2_bufs_addb((bufs), (sym)); \
- if (rv != 0) { \
- return rv; \
- } \
- (avail) = nghttp2_bufs_cur_avail((bufs)); \
- } \
- } while (0)
-
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
- nghttp2_bufs *bufs, const uint8_t *src,
+ nghttp2_buf *buf, const uint8_t *src,
size_t srclen, int final) {
size_t i;
- int rv;
- size_t avail;
-
- avail = nghttp2_bufs_cur_avail(bufs);
/* We use the decoding algorithm described in
http://graphics.ics.uci.edu/pub/Prefix.pdf */
@@ -202,8 +181,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
- /* this is macro, and may return from this function on error */
- hd_huff_decode_sym_emit(bufs, t->sym, avail);
+ *buf->last++ = t->sym;
}
t = &huff_decode_table[t->state][src[i] & 0xf];
@@ -211,8 +189,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
return NGHTTP2_ERR_HEADER_COMP;
}
if (t->flags & NGHTTP2_HUFF_SYM) {
- /* this is macro, and may return from this function on error */
- hd_huff_decode_sym_emit(bufs, t->sym, avail);
+ *buf->last++ = t->sym;
}
ctx->state = t->state;
diff --git a/epan/nghttp2/nghttp2_helper.c b/epan/nghttp2/nghttp2_helper.c
index 4f839e49fe..ada3b0ff5e 100644
--- a/epan/nghttp2/nghttp2_helper.c
+++ b/epan/nghttp2/nghttp2_helper.c
@@ -451,3 +451,38 @@ uint8_t *nghttp2_cpymem(uint8_t *dest, const void *src, size_t len) {
return dest + len;
}
+
+const char *nghttp2_http2_strerror(uint32_t error_code) {
+ switch (error_code) {
+ case NGHTTP2_NO_ERROR:
+ return "NO_ERROR";
+ case NGHTTP2_PROTOCOL_ERROR:
+ return "PROTOCOL_ERROR";
+ case NGHTTP2_INTERNAL_ERROR:
+ return "INTERNAL_ERROR";
+ case NGHTTP2_FLOW_CONTROL_ERROR:
+ return "FLOW_CONTROL_ERROR";
+ case NGHTTP2_SETTINGS_TIMEOUT:
+ return "SETTINGS_TIMEOUT";
+ case NGHTTP2_STREAM_CLOSED:
+ return "STREAM_CLOSED";
+ case NGHTTP2_FRAME_SIZE_ERROR:
+ return "FRAME_SIZE_ERROR";
+ case NGHTTP2_REFUSED_STREAM:
+ return "REFUSED_STREAM";
+ case NGHTTP2_CANCEL:
+ return "CANCEL";
+ case NGHTTP2_COMPRESSION_ERROR:
+ return "COMPRESSION_ERROR";
+ case NGHTTP2_CONNECT_ERROR:
+ return "CONNECT_ERROR";
+ case NGHTTP2_ENHANCE_YOUR_CALM:
+ return "ENHANCE_YOUR_CALM";
+ case NGHTTP2_INADEQUATE_SECURITY:
+ return "INADEQUATE_SECURITY";
+ case NGHTTP2_HTTP_1_1_REQUIRED:
+ return "HTTP_1_1_REQUIRED";
+ default:
+ return "unknown";
+ }
+}
diff --git a/epan/nghttp2/nghttp2_mem.c b/epan/nghttp2/nghttp2_mem.c
index e7d5aae3b8..317363a70d 100644
--- a/epan/nghttp2/nghttp2_mem.c
+++ b/epan/nghttp2/nghttp2_mem.c
@@ -52,6 +52,10 @@ void nghttp2_mem_free(nghttp2_mem *mem, void *ptr) {
mem->free(ptr, mem->mem_user_data);
}
+void nghttp2_mem_free2(nghttp2_free free, void *ptr, void *mem_user_data) {
+ free(ptr, 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);
}
diff --git a/epan/nghttp2/nghttp2_mem.h b/epan/nghttp2/nghttp2_mem.h
index 47e3fcdfd0..55b187e8e1 100644
--- a/epan/nghttp2/nghttp2_mem.h
+++ b/epan/nghttp2/nghttp2_mem.h
@@ -38,6 +38,7 @@ nghttp2_mem *nghttp2_mem_default(void);
|mem|. */
void *nghttp2_mem_malloc(nghttp2_mem *mem, size_t size);
void nghttp2_mem_free(nghttp2_mem *mem, void *ptr);
+void nghttp2_mem_free2(nghttp2_free free, void *ptr, void *mem_user_data);
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);
diff --git a/epan/nghttp2/nghttp2_rcbuf.c b/epan/nghttp2/nghttp2_rcbuf.c
new file mode 100644
index 0000000000..5daef07b7d
--- /dev/null
+++ b/epan/nghttp2/nghttp2_rcbuf.c
@@ -0,0 +1,99 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2016 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_rcbuf.h"
+
+#include <string.h>
+#include <assert.h>
+
+#include "nghttp2_mem.h"
+
+int nghttp2_rcbuf_new(nghttp2_rcbuf **rcbuf_ptr, size_t size,
+ nghttp2_mem *mem) {
+ uint8_t *p;
+
+ p = (uint8_t *)nghttp2_mem_malloc(mem, sizeof(nghttp2_rcbuf) + size);
+ if (p == NULL) {
+ return NGHTTP2_ERR_NOMEM;
+ }
+
+ *rcbuf_ptr = (nghttp2_rcbuf *)(void *)p;
+
+ (*rcbuf_ptr)->mem_user_data = mem->mem_user_data;
+ (*rcbuf_ptr)->free = mem->free;
+ (*rcbuf_ptr)->base = p + sizeof(nghttp2_rcbuf);
+ (*rcbuf_ptr)->len = size;
+ (*rcbuf_ptr)->ref = 1;
+
+ return 0;
+}
+
+int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src,
+ size_t srclen, nghttp2_mem *mem) {
+ int rv;
+
+ rv = nghttp2_rcbuf_new(rcbuf_ptr, srclen + 1, mem);
+ if (rv != 0) {
+ return rv;
+ }
+
+ memcpy((*rcbuf_ptr)->base, src, srclen);
+
+ (*rcbuf_ptr)->len = srclen;
+ (*rcbuf_ptr)->base[srclen] = '\0';
+
+ return 0;
+}
+
+/*
+ * Frees |rcbuf| itself, regardless of its reference cout.
+ */
+void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf) {
+ nghttp2_mem_free2(rcbuf->free, rcbuf, rcbuf->mem_user_data);
+}
+
+void nghttp2_rcbuf_incref(nghttp2_rcbuf *rcbuf) {
+ if (rcbuf->ref == -1) {
+ return;
+ }
+
+ ++rcbuf->ref;
+}
+
+void nghttp2_rcbuf_decref(nghttp2_rcbuf *rcbuf) {
+ if (rcbuf == NULL || rcbuf->ref == -1) {
+ return;
+ }
+
+ assert(rcbuf->ref > 0);
+
+ if (--rcbuf->ref == 0) {
+ nghttp2_rcbuf_del(rcbuf);
+ }
+}
+
+nghttp2_vec nghttp2_rcbuf_get_buf(nghttp2_rcbuf *rcbuf) {
+ nghttp2_vec res = {rcbuf->base, rcbuf->len};
+ return res;
+}
diff --git a/epan/nghttp2/nghttp2_rcbuf.h b/epan/nghttp2/nghttp2_rcbuf.h
new file mode 100644
index 0000000000..aba4b60d4a
--- /dev/null
+++ b/epan/nghttp2/nghttp2_rcbuf.h
@@ -0,0 +1,80 @@
+/*
+ * nghttp2 - HTTP/2 C Library
+ *
+ * Copyright (c) 2016 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_RCBUF_H
+#define NGHTTP2_RCBUF_H
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif /* HAVE_CONFIG_H */
+
+#include <nghttp2.h>
+
+struct nghttp2_rcbuf {
+ /* custom memory allocator belongs to the mem parameter when
+ creating this object. */
+ void *mem_user_data;
+ nghttp2_free free;
+ /* The pointer to the underlying buffer */
+ uint8_t *base;
+ /* Size of buffer pointed by |base|. */
+ size_t len;
+ /* Reference count */
+ int32_t ref;
+};
+
+/*
+ * Allocates nghttp2_rcbuf object with |size| as initial buffer size.
+ * When the function succeeds, the reference count becomes 1.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM:
+ * Out of memory.
+ */
+int nghttp2_rcbuf_new(nghttp2_rcbuf **rcbuf_ptr, size_t size, nghttp2_mem *mem);
+
+/*
+ * Like nghttp2_rcbuf_new(), but initializes the buffer with |src| of
+ * length |srclen|. This function allocates additional byte at the
+ * end and puts '\0' into it, so that the resulting buffer could be
+ * used as NULL-terminated string. Still (*rcbuf_ptr)->len equals to
+ * |srclen|.
+ *
+ * This function returns 0 if it succeeds, or one of the following
+ * negative error codes:
+ *
+ * NGHTTP2_ERR_NOMEM:
+ * Out of memory.
+ */
+int nghttp2_rcbuf_new2(nghttp2_rcbuf **rcbuf_ptr, const uint8_t *src,
+ size_t srclen, nghttp2_mem *mem);
+
+/*
+ * Frees |rcbuf| itself, regardless of its reference cout.
+ */
+void nghttp2_rcbuf_del(nghttp2_rcbuf *rcbuf);
+
+#endif /* NGHTTP2_RCBUF_H */
diff --git a/epan/nghttp2/nghttp2ver.h b/epan/nghttp2/nghttp2ver.h
index 58472c3276..6638235b43 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 "1.8.0"
+#define NGHTTP2_VERSION "1.11.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 0x010800
+#define NGHTTP2_VERSION_NUM 0x010b01
#endif /* NGHTTP2VER_H */