nghttp2_hd: Share static table globally

This commit is contained in:
Tatsuhiro Tsujikawa 2013-10-24 22:09:40 +09:00
parent 5a81e03497
commit 0c3cb104e9
3 changed files with 84 additions and 109 deletions

View File

@ -30,69 +30,76 @@
#include "nghttp2_frame.h" #include "nghttp2_frame.h"
#include "nghttp2_helper.h" #include "nghttp2_helper.h"
static const char *static_table[] = { /* Make scalar initialization form of nghttp2_nv */
/* 0 */ ":authority", "", #define MAKE_NV(N, V) \
/* 1 */ ":method", "GET", { { (uint8_t*)N, (uint8_t*)V, sizeof(N) - 1, sizeof(V) - 1 }, \
/* 2 */ ":method", "POST", 1, NGHTTP2_HD_FLAG_NONE }
/* 3 */ ":path", "/",
/* 4 */ ":path", "/index.html", static nghttp2_hd_entry static_table[] = {
/* 5 */ ":scheme", "http", /* 0 */ MAKE_NV(":authority", ""),
/* 6 */ ":scheme", "https", /* 1 */ MAKE_NV(":method", "GET"),
/* 7 */ ":status", "200", /* 2 */ MAKE_NV(":method", "POST"),
/* 8 */ ":status", "500", /* 3 */ MAKE_NV(":path", "/"),
/* 9 */ ":status", "404", /* 4 */ MAKE_NV(":path", "/index.html"),
/* 10 */ ":status", "403", /* 5 */ MAKE_NV(":scheme", "http"),
/* 11 */ ":status", "400", /* 6 */ MAKE_NV(":scheme", "https"),
/* 12 */ ":status", "401", /* 7 */ MAKE_NV(":status", "200"),
/* 13 */ "accept-charset", "", /* 8 */ MAKE_NV(":status", "500"),
/* 14 */ "accept-encoding", "", /* 9 */ MAKE_NV(":status", "404"),
/* 15 */ "accept-language", "", /* 10 */ MAKE_NV(":status", "403"),
/* 16 */ "accept-ranges", "", /* 11 */ MAKE_NV(":status", "400"),
/* 17 */ "accept", "", /* 12 */ MAKE_NV(":status", "401"),
/* 18 */ "access-control-allow-origin", "", /* 13 */ MAKE_NV("accept-charset", ""),
/* 19 */ "age", "", /* 14 */ MAKE_NV("accept-encoding", ""),
/* 20 */ "allow", "", /* 15 */ MAKE_NV("accept-language", ""),
/* 21 */ "authorization", "", /* 16 */ MAKE_NV("accept-ranges", ""),
/* 22 */ "cache-control", "", /* 17 */ MAKE_NV("accept", ""),
/* 23 */ "content-disposition", "", /* 18 */ MAKE_NV("access-control-allow-origin", ""),
/* 24 */ "content-encoding", "", /* 19 */ MAKE_NV("age", ""),
/* 25 */ "content-language", "", /* 20 */ MAKE_NV("allow", ""),
/* 26 */ "content-length", "", /* 21 */ MAKE_NV("authorization", ""),
/* 27 */ "content-location", "", /* 22 */ MAKE_NV("cache-control", ""),
/* 28 */ "content-range", "", /* 23 */ MAKE_NV("content-disposition", ""),
/* 29 */ "content-type", "", /* 24 */ MAKE_NV("content-encoding", ""),
/* 30 */ "cookie", "", /* 25 */ MAKE_NV("content-language", ""),
/* 31 */ "date", "", /* 26 */ MAKE_NV("content-length", ""),
/* 32 */ "etag", "", /* 27 */ MAKE_NV("content-location", ""),
/* 33 */ "expect", "", /* 28 */ MAKE_NV("content-range", ""),
/* 34 */ "expires", "", /* 29 */ MAKE_NV("content-type", ""),
/* 35 */ "from", "", /* 30 */ MAKE_NV("cookie", ""),
/* 36 */ "if-match", "", /* 31 */ MAKE_NV("date", ""),
/* 37 */ "if-modified-since", "", /* 32 */ MAKE_NV("etag", ""),
/* 38 */ "if-none-match", "", /* 33 */ MAKE_NV("expect", ""),
/* 39 */ "if-range", "", /* 34 */ MAKE_NV("expires", ""),
/* 40 */ "if-unmodified-since", "", /* 35 */ MAKE_NV("from", ""),
/* 41 */ "last-modified", "", /* 36 */ MAKE_NV("if-match", ""),
/* 42 */ "link", "", /* 37 */ MAKE_NV("if-modified-since", ""),
/* 43 */ "location", "", /* 38 */ MAKE_NV("if-none-match", ""),
/* 44 */ "max-forwards", "", /* 39 */ MAKE_NV("if-range", ""),
/* 45 */ "proxy-authenticate", "", /* 40 */ MAKE_NV("if-unmodified-since", ""),
/* 46 */ "proxy-authorization", "", /* 41 */ MAKE_NV("last-modified", ""),
/* 47 */ "range", "", /* 42 */ MAKE_NV("link", ""),
/* 48 */ "referer", "", /* 43 */ MAKE_NV("location", ""),
/* 49 */ "refresh", "", /* 44 */ MAKE_NV("max-forwards", ""),
/* 50 */ "retry-after", "", /* 45 */ MAKE_NV("proxy-authenticate", ""),
/* 51 */ "server", "", /* 46 */ MAKE_NV("proxy-authorization", ""),
/* 52 */ "set-cookie", "", /* 47 */ MAKE_NV("range", ""),
/* 53 */ "strict-transport-security", "", /* 48 */ MAKE_NV("referer", ""),
/* 54 */ "transfer-encoding", "", /* 49 */ MAKE_NV("refresh", ""),
/* 55 */ "user-agent", "", /* 50 */ MAKE_NV("retry-after", ""),
/* 56 */ "vary", "", /* 51 */ MAKE_NV("server", ""),
/* 57 */ "via", "", /* 52 */ MAKE_NV("set-cookie", ""),
/* 58 */ "www-authenticate", "", /* 53 */ MAKE_NV("strict-transport-security", ""),
NULL /* 54 */ MAKE_NV("transfer-encoding", ""),
/* 55 */ MAKE_NV("user-agent", ""),
/* 56 */ MAKE_NV("vary", ""),
/* 57 */ MAKE_NV("via", ""),
/* 58 */ MAKE_NV("www-authenticate", "")
}; };
const static size_t STATIC_TABLE_LENGTH =
sizeof(static_table)/sizeof(static_table[0]);
typedef struct { typedef struct {
nghttp2_nv *nva; nghttp2_nv *nva;
size_t nvacap; size_t nvacap;
@ -215,7 +222,6 @@ static int nghttp2_hd_context_init(nghttp2_hd_context *context,
nghttp2_hd_side side, nghttp2_hd_side side,
size_t hd_table_bufsize_max) size_t hd_table_bufsize_max)
{ {
size_t i;
int rv; int rv;
context->role = role; context->role = role;
context->side = side; context->side = side;
@ -226,29 +232,6 @@ static int nghttp2_hd_context_init(nghttp2_hd_context *context,
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }
for(i = 0; static_table[i]; i += 2);
context->static_hd_table = malloc(sizeof(nghttp2_hd_entry*)*(i / 2 + 1));
if(context->static_hd_table == NULL) {
goto fail;
}
context->static_hd_table[i / 2] = NULL;
for(i = 0; static_table[i]; i += 2) {
nghttp2_hd_entry *p = malloc(sizeof(nghttp2_hd_entry));
if(p == NULL) {
size_t j;
for(j = 0; j < i / 2; ++j) {
--context->static_hd_table[j]->ref;
nghttp2_hd_entry_free(context->static_hd_table[j]);
free(context->static_hd_table[j]);
}
goto fail;
}
nghttp2_hd_entry_init(p, NGHTTP2_HD_FLAG_NONE,
(uint8_t*)static_table[i], strlen(static_table[i]),
(uint8_t*)static_table[i + 1],
strlen(static_table[i+1]));
context->static_hd_table[i / 2] = p;
}
if(role == NGHTTP2_HD_ROLE_INFLATE) { if(role == NGHTTP2_HD_ROLE_INFLATE) {
context->emit_set = malloc(sizeof(nghttp2_hd_entry*)* context->emit_set = malloc(sizeof(nghttp2_hd_entry*)*
@ -277,7 +260,6 @@ static int nghttp2_hd_context_init(nghttp2_hd_context *context,
context->hd_table_bufsize = 0; context->hd_table_bufsize = 0;
return 0; return 0;
fail: fail:
free(context->static_hd_table);
free(context->buf_track); free(context->buf_track);
free(context->emit_set); free(context->emit_set);
nghttp2_hd_ringbuf_free(&context->hd_table); nghttp2_hd_ringbuf_free(&context->hd_table);
@ -330,13 +312,6 @@ static void nghttp2_hd_context_free(nghttp2_hd_context *context)
free(context->emit_set); free(context->emit_set);
nghttp2_hd_ringbuf_free(&context->hd_table); nghttp2_hd_ringbuf_free(&context->hd_table);
for(i = 0; context->static_hd_table[i]; ++i) {
--context->static_hd_table[i]->ref;
nghttp2_hd_entry_free(context->static_hd_table[i]);
free(context->static_hd_table[i]);
}
free(context->static_hd_table);
} }
void nghttp2_hd_deflate_free(nghttp2_hd_context *deflater) void nghttp2_hd_deflate_free(nghttp2_hd_context *deflater)
@ -745,8 +720,8 @@ static ssize_t find_in_hd_table(nghttp2_hd_context *context, nghttp2_nv *nv)
return i; return i;
} }
} }
for(i = 0; context->static_hd_table[i]; ++i) { for(i = 0; i < STATIC_TABLE_LENGTH; ++i) {
nghttp2_hd_entry *ent = context->static_hd_table[i]; nghttp2_hd_entry *ent = &static_table[i];
if(nghttp2_nv_equal(&ent->nv, nv)) { if(nghttp2_nv_equal(&ent->nv, nv)) {
return context->hd_table.len + i; return context->hd_table.len + i;
} }
@ -765,8 +740,8 @@ static ssize_t find_name_in_hd_table(nghttp2_hd_context *context,
return i; return i;
} }
} }
for(i = 0; context->static_hd_table[i]; ++i) { for(i = 0; i < STATIC_TABLE_LENGTH; ++i) {
nghttp2_hd_entry *ent = context->static_hd_table[i]; nghttp2_hd_entry *ent = &static_table[i];
if(ent->nv.namelen == nv->namelen && if(ent->nv.namelen == nv->namelen &&
memcmp(ent->nv.name, nv->name, nv->namelen) == 0) { memcmp(ent->nv.name, nv->name, nv->namelen) == 0) {
return context->hd_table.len + i; return context->hd_table.len + i;
@ -775,13 +750,19 @@ static ssize_t find_name_in_hd_table(nghttp2_hd_context *context,
return -1; return -1;
} }
static int check_index_range(nghttp2_hd_context *context, size_t index)
{
return index < context->hd_table.len + STATIC_TABLE_LENGTH;
}
nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context, nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
size_t index) size_t index)
{ {
assert(check_index_range(context, index));
if(index < context->hd_table.len) { if(index < context->hd_table.len) {
return nghttp2_hd_ringbuf_get(&context->hd_table, index); return nghttp2_hd_ringbuf_get(&context->hd_table, index);
} else { } else {
return context->static_hd_table[index - context->hd_table.len]; return &static_table[index - context->hd_table.len];
} }
} }
@ -971,12 +952,6 @@ static int inflater_post_process_hd_entry(nghttp2_hd_context *inflater,
return 0; return 0;
} }
static int check_index_range(nghttp2_hd_context *context, size_t index)
{
return index < context->hd_table.len +
sizeof(static_table)/sizeof(static_table[0])/2;
}
static ssize_t inflate_decode(uint8_t **dest_ptr, uint8_t *in, size_t inlen, static ssize_t inflate_decode(uint8_t **dest_ptr, uint8_t *in, size_t inlen,
nghttp2_hd_side side) nghttp2_hd_side side)
{ {

View File

@ -83,9 +83,8 @@ typedef struct {
} nghttp2_hd_ringbuf; } nghttp2_hd_ringbuf;
typedef struct { typedef struct {
/* Header table */ /* dynamic header table */
nghttp2_hd_ringbuf hd_table; nghttp2_hd_ringbuf hd_table;
nghttp2_hd_entry **static_hd_table;
/* Holding emitted entry in deflating header block to retain /* Holding emitted entry in deflating header block to retain
reference count. */ reference count. */
nghttp2_hd_entry **emit_set; nghttp2_hd_entry **emit_set;

View File

@ -3,6 +3,7 @@ import re, sys
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)
print '/* {} */ "{}", "{}",'.format(m.group(1), print '/* {} */ MAKE_NV("{}", "{}"),'\
m.group(2), .format(m.group(1),
m.group(3) if m.group(3) else '') m.group(2),
m.group(3) if m.group(3) else '')