summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--epan/nghttp2/nghttp2_buf.c16
-rw-r--r--epan/nghttp2/nghttp2_buf.h21
-rw-r--r--epan/nghttp2/nghttp2_hd.c348
-rw-r--r--epan/nghttp2/nghttp2_hd.h21
-rw-r--r--epan/nghttp2/nghttp2_hd_huffman.c22
-rw-r--r--epan/nghttp2/nghttp2_hd_huffman.h3
-rw-r--r--epan/nghttp2/nghttp2_helper.c2
-rw-r--r--epan/nghttp2/nghttp2_helper.h7
-rw-r--r--epan/nghttp2/nghttp2ver.h4
9 files changed, 292 insertions, 152 deletions
diff --git a/epan/nghttp2/nghttp2_buf.c b/epan/nghttp2/nghttp2_buf.c
index 6bba48cc20..f6018bca46 100644
--- a/epan/nghttp2/nghttp2_buf.c
+++ b/epan/nghttp2/nghttp2_buf.c
@@ -244,9 +244,9 @@ void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs) {
}
}
-ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
+size_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
nghttp2_buf_chain *ci;
- ssize_t len;
+ size_t len;
len = 0;
for (ci = bufs->head; ci; ci = ci->next) {
@@ -256,10 +256,10 @@ ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs) {
return len;
}
-static ssize_t bufs_avail(nghttp2_bufs *bufs) {
- return (ssize_t)(nghttp2_buf_avail(&bufs->cur->buf) +
- (bufs->chunk_length - bufs->offset) *
- (bufs->max_chunk - bufs->chunk_used));
+static size_t bufs_avail(nghttp2_bufs *bufs) {
+ return nghttp2_buf_avail(&bufs->cur->buf) +
+ (bufs->chunk_length - bufs->offset) *
+ (bufs->max_chunk - bufs->chunk_used);
}
static int bufs_alloc_chain(nghttp2_bufs *bufs) {
@@ -301,7 +301,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
nghttp2_buf *buf;
const uint8_t *p;
- if (bufs_avail(bufs) < (ssize_t)len) {
+ if (bufs_avail(bufs) < len) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
@@ -310,7 +310,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len) {
while (len) {
buf = &bufs->cur->buf;
- nwrite = nghttp2_min((size_t)nghttp2_buf_avail(buf), len);
+ nwrite = nghttp2_min(nghttp2_buf_avail(buf), len);
if (nwrite == 0) {
rv = bufs_alloc_chain(bufs);
if (rv != 0) {
diff --git a/epan/nghttp2/nghttp2_buf.h b/epan/nghttp2/nghttp2_buf.h
index a84dc7bea2..072e835ec1 100644
--- a/epan/nghttp2/nghttp2_buf.h
+++ b/epan/nghttp2/nghttp2_buf.h
@@ -51,13 +51,13 @@ typedef struct {
uint8_t *mark;
} nghttp2_buf;
-#define nghttp2_buf_len(BUF) ((ssize_t)((BUF)->last - (BUF)->pos))
-#define nghttp2_buf_avail(BUF) ((ssize_t)((BUF)->end - (BUF)->last))
-#define nghttp2_buf_mark_avail(BUF) ((ssize_t)((BUF)->mark - (BUF)->last))
-#define nghttp2_buf_cap(BUF) ((ssize_t)((BUF)->end - (BUF)->begin))
+#define nghttp2_buf_len(BUF) ((size_t)((BUF)->last - (BUF)->pos))
+#define nghttp2_buf_avail(BUF) ((size_t)((BUF)->end - (BUF)->last))
+#define nghttp2_buf_mark_avail(BUF) ((size_t)((BUF)->mark - (BUF)->last))
+#define nghttp2_buf_cap(BUF) ((size_t)((BUF)->end - (BUF)->begin))
-#define nghttp2_buf_pos_offset(BUF) ((ssize_t)((BUF)->pos - (BUF)->begin))
-#define nghttp2_buf_last_offset(BUF) ((ssize_t)((BUF)->last - (BUF)->begin))
+#define nghttp2_buf_pos_offset(BUF) ((size_t)((BUF)->pos - (BUF)->begin))
+#define nghttp2_buf_last_offset(BUF) ((size_t)((BUF)->last - (BUF)->begin))
#define nghttp2_buf_shift_right(BUF, AMT) \
do { \
@@ -300,12 +300,15 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
#define nghttp2_bufs_fast_orb(BUFS, B) \
do { \
- *(BUFS)->cur->buf.last++ |= B; \
+ uint8_t **p = &(BUFS)->cur->buf.last; \
+ **p = (uint8_t)(**p | (B)); \
+ ++(*p); \
} while (0)
#define nghttp2_bufs_fast_orb_hold(BUFS, B) \
do { \
- *(BUFS)->cur->buf.last |= B; \
+ uint8_t *p = (BUFS)->cur->buf.last; \
+ *p = (uint8_t)(*p | (B)); \
} while (0)
/*
@@ -380,6 +383,6 @@ int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
/*
* Returns the buffer length of |bufs|.
*/
-ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs);
+size_t nghttp2_bufs_len(nghttp2_bufs *bufs);
#endif /* NGHTTP2_BUF_H */
diff --git a/epan/nghttp2/nghttp2_hd.c b/epan/nghttp2/nghttp2_hd.c
index 326ae723a2..d08e5c411c 100644
--- a/epan/nghttp2/nghttp2_hd.c
+++ b/epan/nghttp2/nghttp2_hd.c
@@ -32,10 +32,10 @@
#include "nghttp2_int.h"
/* Make scalar initialization form of nghttp2_hd_entry */
-#define MAKE_STATIC_ENT(N, V, T) \
+#define MAKE_STATIC_ENT(N, V, T, H) \
{ \
{ (uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0 } \
- , (T), 1, NGHTTP2_HD_FLAG_NONE \
+ , NULL, 0, (H), (T), 1, NGHTTP2_HD_FLAG_NONE \
}
/* Generated by mkstatictbl.py */
@@ -43,67 +43,67 @@
first enum value if same header names are repeated (e.g.,
:status). */
static nghttp2_hd_entry static_table[] = {
- MAKE_STATIC_ENT(":authority", "", 0),
- MAKE_STATIC_ENT(":method", "GET", 1),
- MAKE_STATIC_ENT(":method", "POST", 1),
- MAKE_STATIC_ENT(":path", "/", 3),
- MAKE_STATIC_ENT(":path", "/index.html", 3),
- MAKE_STATIC_ENT(":scheme", "http", 5),
- MAKE_STATIC_ENT(":scheme", "https", 5),
- MAKE_STATIC_ENT(":status", "200", 7),
- MAKE_STATIC_ENT(":status", "204", 7),
- MAKE_STATIC_ENT(":status", "206", 7),
- MAKE_STATIC_ENT(":status", "304", 7),
- MAKE_STATIC_ENT(":status", "400", 7),
- MAKE_STATIC_ENT(":status", "404", 7),
- MAKE_STATIC_ENT(":status", "500", 7),
- MAKE_STATIC_ENT("accept-charset", "", 14),
- MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15),
- MAKE_STATIC_ENT("accept-language", "", 16),
- MAKE_STATIC_ENT("accept-ranges", "", 17),
- MAKE_STATIC_ENT("accept", "", 18),
- MAKE_STATIC_ENT("access-control-allow-origin", "", 19),
- MAKE_STATIC_ENT("age", "", 20),
- MAKE_STATIC_ENT("allow", "", 21),
- MAKE_STATIC_ENT("authorization", "", 22),
- MAKE_STATIC_ENT("cache-control", "", 23),
- MAKE_STATIC_ENT("content-disposition", "", 24),
- MAKE_STATIC_ENT("content-encoding", "", 25),
- MAKE_STATIC_ENT("content-language", "", 26),
- MAKE_STATIC_ENT("content-length", "", 27),
- MAKE_STATIC_ENT("content-location", "", 28),
- MAKE_STATIC_ENT("content-range", "", 29),
- MAKE_STATIC_ENT("content-type", "", 30),
- MAKE_STATIC_ENT("cookie", "", 31),
- MAKE_STATIC_ENT("date", "", 32),
- MAKE_STATIC_ENT("etag", "", 33),
- MAKE_STATIC_ENT("expect", "", 34),
- MAKE_STATIC_ENT("expires", "", 35),
- MAKE_STATIC_ENT("from", "", 36),
- MAKE_STATIC_ENT("host", "", 37),
- MAKE_STATIC_ENT("if-match", "", 38),
- MAKE_STATIC_ENT("if-modified-since", "", 39),
- MAKE_STATIC_ENT("if-none-match", "", 40),
- MAKE_STATIC_ENT("if-range", "", 41),
- MAKE_STATIC_ENT("if-unmodified-since", "", 42),
- MAKE_STATIC_ENT("last-modified", "", 43),
- MAKE_STATIC_ENT("link", "", 44),
- MAKE_STATIC_ENT("location", "", 45),
- MAKE_STATIC_ENT("max-forwards", "", 46),
- MAKE_STATIC_ENT("proxy-authenticate", "", 47),
- MAKE_STATIC_ENT("proxy-authorization", "", 48),
- MAKE_STATIC_ENT("range", "", 49),
- MAKE_STATIC_ENT("referer", "", 50),
- MAKE_STATIC_ENT("refresh", "", 51),
- MAKE_STATIC_ENT("retry-after", "", 52),
- MAKE_STATIC_ENT("server", "", 53),
- MAKE_STATIC_ENT("set-cookie", "", 54),
- MAKE_STATIC_ENT("strict-transport-security", "", 55),
- MAKE_STATIC_ENT("transfer-encoding", "", 56),
- MAKE_STATIC_ENT("user-agent", "", 57),
- MAKE_STATIC_ENT("vary", "", 58),
- MAKE_STATIC_ENT("via", "", 59),
- MAKE_STATIC_ENT("www-authenticate", "", 60),
+ MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
+ MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
+ MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
+ MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
+ MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
+ MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
+ MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
+ MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
+ MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
+ MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
+ MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
+ MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
+ MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
+ MAKE_STATIC_ENT("accept", "", 18, 136609321u),
+ MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
+ MAKE_STATIC_ENT("age", "", 20, 742476188u),
+ MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
+ MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
+ MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
+ MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
+ MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
+ MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
+ MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
+ MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
+ MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
+ MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
+ MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
+ MAKE_STATIC_ENT("date", "", 32, 3564297305u),
+ MAKE_STATIC_ENT("etag", "", 33, 113792960u),
+ MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
+ MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
+ MAKE_STATIC_ENT("from", "", 36, 2513272949u),
+ MAKE_STATIC_ENT("host", "", 37, 2952701295u),
+ MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
+ MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
+ MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
+ MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
+ MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
+ MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
+ MAKE_STATIC_ENT("link", "", 44, 232457833u),
+ MAKE_STATIC_ENT("location", "", 45, 200649126u),
+ MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
+ MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
+ MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
+ MAKE_STATIC_ENT("range", "", 49, 4208725202u),
+ MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
+ MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
+ MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
+ MAKE_STATIC_ENT("server", "", 53, 1085029842u),
+ MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
+ MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
+ MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
+ MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
+ MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
+ MAKE_STATIC_ENT("via", "", 59, 1762798611u),
+ MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
};
static int memeq(const void *s1, const void *s2, size_t n) {
@@ -506,7 +506,7 @@ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
if ((flags & NGHTTP2_HD_FLAG_NAME_ALLOC) &&
(flags & NGHTTP2_HD_FLAG_NAME_GIFT) == 0) {
if (namelen == 0) {
- flags &= ~NGHTTP2_HD_FLAG_NAME_ALLOC;
+ flags = (uint8_t)(flags & ~NGHTTP2_HD_FLAG_NAME_ALLOC);
ent->nv.name = (uint8_t *)"";
} else {
/* copy including terminating NULL byte */
@@ -522,7 +522,7 @@ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
if ((flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) &&
(flags & NGHTTP2_HD_FLAG_VALUE_GIFT) == 0) {
if (valuelen == 0) {
- flags &= ~NGHTTP2_HD_FLAG_VALUE_ALLOC;
+ flags = (uint8_t)(flags & ~NGHTTP2_HD_FLAG_VALUE_ALLOC);
ent->nv.value = (uint8_t *)"";
} else {
/* copy including terminating NULL byte */
@@ -540,6 +540,8 @@ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
ent->token = token;
ent->ref = 1;
ent->flags = flags;
+ ent->next = NULL;
+ ent->hash = 0;
return 0;
@@ -562,6 +564,97 @@ void nghttp2_hd_entry_free(nghttp2_hd_entry *ent, nghttp2_mem *mem) {
}
}
+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 value_eq(const nghttp2_nv *a, const nghttp2_nv *b) {
+ return a->valuelen == b->valuelen && memeq(a->value, b->value, a->valuelen);
+}
+
+static uint32_t name_hash(const nghttp2_nv *nv) {
+ /* 32 bit FNV-1a: http://isthe.com/chongo/tech/comp/fnv/ */
+ uint32_t h = 2166136261;
+ size_t i;
+
+ for (i = 0; i < nv->namelen; ++i) {
+ h ^= nv->name[i];
+ h += (h << 1) + (h << 4) + (h << 7) + (h << 8) + (h << 24);
+ }
+
+ return h;
+}
+
+static void hd_map_init(nghttp2_hd_map *map) {
+ memset(map, 0, sizeof(nghttp2_hd_map));
+}
+
+static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
+ nghttp2_hd_entry **bucket;
+
+ bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
+
+ if (*bucket == NULL) {
+ *bucket = ent;
+ return;
+ }
+
+ /* lower index is linked near the root */
+ ent->next = *bucket;
+ *bucket = ent;
+}
+
+static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
+ const nghttp2_nv *nv, int token,
+ uint32_t hash) {
+ nghttp2_hd_entry *p;
+ nghttp2_hd_entry *res = NULL;
+
+ *exact_match = 0;
+
+ for (p = map->table[hash & (HD_MAP_SIZE - 1)]; p; p = p->next) {
+ if (hash != p->hash || token != p->token ||
+ (token == -1 && !name_eq(&p->nv, nv))) {
+ continue;
+ }
+ if (!res) {
+ res = p;
+ }
+ if (value_eq(&p->nv, nv)) {
+ res = p;
+ *exact_match = 1;
+ break;
+ }
+ }
+
+ return res;
+}
+
+static void hd_map_remove(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
+ nghttp2_hd_entry **bucket;
+ nghttp2_hd_entry *p;
+
+ bucket = &map->table[ent->hash & (HD_MAP_SIZE - 1)];
+
+ if (*bucket == NULL) {
+ return;
+ }
+
+ if (*bucket == ent) {
+ *bucket = 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,
nghttp2_mem *mem) {
size_t size;
@@ -656,6 +749,8 @@ static int hd_context_init(nghttp2_hd_context *context, nghttp2_mem *mem) {
}
context->hd_table_bufsize = 0;
+ context->next_seq = 0;
+
return 0;
}
@@ -677,6 +772,8 @@ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
return rv;
}
+ hd_map_init(&deflater->map);
+
if (deflate_hd_table_bufsize_max < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
deflater->notify_table_size_change = 1;
deflater->ctx.hd_table_bufsize_max = deflate_hd_table_bufsize_max;
@@ -780,7 +877,7 @@ static int emit_literal_header(nghttp2_nv *nv_out, int *token_out,
}
static size_t count_encoded_length(size_t n, size_t prefix) {
- size_t k = (1 << prefix) - 1;
+ size_t k = (size_t)((1 << prefix) - 1);
size_t len = 0;
if (n < k) {
@@ -797,21 +894,23 @@ static size_t count_encoded_length(size_t n, size_t prefix) {
}
static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
- size_t k = (1 << prefix) - 1;
+ size_t k = (size_t)((1 << prefix) - 1);
uint8_t *begin = buf;
- *buf &= ~k;
+ *buf = (uint8_t)(*buf & ~k);
if (n < k) {
- *buf |= n;
+ *buf = (uint8_t)(*buf | n);
return 1;
}
- *buf++ |= k;
+ *buf = (uint8_t)(*buf | k);
+ ++buf;
+
n -= k;
for (; n >= 128; n >>= 7) {
- *buf++ = (1 << 7) | (n & 0x7f);
+ *buf++ = (uint8_t)((1 << 7) | (n & 0x7f));
}
*buf++ = (uint8_t)n;
@@ -839,7 +938,7 @@ static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
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 k = (1 << prefix) - 1;
+ uint32_t k = (uint8_t)((1 << prefix) - 1);
uint32_t n = initial;
uint8_t *start = in;
@@ -1081,10 +1180,10 @@ 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) {
+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) {
int rv;
nghttp2_hd_entry *new_ent;
size_t room;
@@ -1105,6 +1204,9 @@ static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context,
ent->nv.name, ent->nv.value));
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);
@@ -1152,19 +1254,21 @@ static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context,
return NULL;
}
+ new_ent->seq = context->next_seq++;
+ new_ent->hash = hash;
+
+ DEBUGF(fprintf(stderr, "deflatehd: indexed at %zu\n",
+ context->hd_table.len + NGHTTP2_STATIC_TABLE_LENGTH));
+
+ if (map) {
+ hd_map_insert(map, new_ent);
+ }
+
context->hd_table_bufsize += room;
}
return new_ent;
}
-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 value_eq(const nghttp2_nv *a, const nghttp2_nv *b) {
- return a->valuelen == b->valuelen && memeq(a->value, b->value, a->valuelen);
-}
-
typedef struct {
ssize_t index;
/* Nonzero if both name and value are matched. */
@@ -1194,9 +1298,11 @@ 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,
- int indexing_mode) {
+ int indexing_mode, nghttp2_hd_map *map,
+ uint32_t hash) {
search_result res = {-1, 0};
- size_t i;
+ nghttp2_hd_entry *ent;
+ int exact_match;
if (token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
res = search_static_table(nv, token, indexing_mode);
@@ -1205,27 +1311,27 @@ static search_result search_hd_table(nghttp2_hd_context *context,
}
}
- for (i = 0; i < context->hd_table.len; ++i) {
- nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, i);
- if (ent->token != token || (token == -1 && !name_eq(&ent->nv, nv))) {
- continue;
- }
+ exact_match = 0;
+ ent = hd_map_find(map, &exact_match, nv, token, hash);
+ if (ent == NULL) {
+ return res;
+ }
- if (res.index == -1) {
- res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH);
- }
+ if (res.index != -1 && !exact_match) {
+ return res;
+ }
- if (indexing_mode != NGHTTP2_HD_NEVER_INDEXING && value_eq(&ent->nv, nv)) {
- res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH);
- res.name_value_match = 1;
- return res;
- }
+ res.index = context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH;
+
+ if (exact_match) {
+ res.name_value_match = 1;
}
return res;
}
-static void hd_context_shrink_table_size(nghttp2_hd_context *context) {
+static void hd_context_shrink_table_size(nghttp2_hd_context *context,
+ nghttp2_hd_map *map) {
nghttp2_mem *mem;
mem = context->mem;
@@ -1236,6 +1342,9 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context) {
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen);
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);
@@ -1255,7 +1364,7 @@ int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
deflater->notify_table_size_change = 1;
- hd_context_shrink_table_size(&deflater->ctx);
+ hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
return 0;
}
@@ -1272,7 +1381,7 @@ int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
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);
+ hd_context_shrink_table_size(&inflater->ctx, NULL);
return 0;
}
@@ -1317,12 +1426,18 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
int indexing_mode;
int token;
nghttp2_mem *mem;
+ uint32_t hash;
DEBUGF(fprintf(stderr, "deflatehd: deflating %s: %s\n", nv->name, nv->value));
mem = deflater->ctx.mem;
token = lookup_token(nv->name, nv->namelen);
+ if (token == -1 || token > NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
+ hash = name_hash(nv);
+ } else {
+ hash = static_table[token].hash;
+ }
/* Don't index authorization header field since it may contain low
entropy secret data (e.g., id/password). Also cookie header
@@ -1335,7 +1450,8 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
? NGHTTP2_HD_NEVER_INDEXING
: hd_deflate_decide_indexing(deflater, nv, token);
- res = search_hd_table(&deflater->ctx, nv, token, indexing_mode);
+ res = search_hd_table(&deflater->ctx, nv, token, indexing_mode,
+ &deflater->map, hash);
idx = res.index;
@@ -1343,7 +1459,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
DEBUGF(fprintf(stderr, "deflatehd: name/value match index=%zd\n", idx));
- rv = emit_indexed_block(bufs, idx);
+ rv = emit_indexed_block(bufs, (size_t)idx);
if (rv != 0) {
return rv;
}
@@ -1360,13 +1476,16 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
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, idx)->nv.name;
+ 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);
+ NGHTTP2_HD_FLAG_VALUE_ALLOC,
+ &deflater->map, hash);
} else {
new_ent = add_hd_table_incremental(&deflater->ctx, nv, token,
NGHTTP2_HD_FLAG_NAME_ALLOC |
- NGHTTP2_HD_FLAG_VALUE_ALLOC);
+ NGHTTP2_HD_FLAG_VALUE_ALLOC,
+ &deflater->map, hash);
}
if (!new_ent) {
return NGHTTP2_ERR_HEADER_COMP;
@@ -1379,7 +1498,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
if (idx == -1) {
rv = emit_newname_block(bufs, nv, indexing_mode);
} else {
- rv = emit_indname_block(bufs, idx, nv, indexing_mode);
+ rv = emit_indname_block(bufs, (size_t)idx, nv, indexing_mode);
}
if (rv != 0) {
return rv;
@@ -1615,7 +1734,7 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
final = 1;
}
readlen = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, bufs, in,
- last - in, final);
+ (size_t)(last - in), final);
if (readlen < 0) {
DEBUGF(fprintf(stderr, "inflatehd: huffman decoding failed\n"));
@@ -1689,7 +1808,7 @@ static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, nghttp2_nv *nv,
nghttp2_bufs_reset(&inflater->nvbufs);
- buflen = rv;
+ buflen = (size_t)rv;
if (value_only) {
/* we don't use this value, so no need to NULL-terminate */
@@ -1816,8 +1935,9 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
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);
+ new_ent = add_hd_table_incremental(&inflater->ctx, &nv,
+ lookup_token(nv.name, nv.namelen),
+ ent_flags, NULL, 0);
if (new_ent) {
emit_indexed_header(nv_out, token_out, new_ent);
@@ -1892,7 +2012,7 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
}
new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->token,
- ent_flags);
+ ent_flags, NULL, 0);
/* At this point, ent_name might be deleted. */
@@ -2021,7 +2141,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);
+ hd_context_shrink_table_size(&inflater->ctx, NULL);
inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
break;
case NGHTTP2_HD_STATE_READ_INDEX: {
diff --git a/epan/nghttp2/nghttp2_hd.h b/epan/nghttp2/nghttp2_hd.h
index e85a04b6e7..36adaf6ef4 100644
--- a/epan/nghttp2/nghttp2_hd.h
+++ b/epan/nghttp2/nghttp2_hd.h
@@ -126,15 +126,25 @@ typedef enum {
NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 3
} nghttp2_hd_flags;
-typedef struct {
+struct nghttp2_hd_entry;
+typedef struct nghttp2_hd_entry nghttp2_hd_entry;
+
+struct nghttp2_hd_entry {
nghttp2_nv nv;
+ /* 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
+ store nghttp2_hd_entry to dynamic header table. */
+ 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;
-} nghttp2_hd_entry;
+};
typedef struct {
nghttp2_hd_entry **buffer;
@@ -183,14 +193,21 @@ typedef struct {
size_t hd_table_bufsize;
/* The effective header table size. */
size_t hd_table_bufsize_max;
+ /* Next sequence number for nghttp2_hd_entry */
+ uint32_t next_seq;
/* If inflate/deflate error occurred, this value is set to 1 and
further invocation of inflate/deflate will fail with
NGHTTP2_ERR_HEADER_COMP. */
uint8_t bad;
} nghttp2_hd_context;
+#define HD_MAP_SIZE 128
+
+typedef struct { nghttp2_hd_entry *table[HD_MAP_SIZE]; } nghttp2_hd_map;
+
struct nghttp2_hd_deflater {
nghttp2_hd_context ctx;
+ nghttp2_hd_map map;
/* The upper limit of the header table size the deflater accepts. */
size_t deflate_hd_table_bufsize_max;
/* Minimum header table size notified in the next context update */
diff --git a/epan/nghttp2/nghttp2_hd_huffman.c b/epan/nghttp2/nghttp2_hd_huffman.c
index 4df1cd0425..fb2d167b03 100644
--- a/epan/nghttp2/nghttp2_hd_huffman.c
+++ b/epan/nghttp2/nghttp2_hd_huffman.c
@@ -48,17 +48,17 @@ static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
/* We assume that sym->nbits <= 32 */
if (rembits > nbits) {
- nghttp2_bufs_fast_orb_hold(bufs, code << (rembits - nbits));
+ nghttp2_bufs_fast_orb_hold(bufs, (uint8_t)(code << (rembits - nbits)));
return (ssize_t)(rembits - nbits);
}
if (rembits == nbits) {
- nghttp2_bufs_fast_orb(bufs, code);
+ nghttp2_bufs_fast_orb(bufs, (uint8_t)code);
--*avail_ptr;
return 8;
}
- nghttp2_bufs_fast_orb(bufs, code >> (nbits - rembits));
+ nghttp2_bufs_fast_orb(bufs, (uint8_t)(code >> (nbits - rembits)));
--*avail_ptr;
nbits -= rembits;
@@ -80,34 +80,34 @@ static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
/* fast path, since most code is less than 8 */
if (nbits < 8) {
- nghttp2_bufs_fast_addb_hold(bufs, code);
+ nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code);
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
return (ssize_t)(8 - nbits);
}
/* handle longer code path */
if (nbits > 24) {
- nghttp2_bufs_fast_addb(bufs, code >> 24);
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 24));
nbits -= 8;
}
if (nbits > 16) {
- nghttp2_bufs_fast_addb(bufs, code >> 16);
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 16));
nbits -= 8;
}
if (nbits > 8) {
- nghttp2_bufs_fast_addb(bufs, code >> 8);
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)(code >> 8));
nbits -= 8;
}
if (nbits == 8) {
- nghttp2_bufs_fast_addb(bufs, code);
+ nghttp2_bufs_fast_addb(bufs, (uint8_t)code);
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
return 8;
}
- nghttp2_bufs_fast_addb_hold(bufs, code);
+ nghttp2_bufs_fast_addb_hold(bufs, (uint8_t)code);
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
return (ssize_t)(8 - nbits);
}
@@ -145,7 +145,7 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
avail = nghttp2_bufs_cur_avail(bufs);
}
}
- rembits = huff_encode_sym(bufs, &avail, rembits, sym);
+ rembits = huff_encode_sym(bufs, &avail, (size_t)rembits, sym);
if (rembits < 0) {
return (int)rembits;
}
@@ -157,7 +157,7 @@ int nghttp2_hd_huff_encode(nghttp2_bufs *bufs, const uint8_t *src,
const nghttp2_huff_sym *sym = &huff_sym_table[256];
assert(avail);
/* Caution we no longer adjust avail here */
- nghttp2_bufs_fast_orb(bufs, sym->code >> (sym->nbits - rembits));
+ nghttp2_bufs_fast_orb(bufs, (uint8_t)(sym->code >> (sym->nbits - rembits)));
}
return 0;
diff --git a/epan/nghttp2/nghttp2_hd_huffman.h b/epan/nghttp2/nghttp2_hd_huffman.h
index a364e4bfe6..e51ee48bb2 100644
--- a/epan/nghttp2/nghttp2_hd_huffman.h
+++ b/epan/nghttp2/nghttp2_hd_huffman.h
@@ -71,4 +71,7 @@ typedef struct {
uint32_t code;
} nghttp2_huff_sym;
+extern const nghttp2_huff_sym huff_sym_table[];
+extern const nghttp2_huff_decode huff_decode_table[][16];
+
#endif /* NGHTTP2_HD_HUFFMAN_H */
diff --git a/epan/nghttp2/nghttp2_helper.c b/epan/nghttp2/nghttp2_helper.c
index aeb2c962ff..c75e082424 100644
--- a/epan/nghttp2/nghttp2_helper.c
+++ b/epan/nghttp2/nghttp2_helper.c
@@ -67,7 +67,7 @@ void *nghttp2_memdup(const void *src, size_t n, nghttp2_mem *mem) {
}
/* Generated by gendowncasetbl.py */
-static const int DOWNCASE_TBL[] = {
+static const uint8_t DOWNCASE_TBL[] = {
0 /* NUL */, 1 /* SOH */, 2 /* STX */, 3 /* ETX */,
4 /* EOT */, 5 /* ENQ */, 6 /* ACK */, 7 /* BEL */,
8 /* BS */, 9 /* HT */, 10 /* LF */, 11 /* VT */,
diff --git a/epan/nghttp2/nghttp2_helper.h b/epan/nghttp2/nghttp2_helper.h
index aa460cc7c8..48008cf4f6 100644
--- a/epan/nghttp2/nghttp2_helper.h
+++ b/epan/nghttp2/nghttp2_helper.h
@@ -40,11 +40,8 @@
#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)); \
- })
+#define nghttp2_struct_of(ptr, type, member) \
+ ((type *)(void *)((char *)(ptr) - offsetof(type, member)))
/*
* Copies 2 byte unsigned integer |n| in host byte order to |buf| in
diff --git a/epan/nghttp2/nghttp2ver.h b/epan/nghttp2/nghttp2ver.h
index fc5dbd193d..173f4648cd 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.3.0"
+#define NGHTTP2_VERSION "1.3.3"
/**
* @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 0x010300
+#define NGHTTP2_VERSION_NUM 0x010303
#endif /* NGHTTP2VER_H */