aboutsummaryrefslogtreecommitdiffstats
path: root/epan/nghttp2
diff options
context:
space:
mode:
authorAlexis La Goutte <alexis.lagoutte@gmail.com>2015-08-12 20:58:52 +0200
committerAlexis La Goutte <alexis.lagoutte@gmail.com>2015-08-31 17:51:50 +0000
commit7dd834975fb9956dc7e8bef89cae111fe0b3610a (patch)
treeda545dd8fa4f2f41600341fd714d6f7c2e50ee3c /epan/nghttp2
parent026812c39108665cc339b8b916f932ff62760c94 (diff)
NGHTTP2: Update to 1.3.0
Change-Id: Ia12396b3b4a2bb4dcbdce63d06558b6474cd588e Reviewed-on: https://code.wireshark.org/review/10324 Petri-Dish: Alexis La Goutte <alexis.lagoutte@gmail.com> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Diffstat (limited to 'epan/nghttp2')
-rw-r--r--epan/nghttp2/nghttp2.h162
-rw-r--r--epan/nghttp2/nghttp2_hd.c30
-rw-r--r--epan/nghttp2/nghttp2_hd.h6
-rw-r--r--epan/nghttp2/nghttp2_helper.h7
-rw-r--r--epan/nghttp2/nghttp2ver.h4
5 files changed, 199 insertions, 10 deletions
diff --git a/epan/nghttp2/nghttp2.h b/epan/nghttp2/nghttp2.h
index 61f2a01c7b..ad5b501c7c 100644
--- a/epan/nghttp2/nghttp2.h
+++ b/epan/nghttp2/nghttp2.h
@@ -2047,6 +2047,25 @@ NGHTTP2_EXTERN void nghttp2_option_set_no_http_messaging(nghttp2_option *option,
/**
* @function
*
+ * RFC 7540 does not enforce any limit on the number of incoming
+ * reserved streams (in RFC 7540 terms, streams in reserved (remote)
+ * state). This only affects client side, since only server can push
+ * streams. Malicious server can push arbitrary number of streams,
+ * and make client's memory exhausted. This option can set the
+ * maximum number of such incoming streams to avoid possible memory
+ * exhaustion. If this option is set, and pushed streams are
+ * automatically closed on reception, without calling user provided
+ * callback, if they exceed the given limit. The default value is
+ * 200. If session is configured as server side, this option has no
+ * effect. Server can control the number of streams to push.
+ */
+NGHTTP2_EXTERN void
+nghttp2_option_set_max_reserved_remote_streams(nghttp2_option *option,
+ uint32_t 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
@@ -3291,10 +3310,6 @@ NGHTTP2_EXTERN int nghttp2_submit_rst_stream(nghttp2_session *session,
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* The |iv| contains invalid value (e.g., initial window size
* strictly greater than (1 << 31) - 1.
- * :enum:`NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS`
- * There is already another in-flight SETTINGS. Note that the
- * current implementation only allows 1 in-flight SETTINGS frame
- * without ACK flag set.
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
*/
@@ -3790,11 +3805,22 @@ NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater);
* The |settings_hd_table_bufsize_max| should be the value transmitted
* in SETTINGS_HEADER_TABLE_SIZE.
*
+ * 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_end_headers()`. Otherwise,
+ * `NGHTTP2_ERR_INVALID_STATE` was returned.
+ *
* 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 while header block is being inflated.
+ * Probably, application missed to call
+ * `nghttp2_hd_inflate_end_headers()`.
*/
NGHTTP2_EXTERN int
nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
@@ -3913,6 +3939,134 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
NGHTTP2_EXTERN int
nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
+struct nghttp2_stream;
+
+/**
+ * @typedef
+ *
+ * The structure to represent HTTP/2 stream. The details of this
+ * structure are intentionally hidden from the public API.
+ */
+typedef struct nghttp2_stream nghttp2_stream;
+
+/**
+ * @function
+ *
+ * Returns pointer to :type:`nghttp2_stream` object denoted by
+ * |stream_id|. If stream was not found, returns NULL.
+ *
+ * Returns imaginary root stream (see
+ * `nghttp2_session_get_root_stream()`) if 0 is given in |stream_id|.
+ *
+ * Unless |stream_id| == 0, the returned pointer is valid until next
+ * call of `nghttp2_session_send()`, `nghttp2_session_mem_send()`,
+ * `nghttp2_session_recv()`, and `nghttp2_session_mem_recv()`.
+ */
+nghttp2_stream *nghttp2_session_find_stream(nghttp2_session *session,
+ int32_t stream_id);
+
+/**
+ * @enum
+ *
+ * State of stream as described in RFC 7540.
+ */
+typedef enum {
+ /**
+ * idle state.
+ */
+ NGHTTP2_STREAM_STATE_IDLE = 1,
+ /**
+ * open state.
+ */
+ NGHTTP2_STREAM_STATE_OPEN,
+ /**
+ * reserved (local) state.
+ */
+ NGHTTP2_STREAM_STATE_RESERVED_LOCAL,
+ /**
+ * reserved (remote) state.
+ */
+ NGHTTP2_STREAM_STATE_RESERVED_REMOTE,
+ /**
+ * half closed (local) state.
+ */
+ NGHTTP2_STREAM_STATE_HALF_CLOSED_LOCAL,
+ /**
+ * half closed (remote) state.
+ */
+ NGHTTP2_STREAM_STATE_HALF_CLOSED_REMOTE,
+ /**
+ * closed state.
+ */
+ NGHTTP2_STREAM_STATE_CLOSED
+} nghttp2_stream_proto_state;
+
+/**
+ * @function
+ *
+ * Returns state of |stream|. The root stream retrieved by
+ * `nghttp2_session_get_root_stream()` will have stream state
+ * :enum:`NGHTTP2_STREAM_STATE_IDLE`.
+ */
+nghttp2_stream_proto_state nghttp2_stream_get_state(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns root of dependency tree, which is imaginary stream with
+ * stream ID 0. The returned pointer is valid until |session| is
+ * freed by `nghttp2_session_del()`.
+ */
+nghttp2_stream *nghttp2_session_get_root_stream(nghttp2_session *session);
+
+/**
+ * @function
+ *
+ * Returns the parent stream of |stream| in dependency tree. Returns
+ * NULL if there is no such stream.
+ */
+nghttp2_stream *nghttp2_stream_get_parent(nghttp2_stream *stream);
+
+int32_t nghttp2_stream_get_stream_id(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the next sibling stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+nghttp2_stream *nghttp2_stream_get_next_sibling(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the previous sibling stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+nghttp2_stream *nghttp2_stream_get_previous_sibling(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the first child stream of |stream| in dependency tree.
+ * Returns NULL if there is no such stream.
+ */
+nghttp2_stream *nghttp2_stream_get_first_child(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns dependency weight to the parent stream of |stream|.
+ */
+int32_t nghttp2_stream_get_weight(nghttp2_stream *stream);
+
+/**
+ * @function
+ *
+ * Returns the sum of the weight for |stream|'s children.
+ */
+int32_t nghttp2_stream_get_sum_dependency_weight(nghttp2_stream *stream);
+
#ifdef __cplusplus
}
#endif
diff --git a/epan/nghttp2/nghttp2_hd.c b/epan/nghttp2/nghttp2_hd.c
index ff818fedd4..326ae723a2 100644
--- a/epan/nghttp2/nghttp2_hd.c
+++ b/epan/nghttp2/nghttp2_hd.c
@@ -704,7 +704,7 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
inflater->nv_keep = NULL;
inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
- inflater->state = NGHTTP2_HD_STATE_OPCODE;
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
rv = nghttp2_bufs_init3(&inflater->nvbufs, NGHTTP2_HD_MAX_NV / 8, 8, 1, 0,
mem);
@@ -1261,6 +1261,15 @@ int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
size_t settings_hd_table_bufsize_max) {
+ switch (inflater->state) {
+ case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
+ case NGHTTP2_HD_STATE_INFLATE_START:
+ break;
+ default:
+ return NGHTTP2_ERR_INVALID_STATE;
+ }
+
+ inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE;
inflater->settings_hd_table_bufsize_max = settings_hd_table_bufsize_max;
inflater->ctx.hd_table_bufsize_max = settings_hd_table_bufsize_max;
hd_context_shrink_table_size(&inflater->ctx);
@@ -1951,9 +1960,25 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
for (; in != last || busy;) {
busy = 0;
switch (inflater->state) {
+ case NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE:
+ if ((*in & 0xe0u) != 0x20u) {
+ DEBUGF(fprintf(stderr, "inflatehd: header table size change was "
+ "expected, but saw 0x%02x as first byte",
+ *in));
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ goto fail;
+ }
+ /* fall through */
+ case NGHTTP2_HD_STATE_INFLATE_START:
case NGHTTP2_HD_STATE_OPCODE:
if ((*in & 0xe0u) == 0x20u) {
DEBUGF(fprintf(stderr, "inflatehd: header table size change\n"));
+ if (inflater->state == NGHTTP2_HD_STATE_OPCODE) {
+ DEBUGF(fprintf(stderr, "inflatehd: header table size change must "
+ "appear at the head of header block\n"));
+ rv = NGHTTP2_ERR_HEADER_COMP;
+ goto fail;
+ }
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
} else if (*in & 0x80u) {
@@ -1997,7 +2022,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
DEBUGF(fprintf(stderr, "inflatehd: table_size=%zu\n", inflater->left));
inflater->ctx.hd_table_bufsize_max = inflater->left;
hd_context_shrink_table_size(&inflater->ctx);
- inflater->state = NGHTTP2_HD_STATE_OPCODE;
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
break;
case NGHTTP2_HD_STATE_READ_INDEX: {
size_t prefixlen;
@@ -2282,6 +2307,7 @@ fail:
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) {
hd_inflate_keep_free(inflater);
+ inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
return 0;
}
diff --git a/epan/nghttp2/nghttp2_hd.h b/epan/nghttp2/nghttp2_hd.h
index 07ea8af3ef..e85a04b6e7 100644
--- a/epan/nghttp2/nghttp2_hd.h
+++ b/epan/nghttp2/nghttp2_hd.h
@@ -151,6 +151,8 @@ typedef enum {
} nghttp2_hd_opcode;
typedef enum {
+ NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE,
+ NGHTTP2_HD_STATE_INFLATE_START,
NGHTTP2_HD_STATE_OPCODE,
NGHTTP2_HD_STATE_READ_TABLE_SIZE,
NGHTTP2_HD_STATE_READ_INDEX,
@@ -356,8 +358,8 @@ 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_EXTERN nghttp2_hd_entry *nghttp2_hd_table_get(nghttp2_hd_context *context,
- size_t index);
+NGHTTP2_EXTERN nghttp2_hd_entry *
+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,
diff --git a/epan/nghttp2/nghttp2_helper.h b/epan/nghttp2/nghttp2_helper.h
index de2d8c0a14..aa460cc7c8 100644
--- a/epan/nghttp2/nghttp2_helper.h
+++ b/epan/nghttp2/nghttp2_helper.h
@@ -30,6 +30,7 @@
#endif /* HAVE_CONFIG_H */
#include <string.h>
+#include <stddef.h>
#include <nghttp2.h>
#include "nghttp2_mem.h"
@@ -39,6 +40,12 @@
#define lstreq(A, B, N) ((sizeof((A)) - 1) == (N) && memcmp((A), (B), (N)) == 0)
+#define nghttp2_struct_of(ptr, type, member) \
+ ({ \
+ const typeof(((type *)0)->member) *nghttp2__mptr = (nghttp2_pq_entry *)(ptr); \
+ (type *)(void *)((char *)nghttp2__mptr - __builtin_offsetof(type, member)); \
+ })
+
/*
* Copies 2 byte unsigned integer |n| in host byte order to |buf| in
* network byte order.
diff --git a/epan/nghttp2/nghttp2ver.h b/epan/nghttp2/nghttp2ver.h
index 0d12eb2e68..fc5dbd193d 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.1.2"
+#define NGHTTP2_VERSION "1.3.0"
/**
* @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 0x010102
+#define NGHTTP2_VERSION_NUM 0x010300
#endif /* NGHTTP2VER_H */