Use hash table for dynamic table lookup
This commit is contained in:
parent
4ac8edfe27
commit
230b1f927f
317
lib/nghttp2_hd.c
317
lib/nghttp2_hd.c
|
@ -32,10 +32,10 @@
|
||||||
#include "nghttp2_int.h"
|
#include "nghttp2_int.h"
|
||||||
|
|
||||||
/* Make scalar initialization form of nghttp2_hd_entry */
|
/* 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 } \
|
{ (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 */
|
/* Generated by mkstatictbl.py */
|
||||||
|
@ -43,67 +43,67 @@
|
||||||
first enum value if same header names are repeated (e.g.,
|
first enum value if same header names are repeated (e.g.,
|
||||||
:status). */
|
:status). */
|
||||||
static nghttp2_hd_entry static_table[] = {
|
static nghttp2_hd_entry static_table[] = {
|
||||||
MAKE_STATIC_ENT(":authority", "", 0),
|
MAKE_STATIC_ENT(":authority", "", 0, 3153725150u),
|
||||||
MAKE_STATIC_ENT(":method", "GET", 1),
|
MAKE_STATIC_ENT(":method", "GET", 1, 695666056u),
|
||||||
MAKE_STATIC_ENT(":method", "POST", 1),
|
MAKE_STATIC_ENT(":method", "POST", 1, 695666056u),
|
||||||
MAKE_STATIC_ENT(":path", "/", 3),
|
MAKE_STATIC_ENT(":path", "/", 3, 3292848686u),
|
||||||
MAKE_STATIC_ENT(":path", "/index.html", 3),
|
MAKE_STATIC_ENT(":path", "/index.html", 3, 3292848686u),
|
||||||
MAKE_STATIC_ENT(":scheme", "http", 5),
|
MAKE_STATIC_ENT(":scheme", "http", 5, 2510477674u),
|
||||||
MAKE_STATIC_ENT(":scheme", "https", 5),
|
MAKE_STATIC_ENT(":scheme", "https", 5, 2510477674u),
|
||||||
MAKE_STATIC_ENT(":status", "200", 7),
|
MAKE_STATIC_ENT(":status", "200", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "204", 7),
|
MAKE_STATIC_ENT(":status", "204", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "206", 7),
|
MAKE_STATIC_ENT(":status", "206", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "304", 7),
|
MAKE_STATIC_ENT(":status", "304", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "400", 7),
|
MAKE_STATIC_ENT(":status", "400", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "404", 7),
|
MAKE_STATIC_ENT(":status", "404", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT(":status", "500", 7),
|
MAKE_STATIC_ENT(":status", "500", 7, 4000288983u),
|
||||||
MAKE_STATIC_ENT("accept-charset", "", 14),
|
MAKE_STATIC_ENT("accept-charset", "", 14, 3664010344u),
|
||||||
MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15),
|
MAKE_STATIC_ENT("accept-encoding", "gzip, deflate", 15, 3379649177u),
|
||||||
MAKE_STATIC_ENT("accept-language", "", 16),
|
MAKE_STATIC_ENT("accept-language", "", 16, 1979086614u),
|
||||||
MAKE_STATIC_ENT("accept-ranges", "", 17),
|
MAKE_STATIC_ENT("accept-ranges", "", 17, 1713753958u),
|
||||||
MAKE_STATIC_ENT("accept", "", 18),
|
MAKE_STATIC_ENT("accept", "", 18, 136609321u),
|
||||||
MAKE_STATIC_ENT("access-control-allow-origin", "", 19),
|
MAKE_STATIC_ENT("access-control-allow-origin", "", 19, 2710797292u),
|
||||||
MAKE_STATIC_ENT("age", "", 20),
|
MAKE_STATIC_ENT("age", "", 20, 742476188u),
|
||||||
MAKE_STATIC_ENT("allow", "", 21),
|
MAKE_STATIC_ENT("allow", "", 21, 2930878514u),
|
||||||
MAKE_STATIC_ENT("authorization", "", 22),
|
MAKE_STATIC_ENT("authorization", "", 22, 2436257726u),
|
||||||
MAKE_STATIC_ENT("cache-control", "", 23),
|
MAKE_STATIC_ENT("cache-control", "", 23, 1355326669u),
|
||||||
MAKE_STATIC_ENT("content-disposition", "", 24),
|
MAKE_STATIC_ENT("content-disposition", "", 24, 3889184348u),
|
||||||
MAKE_STATIC_ENT("content-encoding", "", 25),
|
MAKE_STATIC_ENT("content-encoding", "", 25, 65203592u),
|
||||||
MAKE_STATIC_ENT("content-language", "", 26),
|
MAKE_STATIC_ENT("content-language", "", 26, 24973587u),
|
||||||
MAKE_STATIC_ENT("content-length", "", 27),
|
MAKE_STATIC_ENT("content-length", "", 27, 1308181789u),
|
||||||
MAKE_STATIC_ENT("content-location", "", 28),
|
MAKE_STATIC_ENT("content-location", "", 28, 2302364718u),
|
||||||
MAKE_STATIC_ENT("content-range", "", 29),
|
MAKE_STATIC_ENT("content-range", "", 29, 3555523146u),
|
||||||
MAKE_STATIC_ENT("content-type", "", 30),
|
MAKE_STATIC_ENT("content-type", "", 30, 4244048277u),
|
||||||
MAKE_STATIC_ENT("cookie", "", 31),
|
MAKE_STATIC_ENT("cookie", "", 31, 2007449791u),
|
||||||
MAKE_STATIC_ENT("date", "", 32),
|
MAKE_STATIC_ENT("date", "", 32, 3564297305u),
|
||||||
MAKE_STATIC_ENT("etag", "", 33),
|
MAKE_STATIC_ENT("etag", "", 33, 113792960u),
|
||||||
MAKE_STATIC_ENT("expect", "", 34),
|
MAKE_STATIC_ENT("expect", "", 34, 2530896728u),
|
||||||
MAKE_STATIC_ENT("expires", "", 35),
|
MAKE_STATIC_ENT("expires", "", 35, 1049544579u),
|
||||||
MAKE_STATIC_ENT("from", "", 36),
|
MAKE_STATIC_ENT("from", "", 36, 2513272949u),
|
||||||
MAKE_STATIC_ENT("host", "", 37),
|
MAKE_STATIC_ENT("host", "", 37, 2952701295u),
|
||||||
MAKE_STATIC_ENT("if-match", "", 38),
|
MAKE_STATIC_ENT("if-match", "", 38, 3597694698u),
|
||||||
MAKE_STATIC_ENT("if-modified-since", "", 39),
|
MAKE_STATIC_ENT("if-modified-since", "", 39, 2213050793u),
|
||||||
MAKE_STATIC_ENT("if-none-match", "", 40),
|
MAKE_STATIC_ENT("if-none-match", "", 40, 2536202615u),
|
||||||
MAKE_STATIC_ENT("if-range", "", 41),
|
MAKE_STATIC_ENT("if-range", "", 41, 2340978238u),
|
||||||
MAKE_STATIC_ENT("if-unmodified-since", "", 42),
|
MAKE_STATIC_ENT("if-unmodified-since", "", 42, 3794814858u),
|
||||||
MAKE_STATIC_ENT("last-modified", "", 43),
|
MAKE_STATIC_ENT("last-modified", "", 43, 3226950251u),
|
||||||
MAKE_STATIC_ENT("link", "", 44),
|
MAKE_STATIC_ENT("link", "", 44, 232457833u),
|
||||||
MAKE_STATIC_ENT("location", "", 45),
|
MAKE_STATIC_ENT("location", "", 45, 200649126u),
|
||||||
MAKE_STATIC_ENT("max-forwards", "", 46),
|
MAKE_STATIC_ENT("max-forwards", "", 46, 1826162134u),
|
||||||
MAKE_STATIC_ENT("proxy-authenticate", "", 47),
|
MAKE_STATIC_ENT("proxy-authenticate", "", 47, 2709445359u),
|
||||||
MAKE_STATIC_ENT("proxy-authorization", "", 48),
|
MAKE_STATIC_ENT("proxy-authorization", "", 48, 2686392507u),
|
||||||
MAKE_STATIC_ENT("range", "", 49),
|
MAKE_STATIC_ENT("range", "", 49, 4208725202u),
|
||||||
MAKE_STATIC_ENT("referer", "", 50),
|
MAKE_STATIC_ENT("referer", "", 50, 3969579366u),
|
||||||
MAKE_STATIC_ENT("refresh", "", 51),
|
MAKE_STATIC_ENT("refresh", "", 51, 3572655668u),
|
||||||
MAKE_STATIC_ENT("retry-after", "", 52),
|
MAKE_STATIC_ENT("retry-after", "", 52, 3336180598u),
|
||||||
MAKE_STATIC_ENT("server", "", 53),
|
MAKE_STATIC_ENT("server", "", 53, 1085029842u),
|
||||||
MAKE_STATIC_ENT("set-cookie", "", 54),
|
MAKE_STATIC_ENT("set-cookie", "", 54, 1848371000u),
|
||||||
MAKE_STATIC_ENT("strict-transport-security", "", 55),
|
MAKE_STATIC_ENT("strict-transport-security", "", 55, 4138147361u),
|
||||||
MAKE_STATIC_ENT("transfer-encoding", "", 56),
|
MAKE_STATIC_ENT("transfer-encoding", "", 56, 3719590988u),
|
||||||
MAKE_STATIC_ENT("user-agent", "", 57),
|
MAKE_STATIC_ENT("user-agent", "", 57, 606444526u),
|
||||||
MAKE_STATIC_ENT("vary", "", 58),
|
MAKE_STATIC_ENT("vary", "", 58, 1085005381u),
|
||||||
MAKE_STATIC_ENT("via", "", 59),
|
MAKE_STATIC_ENT("via", "", 59, 1762798611u),
|
||||||
MAKE_STATIC_ENT("www-authenticate", "", 60),
|
MAKE_STATIC_ENT("www-authenticate", "", 60, 779865858u),
|
||||||
};
|
};
|
||||||
|
|
||||||
static int memeq(const void *s1, const void *s2, size_t n) {
|
static int memeq(const void *s1, const void *s2, size_t n) {
|
||||||
|
@ -540,6 +540,8 @@ int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t flags, uint8_t *name,
|
||||||
ent->token = token;
|
ent->token = token;
|
||||||
ent->ref = 1;
|
ent->ref = 1;
|
||||||
ent->flags = flags;
|
ent->flags = flags;
|
||||||
|
ent->next = NULL;
|
||||||
|
ent->hash = 0;
|
||||||
|
|
||||||
return 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,
|
static int hd_ringbuf_init(nghttp2_hd_ringbuf *ringbuf, size_t bufsize,
|
||||||
nghttp2_mem *mem) {
|
nghttp2_mem *mem) {
|
||||||
size_t size;
|
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->hd_table_bufsize = 0;
|
||||||
|
context->next_seq = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -677,6 +772,8 @@ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hd_map_init(&deflater->map);
|
||||||
|
|
||||||
if (deflate_hd_table_bufsize_max < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
|
if (deflate_hd_table_bufsize_max < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) {
|
||||||
deflater->notify_table_size_change = 1;
|
deflater->notify_table_size_change = 1;
|
||||||
deflater->ctx.hd_table_bufsize_max = deflate_hd_table_bufsize_max;
|
deflater->ctx.hd_table_bufsize_max = deflate_hd_table_bufsize_max;
|
||||||
|
@ -1081,10 +1178,10 @@ static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context,
|
static nghttp2_hd_entry *
|
||||||
const nghttp2_nv *nv,
|
add_hd_table_incremental(nghttp2_hd_context *context, const nghttp2_nv *nv,
|
||||||
int token,
|
int token, uint8_t entry_flags, nghttp2_hd_map *map,
|
||||||
uint8_t entry_flags) {
|
uint32_t hash) {
|
||||||
int rv;
|
int rv;
|
||||||
nghttp2_hd_entry *new_ent;
|
nghttp2_hd_entry *new_ent;
|
||||||
size_t room;
|
size_t room;
|
||||||
|
@ -1105,6 +1202,9 @@ static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context,
|
||||||
ent->nv.name, ent->nv.value));
|
ent->nv.name, ent->nv.value));
|
||||||
|
|
||||||
hd_ringbuf_pop_back(&context->hd_table);
|
hd_ringbuf_pop_back(&context->hd_table);
|
||||||
|
if (map) {
|
||||||
|
hd_map_remove(map, ent);
|
||||||
|
}
|
||||||
if (--ent->ref == 0) {
|
if (--ent->ref == 0) {
|
||||||
nghttp2_hd_entry_free(ent, mem);
|
nghttp2_hd_entry_free(ent, mem);
|
||||||
nghttp2_mem_free(mem, ent);
|
nghttp2_mem_free(mem, ent);
|
||||||
|
@ -1152,19 +1252,21 @@ static nghttp2_hd_entry *add_hd_table_incremental(nghttp2_hd_context *context,
|
||||||
return NULL;
|
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;
|
context->hd_table_bufsize += room;
|
||||||
}
|
}
|
||||||
return new_ent;
|
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 {
|
typedef struct {
|
||||||
ssize_t index;
|
ssize_t index;
|
||||||
/* Nonzero if both name and value are matched. */
|
/* Nonzero if both name and value are matched. */
|
||||||
|
@ -1194,9 +1296,11 @@ static search_result search_static_table(const nghttp2_nv *nv, int token,
|
||||||
|
|
||||||
static search_result search_hd_table(nghttp2_hd_context *context,
|
static search_result search_hd_table(nghttp2_hd_context *context,
|
||||||
const nghttp2_nv *nv, int token,
|
const nghttp2_nv *nv, int token,
|
||||||
int indexing_mode) {
|
int indexing_mode, nghttp2_hd_map *map,
|
||||||
|
uint32_t hash) {
|
||||||
search_result res = {-1, 0};
|
search_result res = {-1, 0};
|
||||||
size_t i;
|
nghttp2_hd_entry *ent;
|
||||||
|
int exact_match;
|
||||||
|
|
||||||
if (token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
|
if (token >= 0 && token <= NGHTTP2_TOKEN_WWW_AUTHENTICATE) {
|
||||||
res = search_static_table(nv, token, indexing_mode);
|
res = search_static_table(nv, token, indexing_mode);
|
||||||
|
@ -1205,27 +1309,27 @@ static search_result search_hd_table(nghttp2_hd_context *context,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < context->hd_table.len; ++i) {
|
exact_match = 0;
|
||||||
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, i);
|
ent = hd_map_find(map, &exact_match, nv, token, hash);
|
||||||
if (ent->token != token || (token == -1 && !name_eq(&ent->nv, nv))) {
|
if (ent == NULL) {
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (res.index == -1) {
|
|
||||||
res.index = (ssize_t)(i + NGHTTP2_STATIC_TABLE_LENGTH);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.index != -1 && !exact_match) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.index = context->next_seq - 1 - ent->seq + NGHTTP2_STATIC_TABLE_LENGTH;
|
||||||
|
|
||||||
|
if (exact_match) {
|
||||||
|
res.name_value_match = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
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;
|
nghttp2_mem *mem;
|
||||||
|
|
||||||
mem = context->mem;
|
mem = context->mem;
|
||||||
|
@ -1236,6 +1340,9 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context) {
|
||||||
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, idx);
|
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.namelen, ent->nv.valuelen);
|
||||||
hd_ringbuf_pop_back(&context->hd_table);
|
hd_ringbuf_pop_back(&context->hd_table);
|
||||||
|
if (map) {
|
||||||
|
hd_map_remove(map, ent);
|
||||||
|
}
|
||||||
if (--ent->ref == 0) {
|
if (--ent->ref == 0) {
|
||||||
nghttp2_hd_entry_free(ent, mem);
|
nghttp2_hd_entry_free(ent, mem);
|
||||||
nghttp2_mem_free(mem, ent);
|
nghttp2_mem_free(mem, ent);
|
||||||
|
@ -1255,7 +1362,7 @@ int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
|
||||||
|
|
||||||
deflater->notify_table_size_change = 1;
|
deflater->notify_table_size_change = 1;
|
||||||
|
|
||||||
hd_context_shrink_table_size(&deflater->ctx);
|
hd_context_shrink_table_size(&deflater->ctx, &deflater->map);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1272,7 +1379,7 @@ int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
|
||||||
inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE;
|
inflater->state = NGHTTP2_HD_STATE_EXPECT_TABLE_SIZE;
|
||||||
inflater->settings_hd_table_bufsize_max = settings_hd_table_bufsize_max;
|
inflater->settings_hd_table_bufsize_max = settings_hd_table_bufsize_max;
|
||||||
inflater->ctx.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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1317,12 +1424,18 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||||
int indexing_mode;
|
int indexing_mode;
|
||||||
int token;
|
int token;
|
||||||
nghttp2_mem *mem;
|
nghttp2_mem *mem;
|
||||||
|
uint32_t hash;
|
||||||
|
|
||||||
DEBUGF(fprintf(stderr, "deflatehd: deflating %s: %s\n", nv->name, nv->value));
|
DEBUGF(fprintf(stderr, "deflatehd: deflating %s: %s\n", nv->name, nv->value));
|
||||||
|
|
||||||
mem = deflater->ctx.mem;
|
mem = deflater->ctx.mem;
|
||||||
|
|
||||||
token = lookup_token(nv->name, nv->namelen);
|
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
|
/* Don't index authorization header field since it may contain low
|
||||||
entropy secret data (e.g., id/password). Also cookie header
|
entropy secret data (e.g., id/password). Also cookie header
|
||||||
|
@ -1335,7 +1448,8 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||||
? NGHTTP2_HD_NEVER_INDEXING
|
? NGHTTP2_HD_NEVER_INDEXING
|
||||||
: hd_deflate_decide_indexing(deflater, nv, token);
|
: 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;
|
idx = res.index;
|
||||||
|
|
||||||
|
@ -1362,11 +1476,13 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
|
||||||
nv_indname = *nv;
|
nv_indname = *nv;
|
||||||
nv_indname.name = nghttp2_hd_table_get(&deflater->ctx, idx)->nv.name;
|
nv_indname.name = nghttp2_hd_table_get(&deflater->ctx, idx)->nv.name;
|
||||||
new_ent = add_hd_table_incremental(&deflater->ctx, &nv_indname, token,
|
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 {
|
} else {
|
||||||
new_ent = add_hd_table_incremental(&deflater->ctx, nv, token,
|
new_ent = add_hd_table_incremental(&deflater->ctx, nv, token,
|
||||||
NGHTTP2_HD_FLAG_NAME_ALLOC |
|
NGHTTP2_HD_FLAG_NAME_ALLOC |
|
||||||
NGHTTP2_HD_FLAG_VALUE_ALLOC);
|
NGHTTP2_HD_FLAG_VALUE_ALLOC,
|
||||||
|
&deflater->map, hash);
|
||||||
}
|
}
|
||||||
if (!new_ent) {
|
if (!new_ent) {
|
||||||
return NGHTTP2_ERR_HEADER_COMP;
|
return NGHTTP2_ERR_HEADER_COMP;
|
||||||
|
@ -1816,8 +1932,9 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
|
||||||
management. */
|
management. */
|
||||||
ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
|
ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
|
||||||
|
|
||||||
new_ent = add_hd_table_incremental(
|
new_ent = add_hd_table_incremental(&inflater->ctx, &nv,
|
||||||
&inflater->ctx, &nv, lookup_token(nv.name, nv.namelen), ent_flags);
|
lookup_token(nv.name, nv.namelen),
|
||||||
|
ent_flags, NULL, 0);
|
||||||
|
|
||||||
if (new_ent) {
|
if (new_ent) {
|
||||||
emit_indexed_header(nv_out, token_out, new_ent);
|
emit_indexed_header(nv_out, token_out, new_ent);
|
||||||
|
@ -1892,7 +2009,7 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
|
||||||
}
|
}
|
||||||
|
|
||||||
new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->token,
|
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. */
|
/* At this point, ent_name might be deleted. */
|
||||||
|
|
||||||
|
@ -2021,7 +2138,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
|
||||||
}
|
}
|
||||||
DEBUGF(fprintf(stderr, "inflatehd: table_size=%zu\n", inflater->left));
|
DEBUGF(fprintf(stderr, "inflatehd: table_size=%zu\n", inflater->left));
|
||||||
inflater->ctx.hd_table_bufsize_max = 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;
|
inflater->state = NGHTTP2_HD_STATE_INFLATE_START;
|
||||||
break;
|
break;
|
||||||
case NGHTTP2_HD_STATE_READ_INDEX: {
|
case NGHTTP2_HD_STATE_READ_INDEX: {
|
||||||
|
|
|
@ -126,15 +126,25 @@ typedef enum {
|
||||||
NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 3
|
NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 3
|
||||||
} nghttp2_hd_flags;
|
} nghttp2_hd_flags;
|
||||||
|
|
||||||
typedef struct {
|
struct nghttp2_hd_entry;
|
||||||
|
typedef struct nghttp2_hd_entry nghttp2_hd_entry;
|
||||||
|
|
||||||
|
struct nghttp2_hd_entry {
|
||||||
nghttp2_nv nv;
|
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
|
/* nghttp2_token value for nv.name. It could be -1 if we have no
|
||||||
token for that header field name. */
|
token for that header field name. */
|
||||||
int token;
|
int token;
|
||||||
/* Reference count */
|
/* Reference count */
|
||||||
uint8_t ref;
|
uint8_t ref;
|
||||||
uint8_t flags;
|
uint8_t flags;
|
||||||
} nghttp2_hd_entry;
|
};
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nghttp2_hd_entry **buffer;
|
nghttp2_hd_entry **buffer;
|
||||||
|
@ -183,14 +193,21 @@ typedef struct {
|
||||||
size_t hd_table_bufsize;
|
size_t hd_table_bufsize;
|
||||||
/* The effective header table size. */
|
/* The effective header table size. */
|
||||||
size_t hd_table_bufsize_max;
|
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
|
/* If inflate/deflate error occurred, this value is set to 1 and
|
||||||
further invocation of inflate/deflate will fail with
|
further invocation of inflate/deflate will fail with
|
||||||
NGHTTP2_ERR_HEADER_COMP. */
|
NGHTTP2_ERR_HEADER_COMP. */
|
||||||
uint8_t bad;
|
uint8_t bad;
|
||||||
} nghttp2_hd_context;
|
} nghttp2_hd_context;
|
||||||
|
|
||||||
|
#define HD_MAP_SIZE 128
|
||||||
|
|
||||||
|
typedef struct { nghttp2_hd_entry *table[HD_MAP_SIZE]; } nghttp2_hd_map;
|
||||||
|
|
||||||
struct nghttp2_hd_deflater {
|
struct nghttp2_hd_deflater {
|
||||||
nghttp2_hd_context ctx;
|
nghttp2_hd_context ctx;
|
||||||
|
nghttp2_hd_map map;
|
||||||
/* The upper limit of the header table size the deflater accepts. */
|
/* The upper limit of the header table size the deflater accepts. */
|
||||||
size_t deflate_hd_table_bufsize_max;
|
size_t deflate_hd_table_bufsize_max;
|
||||||
/* Minimum header table size notified in the next context update */
|
/* Minimum header table size notified in the next context update */
|
||||||
|
|
|
@ -10,6 +10,17 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import re, sys
|
import re, sys
|
||||||
|
|
||||||
|
def hd_map_hash(name):
|
||||||
|
h = 2166136261
|
||||||
|
|
||||||
|
# FNV hash variant: http://isthe.com/chongo/tech/comp/fnv/
|
||||||
|
for c in name:
|
||||||
|
h ^= ord(c)
|
||||||
|
h *= 16777619
|
||||||
|
h &= 0xffffffff
|
||||||
|
|
||||||
|
return h
|
||||||
|
|
||||||
entries = []
|
entries = []
|
||||||
for line in sys.stdin:
|
for line in sys.stdin:
|
||||||
m = re.match(r'(\d+)\s+(\S+)\s+(\S.*)?', line)
|
m = re.match(r'(\d+)\s+(\S+)\s+(\S.*)?', line)
|
||||||
|
@ -21,6 +32,6 @@ idx = 0
|
||||||
for i, ent in enumerate(entries):
|
for i, ent in enumerate(entries):
|
||||||
if entries[idx][1] != ent[1]:
|
if entries[idx][1] != ent[1]:
|
||||||
idx = i
|
idx = i
|
||||||
print 'MAKE_STATIC_ENT("{}", "{}", {}),'\
|
print 'MAKE_STATIC_ENT("{}", "{}", {}, {}u),'\
|
||||||
.format(ent[1], ent[2], entries[idx][0] - 1)
|
.format(ent[1], ent[2], entries[idx][0] - 1, hd_map_hash(ent[1]))
|
||||||
print '};'
|
print '};'
|
||||||
|
|
Loading…
Reference in New Issue