Remove HPACK reference set

This commit is contained in:
Tatsuhiro Tsujikawa 2014-07-12 18:47:55 +09:00
parent 63398f30dd
commit 38bfbffb1b
11 changed files with 29 additions and 395 deletions

View File

@ -2819,18 +2819,6 @@ int nghttp2_hd_deflate_new(nghttp2_hd_deflater **deflater_ptr,
*/ */
void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater); void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater);
/**
* @function
*
* Sets the availability of reference set in the |deflater|. If
* |no_refset| is nonzero, the deflater will first emit "Reference Set
* Emptying" in the each subsequent invocation of
* `nghttp2_hd_deflate_hd()` to clear up reference set. By default,
* the deflater uses reference set.
*/
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset);
/** /**
* @function * @function
* *

View File

@ -318,7 +318,6 @@ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }
deflater->no_refset = 0;
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;
@ -346,7 +345,6 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater)
inflater->ent_keep = NULL; inflater->ent_keep = NULL;
inflater->nv_keep = NULL; inflater->nv_keep = NULL;
inflater->end_headers_index = 0;
inflater->opcode = NGHTTP2_HD_OPCODE_NONE; inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
inflater->state = NGHTTP2_HD_STATE_OPCODE; inflater->state = NGHTTP2_HD_STATE_OPCODE;
@ -400,12 +398,6 @@ void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater)
hd_context_free(&inflater->ctx); hd_context_free(&inflater->ctx);
} }
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset)
{
deflater->no_refset = no_refset;
}
static size_t entry_room(size_t namelen, size_t valuelen) static size_t entry_room(size_t namelen, size_t valuelen)
{ {
return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen; return NGHTTP2_HD_ENTRY_OVERHEAD + namelen + valuelen;
@ -418,10 +410,8 @@ static int emit_indexed_header(nghttp2_nv *nv_out, nghttp2_hd_entry *ent)
DEBUGF(fprintf(stderr, ": ")); DEBUGF(fprintf(stderr, ": "));
DEBUGF(fwrite(ent->nv.value, ent->nv.valuelen, 1, stderr)); DEBUGF(fwrite(ent->nv.value, ent->nv.valuelen, 1, stderr));
DEBUGF(fprintf(stderr, "\n")); DEBUGF(fprintf(stderr, "\n"));
/* ent->ref may be 0. This happens if the careless stupid encoder /* ent->ref may be 0. This happens if the encoder emits literal
emits literal block larger than header table capacity with block larger than header table capacity with indexing. */
indexing. */
ent->flags |= NGHTTP2_HD_FLAG_EMIT;
*nv_out = ent->nv; *nv_out = ent->nv;
return 0; return 0;
} }
@ -561,20 +551,6 @@ static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *final,
return in + 1 - start; return in + 1 - start;
} }
static int emit_clear_refset(nghttp2_bufs *bufs)
{
int rv;
DEBUGF(fprintf(stderr, "deflatehd: emit clear refset\n"));
rv = nghttp2_bufs_addb(bufs, 0x30u);
if(rv != 0) {
return rv;
}
return 0;
}
static int emit_table_size(nghttp2_bufs *bufs, size_t table_size) static int emit_table_size(nghttp2_bufs *bufs, size_t table_size)
{ {
int rv; int rv;
@ -584,7 +560,7 @@ static int emit_table_size(nghttp2_bufs *bufs, size_t table_size)
DEBUGF(fprintf(stderr, "deflatehd: emit table_size=%zu\n", table_size)); DEBUGF(fprintf(stderr, "deflatehd: emit table_size=%zu\n", table_size));
blocklen = count_encoded_length(table_size, 4); blocklen = count_encoded_length(table_size, 5);
if(sizeof(sb) < blocklen) { if(sizeof(sb) < blocklen) {
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;
@ -594,7 +570,7 @@ static int emit_table_size(nghttp2_bufs *bufs, size_t table_size)
*bufp = 0x20u; *bufp = 0x20u;
encode_length(bufp, table_size, 4); encode_length(bufp, table_size, 5);
rv = nghttp2_bufs_add(bufs, sb, blocklen); rv = nghttp2_bufs_add(bufs, sb, blocklen);
if(rv != 0) { if(rv != 0) {
@ -789,23 +765,6 @@ static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
return 0; return 0;
} }
/*
* Emit common header with |index| by toggle off and on (thus 2
* indexed representation emissions).
*/
static int emit_implicit(nghttp2_bufs *bufs, size_t idx)
{
int i, rv;
for(i = 0; i < 2; ++i) {
rv = emit_indexed_block(bufs, idx);
if(rv != 0) {
return rv;
}
}
return 0;
}
static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context, static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
nghttp2_bufs *bufs, nghttp2_bufs *bufs,
const nghttp2_nv *nv, const nghttp2_nv *nv,
@ -824,17 +783,7 @@ static nghttp2_hd_entry* add_hd_table_incremental(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);
if(context->role == NGHTTP2_HD_ROLE_DEFLATE) {
if(ent->flags & NGHTTP2_HD_FLAG_IMPLICIT_EMIT) {
/* Emit common header just before it slips away from the
table. If we don't do this, we have to emit it in literal
representation which hurts compression. */
rv = emit_implicit(bufs, idx);
if(rv != 0) {
return NULL;
}
}
}
DEBUGF(fprintf(stderr, "hpack: remove item from header table: ")); DEBUGF(fprintf(stderr, "hpack: remove item from header table: "));
DEBUGF(fwrite(ent->nv.name, ent->nv.namelen, 1, stderr)); DEBUGF(fwrite(ent->nv.name, ent->nv.namelen, 1, stderr));
DEBUGF(fprintf(stderr, ": ")); DEBUGF(fprintf(stderr, ": "));
@ -882,8 +831,6 @@ static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
} }
context->hd_table_bufsize += room; context->hd_table_bufsize += room;
new_ent->flags |= NGHTTP2_HD_FLAG_REFSET;
} }
return new_ent; return new_ent;
} }
@ -987,15 +934,6 @@ int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
return 0; return 0;
} }
static void clear_refset(nghttp2_hd_context *context)
{
size_t i;
for(i = 0; i < context->hd_table.len; ++i) {
nghttp2_hd_entry *ent = hd_ringbuf_get(&context->hd_table, i);
ent->flags &= ~NGHTTP2_HD_FLAG_REFSET;
}
}
#define INDEX_RANGE_VALID(context, idx) \ #define INDEX_RANGE_VALID(context, idx) \
((idx) < (context)->hd_table.len + STATIC_TABLE_LENGTH) ((idx) < (context)->hd_table.len + STATIC_TABLE_LENGTH)
@ -1063,9 +1001,6 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
if(idx >= deflater->ctx.hd_table.len) { if(idx >= deflater->ctx.hd_table.len) {
nghttp2_hd_entry *new_ent; nghttp2_hd_entry *new_ent;
/* It is important to first add entry to the header table and
let eviction go. If NGHTTP2_HD_FLAG_IMPLICIT_EMIT entry is
evicted, it must be emitted before the |nv|. */
new_ent = add_hd_table_incremental(&deflater->ctx, bufs, &ent->nv, new_ent = add_hd_table_incremental(&deflater->ctx, bufs, &ent->nv,
NGHTTP2_HD_FLAG_NONE); NGHTTP2_HD_FLAG_NONE);
if(!new_ent) { if(!new_ent) {
@ -1075,52 +1010,16 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
nghttp2_hd_entry_free(new_ent); nghttp2_hd_entry_free(new_ent);
free(new_ent); free(new_ent);
new_ent = NULL; new_ent = NULL;
} else {
/* new_ent->ref > 0 means that new_ent is in the reference
set */
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
} }
rv = emit_indexed_block(bufs, idx); rv = emit_indexed_block(bufs, idx);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }
} else if((ent->flags & NGHTTP2_HD_FLAG_REFSET) == 0) { } else {
ent->flags |= NGHTTP2_HD_FLAG_REFSET | NGHTTP2_HD_FLAG_EMIT;
rv = emit_indexed_block(bufs, idx); rv = emit_indexed_block(bufs, idx);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }
} else {
int num_emits = 0;
if(ent->flags & NGHTTP2_HD_FLAG_EMIT) {
/* occurrences of the same indexed representation. Emit index
twice. */
num_emits = 2;
} else if(ent->flags & NGHTTP2_HD_FLAG_IMPLICIT_EMIT) {
/* ent was implicitly emitted because it is the common
header field. To support occurrences of the same indexed
representation, we have to emit 4 times. This is because
"implicitly emitted" means actually not emitted at
all. So first 2 emits performs 1st header appears in the
reference set. And another 2 emits are done for 2nd
(current) header. */
ent->flags ^= NGHTTP2_HD_FLAG_IMPLICIT_EMIT;
ent->flags |= NGHTTP2_HD_FLAG_EMIT;
num_emits = 4;
} else {
/* This is common header and not emitted in the current
run. Just mark IMPLICIT_EMIT, in the hope that we are not
required to emit anything for this. We will emit toggle
off/on for this entry if it is removed from the header
table. */
ent->flags |= NGHTTP2_HD_FLAG_IMPLICIT_EMIT;
}
for(; num_emits > 0; --num_emits) {
rv = emit_indexed_block(bufs, idx);
if(rv != 0) {
return rv;
}
}
} }
} else { } else {
ssize_t idx = -1; ssize_t idx = -1;
@ -1150,10 +1049,6 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
if(new_ent->ref == 0) { if(new_ent->ref == 0) {
nghttp2_hd_entry_free(new_ent); nghttp2_hd_entry_free(new_ent);
free(new_ent); free(new_ent);
} else {
/* new_ent->ref > 0 means that new_ent is in the reference
set. */
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
} }
incidx = 1; incidx = 1;
} }
@ -1169,30 +1064,6 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
return 0; return 0;
} }
static int deflate_post_process_hd_entry(nghttp2_hd_entry *ent,
size_t idx,
nghttp2_bufs *bufs)
{
int rv;
if((ent->flags & NGHTTP2_HD_FLAG_REFSET) &&
(ent->flags & NGHTTP2_HD_FLAG_IMPLICIT_EMIT) == 0 &&
(ent->flags & NGHTTP2_HD_FLAG_EMIT) == 0) {
/* This entry is not present in the current header set and must
be removed. */
ent->flags ^= NGHTTP2_HD_FLAG_REFSET;
rv = emit_indexed_block(bufs, idx);
if(rv != 0) {
return rv;
}
}
ent->flags &= ~(NGHTTP2_HD_FLAG_EMIT | NGHTTP2_HD_FLAG_IMPLICIT_EMIT);
return 0;
}
int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater, int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
nghttp2_bufs *bufs, nghttp2_bufs *bufs,
const nghttp2_nv *nv, size_t nvlen) const nghttp2_nv *nv, size_t nvlen)
@ -1215,13 +1086,6 @@ int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
} }
} }
if(deflater->no_refset) {
rv = emit_clear_refset(bufs);
if(rv != 0) {
goto fail;
}
clear_refset(&deflater->ctx);
}
for(i = 0; i < nvlen; ++i) { for(i = 0; i < nvlen; ++i) {
rv = deflate_nv(deflater, bufs, &nv[i]); rv = deflate_nv(deflater, bufs, &nv[i]);
if(rv != 0) { if(rv != 0) {
@ -1232,15 +1096,6 @@ int nghttp2_hd_deflate_hd_bufs(nghttp2_hd_deflater *deflater,
DEBUGF(fprintf(stderr, DEBUGF(fprintf(stderr,
"deflatehd: all input name/value pairs were deflated\n")); "deflatehd: all input name/value pairs were deflated\n"));
for(i = 0; i < deflater->ctx.hd_table.len; ++i) {
nghttp2_hd_entry *ent = hd_ringbuf_get(&deflater->ctx.hd_table, i);
rv = deflate_post_process_hd_entry(ent, i, bufs);
if(rv != 0) {
goto fail;
}
}
return 0; return 0;
fail: fail:
DEBUGF(fprintf(stderr, "deflatehd: error return %d\n", rv)); DEBUGF(fprintf(stderr, "deflatehd: error return %d\n", rv));
@ -1282,12 +1137,9 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater, size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nva, size_t nvlen) const nghttp2_nv *nva, size_t nvlen)
{ {
size_t n; size_t n = 0;
size_t i; size_t i;
/* Possible Reference Set Emptying */
n = 1;
/* Possible Maximum Header Table Size Change. Encoding (1u << 31) - /* Possible Maximum Header Table Size Change. Encoding (1u << 31) -
1 using 4 bit prefix requires 6 bytes. */ 1 using 4 bit prefix requires 6 bytes. */
n += 6; n += 6;
@ -1305,9 +1157,6 @@ size_t nghttp2_hd_deflate_bound(nghttp2_hd_deflater *deflater,
n += nva[i].namelen + nva[i].valuelen; n += nva[i].namelen + nva[i].valuelen;
} }
/* Add possible reference set toggle off */
n += deflater->ctx.hd_table.len;
return n; return n;
} }
@ -1483,18 +1332,11 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
inflater->ent_keep = new_ent; inflater->ent_keep = new_ent;
return 0; return 0;
} }
ent->flags ^= NGHTTP2_HD_FLAG_REFSET;
if(ent->flags & NGHTTP2_HD_FLAG_REFSET) {
emit_indexed_header(nv_out, ent); emit_indexed_header(nv_out, ent);
return 0; return 0;
} }
DEBUGF(fprintf(stderr, "inflatehd: toggle off item: "));
DEBUGF(fwrite(ent->nv.name, ent->nv.namelen, 1, stderr));
DEBUGF(fprintf(stderr, ": "));
DEBUGF(fwrite(ent->nv.value, ent->nv.valuelen, 1, stderr));
DEBUGF(fprintf(stderr, "\n"));
return 1;
}
static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv, int value_only) nghttp2_nv *nv, int value_only)
@ -1678,20 +1520,10 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
for(; in != last;) { for(; in != last;) {
switch(inflater->state) { switch(inflater->state) {
case NGHTTP2_HD_STATE_OPCODE: case NGHTTP2_HD_STATE_OPCODE:
if((*in & 0xf0u) == 0x20u) { if((*in & 0xe0u) == 0x20u) {
DEBUGF(fprintf(stderr, "inflatehd: header table size change\n")); DEBUGF(fprintf(stderr, "inflatehd: header table size change\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED; inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE; inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
} else if((*in & 0xf0u) == 0x30u) {
if(*in != 0x30u) {
rv = NGHTTP2_ERR_HEADER_COMP;
goto fail;
}
DEBUGF(fprintf(stderr, "inflatehd: clearing reference set\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
inflater->state = NGHTTP2_HD_STATE_CLEAR_REFSET;
++in;
} else if(*in & 0x80u) { } else if(*in & 0x80u) {
DEBUGF(fprintf(stderr, "inflatehd: indexed repr\n")); DEBUGF(fprintf(stderr, "inflatehd: indexed repr\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED; inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
@ -1720,15 +1552,10 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
} }
inflater->left = 0; inflater->left = 0;
inflater->shift = 0; inflater->shift = 0;
break;
case NGHTTP2_HD_STATE_CLEAR_REFSET:
clear_refset(&inflater->ctx);
inflater->state = NGHTTP2_HD_STATE_OPCODE;
break; break;
case NGHTTP2_HD_STATE_READ_TABLE_SIZE: case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
rfin = 0; rfin = 0;
rv = hd_inflate_read_len(inflater, &rfin, in, last, 4, rv = hd_inflate_read_len(inflater, &rfin, in, last, 5,
inflater->settings_hd_table_bufsize_max); inflater->settings_hd_table_bufsize_max);
if(rv < 0) { if(rv < 0) {
goto fail; goto fail;
@ -1995,20 +1822,6 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
goto fail; goto fail;
} }
for(; inflater->end_headers_index < inflater->ctx.hd_table.len;
++inflater->end_headers_index) {
nghttp2_hd_entry *ent;
ent = hd_ringbuf_get(&inflater->ctx.hd_table,
inflater->end_headers_index);
if((ent->flags & NGHTTP2_HD_FLAG_REFSET) &&
(ent->flags & NGHTTP2_HD_FLAG_EMIT) == 0) {
emit_indexed_header(nv_out, ent);
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
return (ssize_t)(in - first);
}
ent->flags &= ~NGHTTP2_HD_FLAG_EMIT;
}
*inflate_flags |= NGHTTP2_HD_INFLATE_FINAL; *inflate_flags |= NGHTTP2_HD_INFLATE_FINAL;
} }
return (ssize_t)(in - first); return (ssize_t)(in - first);
@ -2033,7 +1846,6 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater)
{ {
hd_inflate_keep_free(inflater); hd_inflate_keep_free(inflater);
inflater->end_headers_index = 0;
return 0; return 0;
} }

View File

@ -58,18 +58,12 @@ typedef enum {
NGHTTP2_HD_FLAG_NAME_ALLOC = 1, NGHTTP2_HD_FLAG_NAME_ALLOC = 1,
/* Indicates value was dynamically allocated and must be freed */ /* Indicates value was dynamically allocated and must be freed */
NGHTTP2_HD_FLAG_VALUE_ALLOC = 1 << 1, NGHTTP2_HD_FLAG_VALUE_ALLOC = 1 << 1,
/* Indicates that the entry is in the reference set */
NGHTTP2_HD_FLAG_REFSET = 1 << 2,
/* Indicates that the entry is emitted in the current header
processing. */
NGHTTP2_HD_FLAG_EMIT = 1 << 3,
NGHTTP2_HD_FLAG_IMPLICIT_EMIT = 1 << 4,
/* Indicates that the name was gifted to the entry and no copying /* Indicates that the name was gifted to the entry and no copying
necessary. */ necessary. */
NGHTTP2_HD_FLAG_NAME_GIFT = 1 << 5, NGHTTP2_HD_FLAG_NAME_GIFT = 1 << 2,
/* Indicates that the value was gifted to the entry and no copying /* Indicates that the value was gifted to the entry and no copying
necessary. */ necessary. */
NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 6 NGHTTP2_HD_FLAG_VALUE_GIFT = 1 << 3
} nghttp2_hd_flags; } nghttp2_hd_flags;
typedef struct { typedef struct {
@ -97,7 +91,6 @@ typedef enum {
typedef enum { typedef enum {
NGHTTP2_HD_STATE_OPCODE, NGHTTP2_HD_STATE_OPCODE,
NGHTTP2_HD_STATE_CLEAR_REFSET,
NGHTTP2_HD_STATE_READ_TABLE_SIZE, NGHTTP2_HD_STATE_READ_TABLE_SIZE,
NGHTTP2_HD_STATE_READ_INDEX, NGHTTP2_HD_STATE_READ_INDEX,
NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN, NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN,
@ -131,9 +124,6 @@ struct nghttp2_hd_deflater {
nghttp2_hd_context ctx; nghttp2_hd_context ctx;
/* 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;
/* Set to this nonzero to clear reference set on each deflation each
time. */
uint8_t no_refset;
/* If nonzero, send header table size using encoding context update /* If nonzero, send header table size using encoding context update
in the next deflate process */ in the next deflate process */
uint8_t notify_table_size_change; uint8_t notify_table_size_change;
@ -159,9 +149,6 @@ struct nghttp2_hd_inflater {
size_t left; size_t left;
/* The index in indexed repr or indexed name */ /* The index in indexed repr or indexed name */
size_t index; size_t index;
/* The index of header table to toggle off the entry from reference
set at the end of decompression. */
size_t end_headers_index;
/* The length of new name encoded in literal. For huffman encoded /* The length of new name encoded in literal. For huffman encoded
string, this is the length after it is decoded. */ string, this is the length after it is decoded. */
size_t newnamelen; size_t newnamelen;

View File

@ -252,9 +252,6 @@ cdef extern from 'nghttp2/nghttp2.h':
void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater) void nghttp2_hd_deflate_del(nghttp2_hd_deflater *deflater)
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset)
int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t hd_table_bufsize_max) size_t hd_table_bufsize_max)
@ -291,9 +288,6 @@ cdef extern from 'nghttp2_hd.h':
# This is macro # This is macro
int NGHTTP2_HD_ENTRY_OVERHEAD int NGHTTP2_HD_ENTRY_OVERHEAD
ctypedef enum nghttp2_hd_flags:
NGHTTP2_HD_FLAG_REFSET
ctypedef enum nghttp2_hd_inflate_flag: ctypedef enum nghttp2_hd_inflate_flag:
NGHTTP2_HD_INFLATE_EMIT NGHTTP2_HD_INFLATE_EMIT
NGHTTP2_HD_INFLATE_FINAL NGHTTP2_HD_INFLATE_FINAL

View File

@ -33,12 +33,11 @@ HD_ENTRY_OVERHEAD = cnghttp2.NGHTTP2_HD_ENTRY_OVERHEAD
class HDTableEntry: class HDTableEntry:
def __init__(self, name, namelen, value, valuelen, ref): def __init__(self, name, namelen, value, valuelen):
self.name = name self.name = name
self.namelen = namelen self.namelen = namelen
self.value = value self.value = value
self.valuelen = valuelen self.valuelen = valuelen
self.ref = ref
def space(self): def space(self):
return self.namelen + self.valuelen + HD_ENTRY_OVERHEAD return self.namelen + self.valuelen + HD_ENTRY_OVERHEAD
@ -52,8 +51,7 @@ cdef _get_hd_table(cnghttp2.nghttp2_hd_context *ctx):
k = _get_pybytes(entry.nv.name, entry.nv.namelen) k = _get_pybytes(entry.nv.name, entry.nv.namelen)
v = _get_pybytes(entry.nv.value, entry.nv.valuelen) v = _get_pybytes(entry.nv.value, entry.nv.valuelen)
res.append(HDTableEntry(k, entry.nv.namelen, res.append(HDTableEntry(k, entry.nv.namelen,
v, entry.nv.valuelen, v, entry.nv.valuelen))
(entry.flags & cnghttp2.NGHTTP2_HD_FLAG_REFSET) != 0))
return res return res
cdef _get_pybytes(uint8_t *b, uint16_t blen): cdef _get_pybytes(uint8_t *b, uint16_t blen):
@ -143,15 +141,6 @@ cdef class HDDeflater:
return res return res
def set_no_refset(self, no_refset):
'''Tells the compressor not to use reference set if |no_refset| is
nonzero. If |no_refset| is nonzero, on each invocation of
deflate(), compressor first emits index=0 to clear up
reference set.
'''
cnghttp2.nghttp2_hd_deflate_set_no_refset(self._deflater, no_refset)
def change_table_size(self, hd_table_bufsize_max): def change_table_size(self, hd_table_bufsize_max):
'''Changes header table size to |hd_table_bufsize_max| byte. '''Changes header table size to |hd_table_bufsize_max| byte.
@ -243,16 +232,14 @@ def print_hd_table(hdtable):
function does not work if header name/value cannot be decoded using function does not work if header name/value cannot be decoded using
UTF-8 encoding. UTF-8 encoding.
s=N means the entry occupies N bytes in header table. if r=y, then s=N means the entry occupies N bytes in header table.
the entry is in the reference set.
''' '''
idx = 0 idx = 0
for entry in hdtable: for entry in hdtable:
idx += 1 idx += 1
print('[{}] (s={}) (r={}) {}: {}'\ print('[{}] (s={}) {}: {}'\
.format(idx, entry.space(), .format(idx, entry.space(),
'y' if entry.ref else 'n',
entry.name.decode('utf-8'), entry.name.decode('utf-8'),
entry.value.decode('utf-8'))) entry.value.decode('utf-8')))

View File

@ -43,8 +43,6 @@ json_t* dump_header_table(nghttp2_hd_context *context)
json_object_set_new(outent, "index", json_integer(i + 1)); json_object_set_new(outent, "index", json_integer(i + 1));
dump_val(outent, "name", ent->nv.name, ent->nv.namelen); dump_val(outent, "name", ent->nv.name, ent->nv.namelen);
dump_val(outent, "value", ent->nv.value, ent->nv.valuelen); dump_val(outent, "value", ent->nv.value, ent->nv.valuelen);
json_object_set_new(outent, "referenced",
json_boolean(ent->flags & NGHTTP2_HD_FLAG_REFSET));
json_object_set_new(outent, "size", json_object_set_new(outent, "size",
json_integer(ent->nv.namelen + ent->nv.valuelen + json_integer(ent->nv.namelen + ent->nv.valuelen +
NGHTTP2_HD_ENTRY_OVERHEAD)); NGHTTP2_HD_ENTRY_OVERHEAD));

View File

@ -53,7 +53,6 @@ typedef struct {
size_t deflate_table_size; size_t deflate_table_size;
int http1text; int http1text;
int dump_header_table; int dump_header_table;
int no_refset;
} deflate_config; } deflate_config;
static deflate_config config; static deflate_config config;
@ -198,7 +197,6 @@ static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
static void init_deflater(nghttp2_hd_deflater *deflater) static void init_deflater(nghttp2_hd_deflater *deflater)
{ {
nghttp2_hd_deflate_init2(deflater, config.deflate_table_size); nghttp2_hd_deflate_init2(deflater, config.deflate_table_size);
nghttp2_hd_deflate_set_no_refset(deflater, config.no_refset);
nghttp2_hd_deflate_change_table_size(deflater, config.table_size); nghttp2_hd_deflate_change_table_size(deflater, config.table_size);
} }
@ -387,8 +385,7 @@ OPTIONS:
buffer. buffer.
Default: 4096 Default: 4096
-d, --dump-header-table -d, --dump-header-table
Output dynamic header table. Output dynamic header table.)"
-c, --no-refset Don't use reference set.)"
<< std::endl; << std::endl;
} }
@ -397,7 +394,6 @@ static struct option long_options[] = {
{"table-size", required_argument, nullptr, 's'}, {"table-size", required_argument, nullptr, 's'},
{"deflate-table-size", required_argument, nullptr, 'S'}, {"deflate-table-size", required_argument, nullptr, 'S'},
{"dump-header-table", no_argument, nullptr, 'd'}, {"dump-header-table", no_argument, nullptr, 'd'},
{"no-refset", no_argument, nullptr, 'c'},
{nullptr, 0, nullptr, 0 } {nullptr, 0, nullptr, 0 }
}; };
@ -409,10 +405,9 @@ int main(int argc, char **argv)
config.deflate_table_size = NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE; config.deflate_table_size = NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE;
config.http1text = 0; config.http1text = 0;
config.dump_header_table = 0; config.dump_header_table = 0;
config.no_refset = 0;
while(1) { while(1) {
int option_index = 0; int option_index = 0;
int c = getopt_long(argc, argv, "S:cdhs:t", long_options, &option_index); int c = getopt_long(argc, argv, "S:dhs:t", long_options, &option_index);
if(c == -1) { if(c == -1) {
break; break;
} }
@ -446,10 +441,6 @@ int main(int argc, char **argv)
// --dump-header-table // --dump-header-table
config.dump_header_table = 1; config.dump_header_table = 1;
break; break;
case 'c':
// --no-refset
config.no_refset = 1;
break;
case '?': case '?':
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
default: default:

View File

@ -255,10 +255,6 @@ int main(int argc, char* argv[])
!CU_add_test(pSuite, "hd_deflate", test_nghttp2_hd_deflate) || !CU_add_test(pSuite, "hd_deflate", test_nghttp2_hd_deflate) ||
!CU_add_test(pSuite, "hd_deflate_same_indexed_repr", !CU_add_test(pSuite, "hd_deflate_same_indexed_repr",
test_nghttp2_hd_deflate_same_indexed_repr) || test_nghttp2_hd_deflate_same_indexed_repr) ||
!CU_add_test(pSuite, "hd_deflate_common_header_eviction",
test_nghttp2_hd_deflate_common_header_eviction) ||
!CU_add_test(pSuite, "hd_deflate_clear_refset",
test_nghttp2_hd_deflate_clear_refset) ||
!CU_add_test(pSuite, "hd_inflate_indexed", !CU_add_test(pSuite, "hd_inflate_indexed",
test_nghttp2_hd_inflate_indexed) || test_nghttp2_hd_inflate_indexed) ||
!CU_add_test(pSuite, "hd_inflate_indname_noinc", !CU_add_test(pSuite, "hd_inflate_indname_noinc",

View File

@ -159,8 +159,7 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater)); CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater));
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater)); CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater));
/* Encode 2 same headers. cookie:alpha is not in the reference set, /* Encode 2 same headers. Emit 1 literal reprs and 1 index repr. */
so first emit literal repr and then 2 emits of indexed repr. */
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1)); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva1, ARRLEN(nva1));
blocklen = nghttp2_bufs_len(&bufs); blocklen = nghttp2_bufs_len(&bufs);
@ -174,13 +173,12 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
nva_out_reset(&out); nva_out_reset(&out);
nghttp2_bufs_reset(&bufs); nghttp2_bufs_reset(&bufs);
/* Encode 3 same headers. This time, cookie:alpha is in the /* Encode 3 same headers. This time, emits 3 index reprs. */
reference set, so the encoder emits indexed repr 6 times */
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2)); rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva2, ARRLEN(nva2));
blocklen = nghttp2_bufs_len(&bufs); blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
CU_ASSERT(blocklen == 6); CU_ASSERT(blocklen == 3);
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0)); CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
CU_ASSERT(3 == out.nvlen); CU_ASSERT(3 == out.nvlen);
@ -195,120 +193,6 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
nghttp2_hd_deflate_free(&deflater); nghttp2_hd_deflate_free(&deflater);
} }
void test_nghttp2_hd_deflate_common_header_eviction(void)
{
nghttp2_hd_deflater deflater;
nghttp2_hd_inflater inflater;
nghttp2_nv nva[] = {MAKE_NV("h1", ""),
MAKE_NV("h2", "")};
nghttp2_bufs bufs;
ssize_t blocklen;
/* Default header table capacity is 4096. Adding 2 byte header name
and 4060 byte value, which is 4094 bytes including overhead, to
the table evicts first entry. */
uint8_t value[3038];
nva_out out;
size_t i;
int rv;
frame_pack_bufs_init(&bufs);
nva_out_init(&out);
memset(value, '0', sizeof(value));
for(i = 0; i < 2; ++i) {
nva[i].value = value;
nva[i].valuelen = sizeof(value);
}
nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater);
/* First emit "h1: ..." to put it in the reference set (index
= 0). */
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 1);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
CU_ASSERT(blocklen > 0);
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
CU_ASSERT(1 == out.nvlen);
nghttp2_nv_array_sort(nva, 1);
assert_nv_equal(nva, out.nva, 1);
nva_out_reset(&out);
nghttp2_bufs_reset(&bufs);
/* Encode with second header */
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nva, 2);
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
CU_ASSERT(blocklen > 0);
/* Check common header "h1: ...:, which is removed from the
header table because of eviction, is still emitted by the
inflater */
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
CU_ASSERT(2 == out.nvlen);
nghttp2_nv_array_sort(nva, 2);
assert_nv_equal(nva, out.nva, 2);
nva_out_reset(&out);
nghttp2_bufs_reset(&bufs);
CU_ASSERT(1 == deflater.ctx.hd_table.len);
CU_ASSERT(1 == inflater.ctx.hd_table.len);
nghttp2_bufs_free(&bufs);
nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater);
}
void test_nghttp2_hd_deflate_clear_refset(void)
{
nghttp2_hd_deflater deflater;
nghttp2_hd_inflater inflater;
nghttp2_bufs bufs;
ssize_t blocklen;
nghttp2_nv nv[] = {
MAKE_NV(":path", "/"),
MAKE_NV(":scheme", "http")
};
size_t i;
nva_out out;
int rv;
frame_pack_bufs_init(&bufs);
nva_out_init(&out);
nghttp2_hd_deflate_init2(&deflater,
NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE);
nghttp2_hd_deflate_set_no_refset(&deflater, 1);
nghttp2_hd_inflate_init(&inflater);
for(i = 0; i < 2; ++i) {
rv = nghttp2_hd_deflate_hd_bufs(&deflater, &bufs, nv, ARRLEN(nv));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
CU_ASSERT(blocklen > 1);
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
CU_ASSERT(ARRLEN(nv) == out.nvlen);
assert_nv_equal(nv, out.nva, ARRLEN(nv));
nva_out_reset(&out);
nghttp2_bufs_reset(&bufs);
}
nghttp2_bufs_free(&bufs);
nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater);
}
void test_nghttp2_hd_inflate_indexed(void) void test_nghttp2_hd_inflate_indexed(void)
{ {
nghttp2_hd_inflater inflater; nghttp2_hd_inflater inflater;
@ -459,7 +343,6 @@ void test_nghttp2_hd_inflate_indname_inc_eviction(void)
nghttp2_bufs_reset(&bufs); nghttp2_bufs_reset(&bufs);
CU_ASSERT(3 == inflater.ctx.hd_table.len); CU_ASSERT(3 == inflater.ctx.hd_table.len);
CU_ASSERT(GET_TABLE_ENT(&inflater.ctx, 0)->flags & NGHTTP2_HD_FLAG_REFSET);
nghttp2_bufs_free(&bufs); nghttp2_bufs_free(&bufs);
nghttp2_hd_inflate_free(&inflater); nghttp2_hd_inflate_free(&inflater);
@ -1163,7 +1046,7 @@ void test_nghttp2_hd_deflate_bound(void)
bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva)); bound = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
CU_ASSERT(1 + 6 + 6 * 2 * 2 + CU_ASSERT(6 + 6 * 2 * 2 +
nva[0].namelen + nva[0].valuelen + nva[0].namelen + nva[0].valuelen +
nva[1].namelen + nva[1].valuelen nva[1].namelen + nva[1].valuelen
== bound); == bound);
@ -1174,7 +1057,7 @@ void test_nghttp2_hd_deflate_bound(void)
bound2 = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva)); bound2 = nghttp2_hd_deflate_bound(&deflater, nva, ARRLEN(nva));
CU_ASSERT(bound + 2 == bound2); CU_ASSERT(bound == bound2);
nghttp2_bufs_free(&bufs); nghttp2_bufs_free(&bufs);
nghttp2_hd_deflate_free(&deflater); nghttp2_hd_deflate_free(&deflater);

View File

@ -27,8 +27,6 @@
void test_nghttp2_hd_deflate(void); void test_nghttp2_hd_deflate(void);
void test_nghttp2_hd_deflate_same_indexed_repr(void); void test_nghttp2_hd_deflate_same_indexed_repr(void);
void test_nghttp2_hd_deflate_common_header_eviction(void);
void test_nghttp2_hd_deflate_clear_refset(void);
void test_nghttp2_hd_inflate_indexed(void); void test_nghttp2_hd_inflate_indexed(void);
void test_nghttp2_hd_inflate_indname_noinc(void); void test_nghttp2_hd_inflate_indname_noinc(void);
void test_nghttp2_hd_inflate_indname_inc(void); void test_nghttp2_hd_inflate_indname_inc(void);

View File

@ -927,7 +927,7 @@ void test_nghttp2_session_recv_headers_with_priority(void)
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
CU_ASSERT(NGHTTP2_FRAME_HDLEN + 5 == nghttp2_bufs_len(&bufs)); CU_ASSERT(NGHTTP2_FRAME_HDLEN + 5 + 2 == nghttp2_bufs_len(&bufs));
nghttp2_frame_headers_free(&frame.headers); nghttp2_frame_headers_free(&frame.headers);