HPACK post -05 updates

* Use 1 Huffman code table for both request and response
* Remove complicated deflater side table size management
* Add encoding context update
* Fix memory leak in inflater
This commit is contained in:
Tatsuhiro Tsujikawa 2014-02-13 23:22:52 +09:00
parent 082876d92d
commit fd88c6160d
19 changed files with 471 additions and 5771 deletions

View File

@ -286,13 +286,10 @@ static void nghttp2_hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf)
}
static int nghttp2_hd_context_init(nghttp2_hd_context *context,
nghttp2_hd_role role,
nghttp2_hd_side side,
size_t deflate_hd_table_bufsize_max)
nghttp2_hd_role role)
{
int rv;
context->role = role;
context->side = side;
context->bad = 0;
context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
rv = nghttp2_hd_ringbuf_init
@ -302,41 +299,41 @@ static int nghttp2_hd_context_init(nghttp2_hd_context *context,
return rv;
}
context->deflate_hd_table_bufsize_max = deflate_hd_table_bufsize_max;
context->deflate_hd_table_bufsize = 0;
context->deflate_hd_tablelen = 0;
context->hd_table_bufsize = 0;
return 0;
}
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater, nghttp2_hd_side side)
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater)
{
return nghttp2_hd_deflate_init2(deflater, side,
return nghttp2_hd_deflate_init2(deflater,
NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE);
}
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
nghttp2_hd_side side,
size_t deflate_hd_table_bufsize_max)
{
int rv;
rv = nghttp2_hd_context_init(&deflater->ctx, NGHTTP2_HD_ROLE_DEFLATE, side,
deflate_hd_table_bufsize_max);
rv = nghttp2_hd_context_init(&deflater->ctx, NGHTTP2_HD_ROLE_DEFLATE);
if(rv != 0) {
return rv;
}
deflater->no_refset = 0;
deflater->deflate_hd_table_bufsize_max = deflate_hd_table_bufsize_max;
return 0;
}
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_hd_side side)
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater)
{
int rv;
rv = nghttp2_hd_context_init(&inflater->ctx, NGHTTP2_HD_ROLE_INFLATE, side,
NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE);
rv = nghttp2_hd_context_init(&inflater->ctx, NGHTTP2_HD_ROLE_INFLATE);
if(rv != 0) {
return rv;
}
inflater->settings_hd_table_bufsize_max =
NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
inflater->ent_keep = NULL;
inflater->name_keep = NULL;
inflater->value_keep = NULL;
@ -559,16 +556,38 @@ static uint8_t* decode_length(ssize_t *res, int *final, ssize_t initial,
return in + 1;
}
static int emit_indexed0(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr)
static int emit_clear_refset(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr)
{
int rv;
rv = ensure_write_buffer(buf_ptr, buflen_ptr, *offset_ptr, 1);
uint8_t *bufp;
rv = ensure_write_buffer(buf_ptr, buflen_ptr, *offset_ptr, 2);
if(rv != 0) {
return rv;
}
*(*buf_ptr + *offset_ptr) = 0x80u;
++*offset_ptr;
bufp = *buf_ptr + *offset_ptr;
*bufp++ = 0x80u;
*bufp = 0x80u;
*offset_ptr += 2;
return 0;
}
static int emit_table_size(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, size_t table_size)
{
int rv;
uint8_t *bufp;
size_t blocklen = 1 + count_encoded_length(table_size, 7);
rv = ensure_write_buffer(buf_ptr, buflen_ptr, *offset_ptr, blocklen);
if(rv != 0) {
return rv;
}
DEBUGF(fprintf(stderr, "emit table_size=%zu\n", table_size));
bufp = *buf_ptr + *offset_ptr;
*bufp++ = 0x80u;
*bufp = 0;
encode_length(bufp, table_size, 7);
*offset_ptr += blocklen;
return 0;
}
@ -591,15 +610,14 @@ static int emit_indexed_block(uint8_t **buf_ptr, size_t *buflen_ptr,
static size_t emit_string(uint8_t *buf, size_t buflen,
size_t enclen, int huffman,
const uint8_t *str, size_t len,
nghttp2_hd_side side)
const uint8_t *str, size_t len)
{
size_t rv;
*buf = huffman ? 1 << 7 : 0;
rv = encode_length(buf, enclen, 7);
buf += rv;
if(huffman) {
nghttp2_hd_huff_encode(buf, buflen - rv, str, len, side);
nghttp2_hd_huff_encode(buf, buflen - rv, str, len);
} else {
assert(enclen == len);
memcpy(buf, str, len);
@ -610,12 +628,11 @@ static size_t emit_string(uint8_t *buf, size_t buflen,
static int emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, size_t index,
const uint8_t *value, size_t valuelen,
int inc_indexing,
nghttp2_hd_side side)
int inc_indexing)
{
int rv;
uint8_t *bufp;
size_t encvallen = nghttp2_hd_huff_encode_count(value, valuelen, side);
size_t encvallen = nghttp2_hd_huff_encode_count(value, valuelen);
size_t blocklen = count_encoded_length(index + 1, 6);
int huffman = encvallen < valuelen;
if(!huffman) {
@ -630,7 +647,7 @@ static int emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
*bufp = inc_indexing ? 0 : 0x40u;
bufp += encode_length(bufp, index + 1, 6);
bufp += emit_string(bufp, *buflen_ptr - (bufp - *buf_ptr),
encvallen, huffman, value, valuelen, side);
encvallen, huffman, value, valuelen);
assert(bufp - (*buf_ptr + *offset_ptr) == (ssize_t)blocklen);
*offset_ptr += blocklen;
return 0;
@ -638,15 +655,14 @@ static int emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
static int emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, nghttp2_nv *nv,
int inc_indexing,
nghttp2_hd_side side)
int inc_indexing)
{
int rv;
uint8_t *bufp;
size_t encnamelen =
nghttp2_hd_huff_encode_count(nv->name, nv->namelen, side);
nghttp2_hd_huff_encode_count(nv->name, nv->namelen);
size_t encvallen =
nghttp2_hd_huff_encode_count(nv->value, nv->valuelen, side);
nghttp2_hd_huff_encode_count(nv->value, nv->valuelen);
size_t blocklen = 1;
int name_huffman = encnamelen < nv->namelen;
int value_huffman = encvallen < nv->valuelen;
@ -665,9 +681,9 @@ static int emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
bufp = *buf_ptr + *offset_ptr;
*bufp++ = inc_indexing ? 0 : 0x40u;
bufp += emit_string(bufp, *buflen_ptr - (bufp - *buf_ptr),
encnamelen, name_huffman, nv->name, nv->namelen, side);
encnamelen, name_huffman, nv->name, nv->namelen);
bufp += emit_string(bufp, *buflen_ptr - (bufp - *buf_ptr),
encvallen, value_huffman, nv->value, nv->valuelen, side);
encvallen, value_huffman, nv->value, nv->valuelen);
*offset_ptr += blocklen;
return 0;
}
@ -707,11 +723,6 @@ static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
size_t index = context->hd_table.len - 1;
nghttp2_hd_entry* ent = nghttp2_hd_ringbuf_get(&context->hd_table, index);
context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen);
if(context->hd_table_bufsize < context->deflate_hd_table_bufsize) {
context->deflate_hd_table_bufsize -= entry_room(ent->nv.namelen,
ent->nv.valuelen);
--context->deflate_hd_tablelen;
}
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
@ -734,82 +745,19 @@ static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
free(ent);
}
}
while(context->deflate_hd_table_bufsize + room >
context->deflate_hd_table_bufsize_max
&& context->deflate_hd_tablelen > 0) {
size_t index = context->deflate_hd_tablelen - 1;
nghttp2_hd_entry *ent =
nghttp2_hd_ringbuf_get(&context->hd_table, index);
context->deflate_hd_table_bufsize -= entry_room(ent->nv.namelen,
ent->nv.valuelen);
--context->deflate_hd_tablelen;
if(ent->flags & NGHTTP2_HD_FLAG_IMPLICIT_EMIT) {
/* Just like a normal eviction, implicit header must be
emitted twice. */
rv = emit_implicit(buf_ptr, buflen_ptr, offset_ptr, index);
if(rv != 0) {
return NULL;
}
ent->flags ^= NGHTTP2_HD_FLAG_IMPLICIT_EMIT;
}
if(ent->flags & NGHTTP2_HD_FLAG_REFSET) {
/* We need to drop entry from reference set. */
rv = emit_indexed_block(buf_ptr, buflen_ptr, offset_ptr, index);
if(rv != 0) {
return NULL;
}
ent->flags ^= NGHTTP2_HD_FLAG_REFSET;
}
/* Release memory. We don't remove entry from the header table
at this moment. */
if(ent->flags & NGHTTP2_HD_FLAG_NAME_ALLOC) {
free(ent->nv.name);
ent->nv.name = NULL;
ent->flags ^= NGHTTP2_HD_FLAG_NAME_ALLOC;
}
if(ent->flags & NGHTTP2_HD_FLAG_VALUE_ALLOC) {
free(ent->nv.value);
ent->nv.value = NULL;
ent->flags ^= NGHTTP2_HD_FLAG_VALUE_ALLOC;
}
}
new_ent = malloc(sizeof(nghttp2_hd_entry));
if(new_ent == NULL) {
return NULL;
}
if(context->role == NGHTTP2_HD_ROLE_DEFLATE &&
room > context->deflate_hd_table_bufsize_max) {
uint8_t flags = entry_flags &
~(NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_VALUE_ALLOC |
NGHTTP2_HD_FLAG_NAME_GIFT | NGHTTP2_HD_FLAG_VALUE_GIFT);
rv = nghttp2_hd_entry_init(new_ent, flags,
NULL, nv->namelen, NULL, nv->valuelen);
if(rv != 0) {
free(new_ent);
return NULL;
}
if(flags & NGHTTP2_HD_FLAG_NAME_GIFT) {
free(nv->name);
nv->name = NULL;
}
if(flags & NGHTTP2_HD_FLAG_VALUE_GIFT) {
free(nv->value);
nv->value = NULL;
}
/* caller must emit indexed repr to toggle off new_ent from
reference set. We cannot do it here because it may break the
indexing. */
} else {
rv = nghttp2_hd_entry_init(new_ent,
entry_flags,
nv->name, nv->namelen, nv->value, nv->valuelen);
if(rv != 0) {
free(new_ent);
return NULL;
}
rv = nghttp2_hd_entry_init(new_ent, entry_flags,
nv->name, nv->namelen, nv->value, nv->valuelen);
if(rv != 0) {
free(new_ent);
return NULL;
}
if(room > context->hd_table_bufsize_max) {
/* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
immediately evicted. */
@ -817,11 +765,8 @@ static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
} else {
context->hd_table_bufsize += room;
nghttp2_hd_ringbuf_push_front(&context->hd_table, new_ent);
if(room <= context->deflate_hd_table_bufsize_max) {
new_ent->flags |= NGHTTP2_HD_FLAG_REFSET;
context->deflate_hd_table_bufsize += room;
++context->deflate_hd_tablelen;
}
new_ent->flags |= NGHTTP2_HD_FLAG_REFSET;
}
return new_ent;
}
@ -851,7 +796,7 @@ static search_result search_hd_table(nghttp2_hd_context *context,
uint32_t value_hash = hash(nv->value, nv->valuelen);
ssize_t left = -1, right = STATIC_TABLE_LENGTH;
for(i = 0; i < context->deflate_hd_tablelen; ++i) {
for(i = 0; i < context->hd_table.len; ++i) {
nghttp2_hd_entry *ent = nghttp2_hd_ringbuf_get(&context->hd_table, i);
if(ent->name_hash == name_hash && name_eq(&ent->nv, nv)) {
if(res.index == -1) {
@ -893,35 +838,59 @@ static search_result search_hd_table(nghttp2_hd_context *context,
return res;
}
int nghttp2_hd_change_table_size(nghttp2_hd_context *context,
size_t hd_table_bufsize_max)
static void hd_context_shrink_table_size(nghttp2_hd_context *context)
{
int rv;
rv = nghttp2_hd_ringbuf_reserve
(&context->hd_table, hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD);
if(rv != 0) {
return rv;
}
context->hd_table_bufsize_max = hd_table_bufsize_max;
if(context->role == NGHTTP2_HD_ROLE_INFLATE) {
context->deflate_hd_table_bufsize_max = hd_table_bufsize_max;
}
while(context->hd_table_bufsize > context->hd_table_bufsize_max &&
context->hd_table.len > 0) {
size_t index = context->hd_table.len - 1;
nghttp2_hd_entry* ent = nghttp2_hd_ringbuf_get(&context->hd_table, index);
context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen);
if(context->hd_table_bufsize < context->deflate_hd_table_bufsize) {
context->deflate_hd_table_bufsize -= entry_room(ent->nv.namelen,
ent->nv.valuelen);
--context->deflate_hd_tablelen;
}
nghttp2_hd_ringbuf_pop_back(&context->hd_table);
if(--ent->ref == 0) {
nghttp2_hd_entry_free(ent);
free(ent);
}
}
}
int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t settings_hd_table_bufsize_max)
{
int rv;
size_t next_bufsize = nghttp2_min(settings_hd_table_bufsize_max,
deflater->deflate_hd_table_bufsize_max);
rv = nghttp2_hd_ringbuf_reserve
(&deflater->ctx.hd_table, next_bufsize / NGHTTP2_HD_ENTRY_OVERHEAD);
if(rv != 0) {
return rv;
}
deflater->ctx.hd_table_bufsize_max = settings_hd_table_bufsize_max;
if(settings_hd_table_bufsize_max >= deflater->deflate_hd_table_bufsize_max) {
/* On the next encoding, we sends encoding context update with
deflater->deflate_hd_table_bufsize_max if it is strictly
smaller than settings_hd_table_bufsize_max. */
return 0;
}
hd_context_shrink_table_size(&deflater->ctx);
return 0;
}
int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
size_t settings_hd_table_bufsize_max)
{
int rv;
rv = nghttp2_hd_ringbuf_reserve
(&inflater->ctx.hd_table,
settings_hd_table_bufsize_max / NGHTTP2_HD_ENTRY_OVERHEAD);
if(rv != 0) {
return rv;
}
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);
return 0;
}
@ -962,9 +931,8 @@ nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
static int hd_deflate_should_indexing(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nv)
{
size_t table_size = nghttp2_min(deflater->ctx.deflate_hd_table_bufsize_max,
deflater->ctx.hd_table_bufsize_max);
if(entry_room(nv->namelen, nv->valuelen) > table_size * 3 / 4) {
if(entry_room(nv->namelen, nv->valuelen) >
deflater->ctx.hd_table_bufsize_max * 3 / 4) {
return 0;
}
#ifdef NGHTTP2_XHD
@ -1006,9 +974,9 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
nghttp2_hd_entry_free(new_ent);
free(new_ent);
new_ent = NULL;
} else if(new_ent->nv.name != NULL) {
/* new_ent->ref > 0 and nv.name is not NULL means that new_ent is
in the reference set and in deflate_hd_table_bufsize */
} 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(buf_ptr, buflen_ptr, offset_ptr, index);
@ -1080,20 +1048,18 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
if(new_ent->ref == 0) {
nghttp2_hd_entry_free(new_ent);
free(new_ent);
} else if(new_ent->nv.name != NULL) {
/* new_ent->ref > 0 and nv.name is not NULL means that new_ent is
in the reference set and in deflate_hd_table_bufsize */
} else {
/* new_ent->ref > 0 means that new_ent is in the reference
set. */
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
}
incidx = 1;
}
if(index == -1) {
rv = emit_newname_block(buf_ptr, buflen_ptr, offset_ptr, nv, incidx,
deflater->ctx.side);
rv = emit_newname_block(buf_ptr, buflen_ptr, offset_ptr, nv, incidx);
} else {
rv = emit_indname_block(buf_ptr, buflen_ptr, offset_ptr, index,
nv->value, nv->valuelen, incidx,
deflater->ctx.side);
nv->value, nv->valuelen, incidx);
}
if(rv != 0) {
return rv;
@ -1135,8 +1101,20 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
return NGHTTP2_ERR_HEADER_COMP;
}
offset = nv_offset;
if(deflater->ctx.hd_table_bufsize_max >
deflater->deflate_hd_table_bufsize_max) {
rv = emit_table_size(buf_ptr, buflen_ptr, &offset,
deflater->deflate_hd_table_bufsize_max);
if(rv != 0) {
goto fail;
}
deflater->ctx.hd_table_bufsize_max =
deflater->deflate_hd_table_bufsize_max;
}
if(deflater->no_refset) {
rv = emit_indexed0(buf_ptr, buflen_ptr, &offset);
rv = emit_clear_refset(buf_ptr, buflen_ptr, &offset);
if(rv != 0) {
goto fail;
}
@ -1148,7 +1126,7 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
goto fail;
}
}
for(i = 0; i < deflater->ctx.deflate_hd_tablelen; ++i) {
for(i = 0; i < deflater->ctx.hd_table.len; ++i) {
nghttp2_hd_entry *ent = nghttp2_hd_ringbuf_get(&deflater->ctx.hd_table, i);
rv = deflate_post_process_hd_entry(ent, i, buf_ptr, buflen_ptr, &offset);
if(rv != 0) {
@ -1414,11 +1392,17 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
DEBUGF(fprintf(stderr, "nghtp2_hd_infalte_hd start state=%d\n",
inflater->state));
hd_inflate_keep_free(inflater);
*inflate_flags = NGHTTP2_HD_INFLATE_NONE;
for(; in != last;) {
switch(inflater->state) {
case NGHTTP2_HD_STATE_OPCODE:
if(*in & 0x80u) {
if(*in == 0x80u) {
DEBUGF(fprintf(stderr, "Encoding context update\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
inflater->state = NGHTTP2_HD_STATE_CONTEXT_UPDATE;
++in;
} else if(*in & 0x80u) {
DEBUGF(fprintf(stderr, "Indexed repr\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
@ -1441,6 +1425,38 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
}
inflater->left = 0;
break;
case NGHTTP2_HD_STATE_CONTEXT_UPDATE:
if(*in & 0x80u) {
if(*in != 0x80u) {
rv = NGHTTP2_ERR_HEADER_COMP;
goto fail;
}
++in;
DEBUGF(fprintf(stderr, "Clearing reference set\n"));
clear_refset(&inflater->ctx);
inflater->state = NGHTTP2_HD_STATE_OPCODE;
break;
}
/* Header table size change */
DEBUGF(fprintf(stderr, "Header table size change\n"));
inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
break;
case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
rfin = 0;
rv = hd_inflate_read_len(inflater, &rfin, in, last, 7,
inflater->settings_hd_table_bufsize_max);
if(rv < 0) {
goto fail;
}
in += rv;
if(!rfin) {
return in - first;
}
DEBUGF(fprintf(stderr, "table_size=%zd\n", inflater->left));
inflater->ctx.hd_table_bufsize_max = inflater->left;
hd_context_shrink_table_size(&inflater->ctx);
inflater->state = NGHTTP2_HD_STATE_OPCODE;
break;
case NGHTTP2_HD_STATE_READ_INDEX:
rfin = 0;
rv = hd_inflate_read_len(inflater, &rfin, in, last,
@ -1457,12 +1473,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
DEBUGF(fprintf(stderr, "index=%zd\n", inflater->left));
if(inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
inflater->index = inflater->left;
if(inflater->index == 0) {
DEBUGF(fprintf(stderr, "Clearing reference set\n"));
clear_refset(&inflater->ctx);
inflater->state = NGHTTP2_HD_STATE_OPCODE;
break;
}
assert(inflater->index > 0);
--inflater->index;
rv = hd_inflate_commit_indexed(inflater, nv_out);
if(rv < 0) {
@ -1504,8 +1515,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
}
rv = 0;
if(inflater->huffman_encoded) {
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx,
inflater->ctx.side);
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
rv = nghttp2_buffer_reserve(&inflater->namebuf,
guess_huff_decode_len(inflater->left));
if(rv != 0) {
@ -1579,8 +1589,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
return in - first;
}
if(inflater->huffman_encoded) {
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx,
inflater->ctx.side);
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
rv = nghttp2_buffer_reserve(&inflater->valuebuf,
guess_huff_decode_len(inflater->left));
inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
@ -1678,19 +1687,21 @@ int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater)
int nghttp2_hd_emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, size_t index,
const uint8_t *value, size_t valuelen,
int inc_indexing,
nghttp2_hd_side side)
int inc_indexing)
{
return emit_indname_block(buf_ptr, buflen_ptr, offset_ptr,
index, value, valuelen, inc_indexing,
side);
index, value, valuelen, inc_indexing);
}
int nghttp2_hd_emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, nghttp2_nv *nv,
int inc_indexing,
nghttp2_hd_side side)
int inc_indexing)
{
return emit_newname_block(buf_ptr, buflen_ptr, offset_ptr, nv, inc_indexing,
side);
return emit_newname_block(buf_ptr, buflen_ptr, offset_ptr, nv, inc_indexing);
}
int nghttp2_hd_emit_table_size(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, size_t table_size)
{
return emit_table_size(buf_ptr, buflen_ptr, offset_ptr, table_size);
}

View File

@ -22,8 +22,8 @@
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGHTTP2_HD_COMP_H
#define NGHTTP2_HD_COMP_H
#ifndef NGHTTP2_HD_H
#define NGHTTP2_HD_H
#ifdef HAVE_CONFIG_H
# include <config.h>
@ -48,11 +48,6 @@
encoder only uses the memory up to this value. */
#define NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE (1 << 12)
typedef enum {
NGHTTP2_HD_SIDE_REQUEST = 0,
NGHTTP2_HD_SIDE_RESPONSE = 1
} nghttp2_hd_side;
typedef enum {
NGHTTP2_HD_ROLE_DEFLATE,
NGHTTP2_HD_ROLE_INFLATE
@ -108,6 +103,8 @@ typedef enum {
typedef enum {
NGHTTP2_HD_STATE_OPCODE,
NGHTTP2_HD_STATE_CONTEXT_UPDATE,
NGHTTP2_HD_STATE_READ_TABLE_SIZE,
NGHTTP2_HD_STATE_READ_INDEX,
NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN,
NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN,
@ -126,30 +123,10 @@ typedef struct {
is the sum of length of name/value in hd_table +
NGHTTP2_HD_ENTRY_OVERHEAD bytes overhead per each entry. */
size_t hd_table_bufsize;
/* The header table size for decoding. If the context is initialized
as encoder, this value is advertised by remote endpoint
decoder. */
/* The effective header table size. */
size_t hd_table_bufsize_max;
/* The current effective header table size for encoding. This value
is always equal to |hd_table_bufsize| on decoder
context. |deflate_hd_table_bufsize| <= |hd_table_bufsize| must be
hold. */
size_t deflate_hd_table_bufsize;
/* The maximum effective header table for encoding. Although header
table size is bounded by |hd_table_bufsize_max|, the encoder can
use smaller buffer by not retaining the header name/values beyond
the |deflate_hd_table_bufsize_max| and not referencing those
entries. This value is always equal to |hd_table_bufsize_max| on
decoder context. */
size_t deflate_hd_table_bufsize_max;
/* The number of effective entry in |hd_table|. This value is always
equal to hd_table.len on decoder side. */
size_t deflate_hd_tablelen;
/* Role of this context; deflate or infalte */
nghttp2_hd_role role;
/* NGHTTP2_HD_SIDE_REQUEST for processing request, otherwise
response. */
nghttp2_hd_side side;
/* If inflate/deflate error occurred, this value is set to 1 and
further invocation of inflate/deflate will fail with
NGHTTP2_ERR_HEADER_COMP. */
@ -158,6 +135,8 @@ typedef struct {
typedef struct {
nghttp2_hd_context ctx;
/* The upper limit of the header table size the deflater accepts. */
size_t deflate_hd_table_bufsize_max;
/* Set to this nonzero to clear reference set on each deflation each
time. */
uint8_t no_refset;
@ -189,6 +168,9 @@ typedef struct {
/* The index of header table to toggle off the entry from reference
set at the end of decompression. */
size_t end_headers_index;
/* The maximum header table size the inflater supports. This is the
same value transmitted in SETTINGS_HEADER_TABLE_SIZE */
size_t settings_hd_table_bufsize_max;
nghttp2_hd_opcode opcode;
nghttp2_hd_inflate_state state;
/* nonzero if string is huffman encoded */
@ -230,8 +212,7 @@ void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater,
nghttp2_hd_side side);
int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater);
/*
* Initializes |deflater| for deflating name/values pairs.
@ -247,7 +228,6 @@ int nghttp2_hd_deflate_init(nghttp2_hd_deflater *deflater,
* Out of memory.
*/
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
nghttp2_hd_side side,
size_t deflate_hd_table_bufsize_max);
/*
@ -259,8 +239,7 @@ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater,
nghttp2_hd_side side);
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater);
/*
* Deallocates any resources allocated for |deflater|.
@ -282,10 +261,11 @@ void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset);
/*
* Changes header table size in |context|. This may trigger eviction
* in the dynamic table.
* Changes header table size of the |deflater|. This may trigger
* eviction in the dynamic table.
*
* This function can be used for deflater and inflater.
* The |settings_hd_table_bufsize_max| should be the value received in
* SETTINGS_HEADER_TABLE_SIZE.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@ -293,8 +273,25 @@ void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_change_table_size(nghttp2_hd_context *context,
size_t hd_table_bufsize_max);
int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t settings_hd_table_bufsize_max);
/*
* Changes header table size in the |inflater|. This may trigger
* eviction in the dynamic table.
*
* The |settings_hd_table_bufsize_max| should be the value transmitted
* in SETTINGS_HEADER_TABLE_SIZE.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
size_t settings_hd_table_bufsize_max);
/*
* Deflates the |nva|, which has the |nvlen| name/value pairs, into
@ -379,14 +376,16 @@ int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
int nghttp2_hd_emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, size_t index,
const uint8_t *value, size_t valuelen,
int inc_indexing,
nghttp2_hd_side side);
int inc_indexing);
/* For unittesting purpose */
int nghttp2_hd_emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, nghttp2_nv *nv,
int inc_indexing,
nghttp2_hd_side side);
int inc_indexing);
/* For unittesting purpose */
int nghttp2_hd_emit_table_size(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, size_t table_size);
/* For unittesting purpose */
nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
@ -395,37 +394,30 @@ nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
/* Huffman encoding/decoding functions */
/*
* Counts the required bytes to encode |src| with length |len|. If
* |side| is NGHTTP2_HD_SIDE_REQUEST, the request huffman code table
* is used. Otherwise, the response code table is used.
* Counts the required bytes to encode |src| with length |len|.
*
* This function returns the number of required bytes to encode given
* data, including padding of prefix of terminal symbol code. This
* function always succeeds.
*/
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len,
nghttp2_hd_side side);
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len);
/*
* Encodes the given data |src| with length |srclen| to the given
* memory location pointed by |dest|, allocated at lest |destlen|
* bytes. The caller is responsible to specify |destlen| at least the
* length that nghttp2_hd_huff_encode_count() returns. If |side| is
* NGHTTP2_HD_SIDE_REQUEST, the request huffman code table is
* used. Otherwise, the response code table is used.
* length that nghttp2_hd_huff_encode_count() returns.
*
* This function returns the number of written bytes, including
* padding of prefix of terminal symbol code. This return value is
* exactly the same with the return value of
* nghttp2_hd_huff_encode_count() if it is given with the same |src|,
* |srclen|, and |side|. This function always succeeds.
* nghttp2_hd_huff_encode_count() if it is given with the same |src|
* and |srclen|. This function always succeeds.
*/
ssize_t nghttp2_hd_huff_encode(uint8_t *dest, size_t destlen,
const uint8_t *src, size_t srclen,
nghttp2_hd_side side);
const uint8_t *src, size_t srclen);
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx,
nghttp2_hd_side side);
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
/*
* Decodes the given data |src| with length |srclen|. The |ctx| must
@ -453,4 +445,4 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_buffer *dest,
const uint8_t *src, size_t srclen, int final);
#endif /* NGHTTP2_HD_COMP_H */
#endif /* NGHTTP2_HD_H */

View File

@ -30,11 +30,8 @@
#include "nghttp2_hd.h"
extern const nghttp2_huff_sym req_huff_sym_table[];
extern const nghttp2_huff_decode req_huff_decode_table[][16];
extern const nghttp2_huff_sym res_huff_sym_table[];
extern const nghttp2_huff_decode res_huff_decode_table[][16];
extern const nghttp2_huff_sym huff_sym_table[];
extern const nghttp2_huff_decode huff_decode_table[][16];
/*
* Encodes huffman code |sym| into |*dest_ptr|, whose least |rembits|
@ -65,18 +62,11 @@ static size_t huff_encode_sym(uint8_t **dest_ptr, size_t rembits,
return rembits;
}
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len,
nghttp2_hd_side side)
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len)
{
size_t i;
size_t nbits = 0;
const nghttp2_huff_sym *huff_sym_table;
if(side == NGHTTP2_HD_SIDE_REQUEST) {
huff_sym_table = req_huff_sym_table;
} else {
huff_sym_table = res_huff_sym_table;
}
for(i = 0; i < len; ++i) {
nbits += huff_sym_table[src[i]].nbits;
}
@ -85,19 +75,12 @@ size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len,
}
ssize_t nghttp2_hd_huff_encode(uint8_t *dest, size_t destlen,
const uint8_t *src, size_t srclen,
nghttp2_hd_side side)
const uint8_t *src, size_t srclen)
{
int rembits = 8;
uint8_t *dest_first = dest;
size_t i;
const nghttp2_huff_sym *huff_sym_table;
if(side == NGHTTP2_HD_SIDE_REQUEST) {
huff_sym_table = req_huff_sym_table;
} else {
huff_sym_table = res_huff_sym_table;
}
for(i = 0; i < srclen; ++i) {
const nghttp2_huff_sym *sym = &huff_sym_table[src[i]];
if(rembits == 8) {
@ -114,14 +97,8 @@ ssize_t nghttp2_hd_huff_encode(uint8_t *dest, size_t destlen,
return dest - dest_first;
}
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx,
nghttp2_hd_side side)
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx)
{
if(side == NGHTTP2_HD_SIDE_REQUEST) {
ctx->huff_decode_table = req_huff_decode_table;
} else {
ctx->huff_decode_table = res_huff_decode_table;
}
ctx->state = 0;
ctx->accept = 1;
}
@ -137,7 +114,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
for(i = 0; i < srclen; ++i) {
uint8_t in = src[i] >> 4;
for(j = 0; j < 2; ++j) {
const nghttp2_huff_decode *t = &ctx->huff_decode_table[ctx->state][in];
const nghttp2_huff_decode *t = &huff_decode_table[ctx->state][in];
if(t->state == -1) {
return NGHTTP2_ERR_HEADER_COMP;
}

View File

@ -52,7 +52,6 @@ typedef struct {
typedef nghttp2_huff_decode huff_decode_table_type[16];
typedef struct {
const huff_decode_table_type *huff_decode_table;
/* Current huffman decoding state. We stripped leaf nodes, so the
value range is [0..255], inclusive. */
uint8_t state;

File diff suppressed because it is too large Load Diff

View File

@ -201,7 +201,7 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
const nghttp2_opt_set *opt_set)
{
int r;
nghttp2_hd_side side_deflate, side_inflate;
*session_ptr = malloc(sizeof(nghttp2_session));
if(*session_ptr == NULL) {
r = NGHTTP2_ERR_NOMEM;
@ -236,17 +236,12 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
if(server) {
(*session_ptr)->server = 1;
side_deflate = NGHTTP2_HD_SIDE_RESPONSE;
side_inflate = NGHTTP2_HD_SIDE_REQUEST;
} else {
side_deflate = NGHTTP2_HD_SIDE_REQUEST;
side_inflate = NGHTTP2_HD_SIDE_RESPONSE;
}
r = nghttp2_hd_deflate_init(&(*session_ptr)->hd_deflater, side_deflate);
r = nghttp2_hd_deflate_init(&(*session_ptr)->hd_deflater);
if(r != 0) {
goto fail_hd_deflater;
}
r = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater, side_inflate);
r = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater);
if(r != 0) {
goto fail_hd_inflater;
}
@ -2708,8 +2703,8 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
header_table_size > NGHTTP2_MAX_HEADER_TABLE_SIZE) {
return NGHTTP2_ERR_HEADER_COMP;
}
rv = nghttp2_hd_change_table_size(&session->hd_inflater.ctx,
header_table_size);
rv = nghttp2_hd_inflate_change_table_size(&session->hd_inflater,
header_table_size);
if(rv != 0) {
return rv;
}
@ -2791,8 +2786,8 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
return nghttp2_session_handle_invalid_connection
(session, frame, NGHTTP2_COMPRESSION_ERROR);
}
rv = nghttp2_hd_change_table_size(&session->hd_deflater.ctx,
entry->value);
rv = nghttp2_hd_deflate_change_table_size(&session->hd_deflater,
entry->value);
if(rv != 0) {
if(nghttp2_is_fatal(rv)) {
return rv;

View File

@ -45,10 +45,6 @@ cdef extern from 'nghttp2_hd.h':
# This is macro
int NGHTTP2_HD_ENTRY_OVERHEAD
ctypedef enum nghttp2_hd_side:
NGHTTP2_HD_SIDE_REQUEST
NGHTTP2_HD_SIDE_RESPONSE
ctypedef enum nghttp2_hd_flags:
NGHTTP2_HD_FLAG_REFSET
@ -73,12 +69,9 @@ cdef extern from 'nghttp2_hd.h':
nghttp2_hd_context ctx
int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater,
nghttp2_hd_side side,
size_t deflate_hd_table_bufsize_max)
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater,
nghttp2_hd_side side)
int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater)
void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater)
@ -87,8 +80,11 @@ cdef extern from 'nghttp2_hd.h':
void nghttp2_hd_deflate_set_no_refset(nghttp2_hd_deflater *deflater,
uint8_t no_refset)
int nghttp2_hd_change_table_size(nghttp2_hd_context *context,
size_t hd_table_bufsize_max)
int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater,
size_t hd_table_bufsize_max)
int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
size_t hd_table_bufsize_max)
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
uint8_t **buf_ptr, size_t *buflen_ptr,

View File

@ -13,12 +13,7 @@ from binascii import a2b_hex
import nghttp2
def testsuite(testdata):
if testdata['context'] == 'request':
side = nghttp2.HD_SIDE_REQUEST
else:
side = nghttp2.HD_SIDE_RESPONSE
inflater = nghttp2.HDInflater(side)
inflater = nghttp2.HDInflater()
for casenum, item in enumerate(testdata['cases']):
if 'header_table_size' in item:
@ -47,7 +42,7 @@ def testsuite(testdata):
if __name__ == '__main__':
for filename in sys.argv[1:]:
sys.stderr.write('{}\n'.format(filename))
sys.stderr.write('{}: '.format(filename))
with open(filename) as f:
input = f.read()
testsuite(json.loads(input))

View File

@ -14,11 +14,6 @@ from binascii import b2a_hex
import nghttp2
def testsuite(testdata, filename, outdir, table_size, deflate_table_size):
if testdata['context'] == 'request':
side = nghttp2.HD_SIDE_REQUEST
else:
side = nghttp2.HD_SIDE_RESPONSE
res = {
'draft':5, 'context': testdata['context'],
'description': '''\
@ -29,7 +24,7 @@ original. We make some headers not indexing at all, but this does not always \
result in less bits on the wire.'''
}
cases = []
deflater = nghttp2.HDDeflater(side, deflate_table_size)
deflater = nghttp2.HDDeflater(deflate_table_size)
deflater.change_table_size(table_size)
for casenum, item in enumerate(testdata['cases']):
outitem = {

View File

@ -26,9 +26,6 @@ from libc.stdlib cimport malloc, free
from libc.string cimport memcpy, memset
from libc.stdint cimport uint8_t, uint16_t, uint32_t, int32_t
HD_SIDE_REQUEST = cnghttp2.NGHTTP2_HD_SIDE_REQUEST
HD_SIDE_RESPONSE = cnghttp2.NGHTTP2_HD_SIDE_RESPONSE
HD_DEFLATE_HD_TABLE_BUFSIZE_MAX = 4096
HD_ENTRY_OVERHEAD = cnghttp2.NGHTTP2_HD_ENTRY_OVERHEAD
@ -45,12 +42,6 @@ class HDTableEntry:
def space(self):
return self.namelen + self.valuelen + HD_ENTRY_OVERHEAD
cdef _change_table_size(cnghttp2.nghttp2_hd_context *ctx, hd_table_bufsize_max):
cdef int rv
rv = cnghttp2.nghttp2_hd_change_table_size(ctx, hd_table_bufsize_max)
if rv != 0:
raise Exception(_strerror(rv))
cdef _get_hd_table(cnghttp2.nghttp2_hd_context *ctx):
cdef int length = ctx.hd_table.len
cdef cnghttp2.nghttp2_hd_entry *entry
@ -65,35 +56,25 @@ cdef _get_hd_table(cnghttp2.nghttp2_hd_context *ctx):
return res
cdef _get_pybytes(uint8_t *b, uint16_t blen):
# While the |blen| is positive, the |b| could be NULL. This is
# because deflater may deallocate the byte strings its local table
# space.
if b == NULL and blen > 0:
val = None
else:
val = b[:blen]
return val
return b[:blen]
cdef class HDDeflater:
'''Performs header compression. The header compression algorithm has
to know the header set to be compressed is request headers or
response headers. It is indicated by |side| parameter in the
constructor. The constructor also takes |hd_table_bufsize_max|
parameter, which limits the usage of header table in the given
amount of bytes. This is necessary because the header compressor
and decompressor has to share the same amount of header table and
the decompressor decides that number. The compressor may not want
to use all header table size because of limited memory
availability. In that case, the |hd_table_bufsize_max| can be used
to cap the upper limit of talbe size whatever the header table
size is chosen. The default value of |hd_table_bufsize_max| is
4096 bytes.
'''Performs header compression. The constructor takes
|hd_table_bufsize_max| parameter, which limits the usage of header
table in the given amount of bytes. This is necessary because the
header compressor and decompressor has to share the same amount of
header table and the decompressor decides that number. The
compressor may not want to use all header table size because of
limited memory availability. In that case, the
|hd_table_bufsize_max| can be used to cap the upper limit of table
size whatever the header table size is chosen by the decompressor.
The default value of |hd_table_bufsize_max| is 4096 bytes.
The following example shows how to compress request header sets:
import binascii, nghttp2
deflater = nghttp2.HDDeflater(nghttp2.HD_SIDE_REQUEST)
deflater = nghttp2.HDDeflater()
res = deflater.deflate([(b'foo', b'bar'),
(b'baz', b'buz')])
print(binascii.b2a_hex(res))
@ -102,17 +83,13 @@ cdef class HDDeflater:
cdef cnghttp2.nghttp2_hd_deflater _deflater
def __cinit__(self, side,
def __cinit__(self,
hd_table_bufsize_max = HD_DEFLATE_HD_TABLE_BUFSIZE_MAX):
rv = cnghttp2.nghttp2_hd_deflate_init2(&self._deflater, side,
rv = cnghttp2.nghttp2_hd_deflate_init2(&self._deflater,
hd_table_bufsize_max)
if rv != 0:
raise Exception(_strerror(rv))
def __init__(self, side,
hd_table_bufsize_max = HD_DEFLATE_HD_TABLE_BUFSIZE_MAX):
super(HDDeflater, self).__init__()
def __dealloc__(self):
cnghttp2.nghttp2_hd_deflate_free(&self._deflater)
@ -165,7 +142,11 @@ cdef class HDDeflater:
An exception will be raised on error.
'''
_change_table_size(&self._deflater.ctx, hd_table_bufsize_max)
cdef int rv
rv = cnghttp2.nghttp2_hd_deflate_change_table_size(&self._deflater,
hd_table_bufsize_max)
if rv != 0:
raise Exception(_strerror(rv))
def get_hd_table(self,):
'''Returns copy of current dynamic header table.'''
@ -177,7 +158,7 @@ cdef class HDInflater:
The following example shows how to compress request header sets:
data = b'0082c5ad82bd0f000362617a0362757a'
inflater = nghttp2.HDInflater(nghttp2.HD_SIDE_REQUEST)
inflater = nghttp2.HDInflater()
hdrs = inflater.inflate(data)
print(hdrs)
@ -185,14 +166,11 @@ cdef class HDInflater:
cdef cnghttp2.nghttp2_hd_inflater _inflater
def __cinit__(self, side):
rv = cnghttp2.nghttp2_hd_inflate_init(&self._inflater, side)
def __cinit__(self):
rv = cnghttp2.nghttp2_hd_inflate_init(&self._inflater)
if rv != 0:
raise Exception(_strerror(rv))
def __init__(self, side):
super(HDInflater, self).__init__()
def __dealloc__(self):
cnghttp2.nghttp2_hd_inflate_free(&self._inflater)
@ -231,7 +209,11 @@ cdef class HDInflater:
An exception will be raised on error.
'''
_change_table_size(&self._inflater.ctx, hd_table_bufsize_max)
cdef int rv
rv = cnghttp2.nghttp2_hd_inflate_change_table_size(&self._inflater,
hd_table_bufsize_max)
if rv != 0:
raise Exception(_strerror(rv))
def get_hd_table(self):
'''Returns copy of current dynamic header table.'''
@ -255,5 +237,5 @@ def print_hd_table(hdtable):
print('[{}] (s={}) (r={}) {}: {}'\
.format(idx, entry.space(),
'y' if entry.ref else 'n',
'**DEALLOCATED**' if entry.name is None else entry.name.decode('utf-8'),
'**DEALLOCATED**' if entry.value is None else entry.value.decode('utf-8')))
entry.name.decode('utf-8'),
entry.value.decode('utf-8')))

View File

@ -27,11 +27,7 @@
static void dump_val(json_t *jent, const char *key, uint8_t *val, size_t len)
{
if(val == NULL && len > 0) {
json_object_set_new(jent, key, json_string("**DEALLOCATED**"));
} else {
json_object_set_new(jent, key, json_pack("s#", val, len));
}
json_object_set_new(jent, key, json_pack("s#", val, len));
}
json_t* dump_header_table(nghttp2_hd_context *context)
@ -58,12 +54,6 @@ json_t* dump_header_table(nghttp2_hd_context *context)
json_object_set_new(obj, "size", json_integer(context->hd_table_bufsize));
json_object_set_new(obj, "max_size",
json_integer(context->hd_table_bufsize_max));
if(context->role == NGHTTP2_HD_ROLE_DEFLATE) {
json_object_set_new(obj, "deflate_size",
json_integer(context->deflate_hd_table_bufsize));
json_object_set_new(obj, "max_deflate_size",
json_integer(context->deflate_hd_table_bufsize_max));
}
return obj;
}
@ -93,13 +83,11 @@ json_t* dump_headers(const nghttp2_nv *nva, size_t nvlen)
return headers;
}
void output_json_header(int side)
void output_json_header(void)
{
printf("{\n"
" \"context\": \"%s\",\n"
" \"cases\":\n"
" [\n",
(side == NGHTTP2_HD_SIDE_REQUEST ? "request" : "response"));
" [\n");
}
void output_json_footer(void)

View File

@ -40,7 +40,7 @@ json_t* dump_header(const uint8_t *name, size_t namelen,
json_t* dump_headers(const nghttp2_nv *nva, size_t nvlen);
void output_json_header(int side);
void output_json_header(void);
void output_json_footer(void);

View File

@ -44,7 +44,6 @@
typedef struct {
size_t table_size;
size_t deflate_table_size;
nghttp2_hd_side side;
int http1text;
int dump_header_table;
int no_refset;
@ -174,11 +173,11 @@ static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
return 0;
}
static void init_deflater(nghttp2_hd_deflater *deflater, nghttp2_hd_side side)
static void init_deflater(nghttp2_hd_deflater *deflater)
{
nghttp2_hd_deflate_init2(deflater, side, 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_change_table_size(&deflater->ctx, config.table_size);
nghttp2_hd_deflate_change_table_size(deflater, config.table_size);
}
static void deinit_deflater(nghttp2_hd_deflater *deflater)
@ -193,19 +192,12 @@ static int perform(void)
json_error_t error;
size_t len;
nghttp2_hd_deflater deflater;
nghttp2_hd_side side;
json = json_loadf(stdin, 0, &error);
if(json == NULL) {
fprintf(stderr, "JSON loading failed\n");
exit(EXIT_FAILURE);
}
if(strcmp("request", json_string_value(json_object_get(json, "context")))
== 0) {
side = NGHTTP2_HD_SIDE_REQUEST;
} else {
side = NGHTTP2_HD_SIDE_RESPONSE;
}
cases = json_object_get(json, "cases");
if(cases == NULL) {
fprintf(stderr, "Missing 'cases' key in root object\n");
@ -215,8 +207,8 @@ static int perform(void)
fprintf(stderr, "'cases' must be JSON array\n");
exit(EXIT_FAILURE);
}
init_deflater(&deflater, side);
output_json_header(side);
init_deflater(&deflater);
output_json_header();
len = json_array_size(cases);
for(i = 0; i < len; ++i) {
json_t *obj = json_array_get(cases, i);
@ -244,8 +236,8 @@ static int perform_from_http1text(void)
nghttp2_nv nva[256];
int seq = 0;
nghttp2_hd_deflater deflater;
init_deflater(&deflater, config.side);
output_json_header(config.side);
init_deflater(&deflater);
output_json_header();
for(;;) {
size_t nvlen = 0;
int end = 0;
@ -355,10 +347,6 @@ static void print_help(void)
"The output of this program can be used as input for inflatehd.\n"
"\n"
"OPTIONS:\n"
" -r, --response Use response compression context instead of\n"
" request if -t is used. For JSON input, it is\n"
" determined by inspecting \"context\" key in\n"
" root JSON object.\n"
" -t, --http1text Use HTTP/1 style header field text as input.\n"
" Each header set is delimited by single empty\n"
" line.\n"
@ -377,7 +365,6 @@ static void print_help(void)
}
static struct option long_options[] = {
{"response", no_argument, NULL, 'r'},
{"http1text", no_argument, NULL, 't'},
{"table-size", required_argument, NULL, 's'},
{"deflate-table-size", required_argument, NULL, 'S'},
@ -390,7 +377,6 @@ int main(int argc, char **argv)
{
char *end;
config.side = NGHTTP2_HD_SIDE_REQUEST;
config.table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
config.deflate_table_size = NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE;
config.http1text = 0;
@ -398,15 +384,11 @@ int main(int argc, char **argv)
config.no_refset = 0;
while(1) {
int option_index = 0;
int c = getopt_long(argc, argv, "S:cdhrs:t", long_options, &option_index);
int c = getopt_long(argc, argv, "S:cdhs:t", long_options, &option_index);
if(c == -1) {
break;
}
switch(c) {
case 'r':
/* --response */
config.side = NGHTTP2_HD_SIDE_RESPONSE;
break;
case 'h':
print_help();
exit(EXIT_SUCCESS);

View File

@ -42,7 +42,6 @@
#include "comp_helper.h"
typedef struct {
size_t table_size;
int dump_header_table;
} inflate_config;
@ -110,8 +109,8 @@ static int inflate_hd(json_t *obj, nghttp2_hd_inflater *inflater, int seq)
seq);
return -1;
}
rv = nghttp2_hd_change_table_size(&inflater->ctx,
json_integer_value(table_size));
rv = nghttp2_hd_inflate_change_table_size(inflater,
json_integer_value(table_size));
if(rv != 0) {
fprintf(stderr,
"nghttp2_hd_change_table_size() failed with error %s at %d\n",
@ -163,19 +162,12 @@ static int perform(void)
json_t *json, *cases;
json_error_t error;
size_t len;
nghttp2_hd_side side;
json = json_loadf(stdin, 0, &error);
if(json == NULL) {
fprintf(stderr, "JSON loading failed\n");
exit(EXIT_FAILURE);
}
if(strcmp("request", json_string_value(json_object_get(json, "context")))
== 0) {
side = NGHTTP2_HD_SIDE_REQUEST;
} else {
side = NGHTTP2_HD_SIDE_RESPONSE;
}
cases = json_object_get(json, "cases");
if(cases == NULL) {
fprintf(stderr, "Missing 'cases' key in root object\n");
@ -185,10 +177,8 @@ static int perform(void)
fprintf(stderr, "'cases' must be JSON array\n");
exit(EXIT_FAILURE);
}
nghttp2_hd_inflate_init(&inflater, side);
nghttp2_hd_change_table_size(&inflater.ctx, config.table_size);
output_json_header(side);
nghttp2_hd_inflate_init(&inflater);
output_json_header();
len = json_array_size(cases);
for(i = 0; i < len; ++i) {
json_t *obj = json_array_get(cases, i);
@ -241,29 +231,21 @@ static void print_help(void)
"The output of this program can be used as input for deflatehd.\n"
"\n"
"OPTIONS:\n"
" -s, --table-size=<N>\n"
" Set dynamic table size. In the HPACK\n"
" specification, this value is denoted by\n"
" SETTINGS_HEADER_TABLE_SIZE.\n"
" Default: 4096\n"
" -d, --dump-header-table\n"
" Output dynamic header table.\n");
}
static struct option long_options[] = {
{"table-size", required_argument, NULL, 's'},
{"dump-header-table", no_argument, NULL, 'd'},
{NULL, 0, NULL, 0 }
};
int main(int argc, char **argv)
{
char *end;
config.table_size = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
config.dump_header_table = 0;
while(1) {
int option_index = 0;
int c = getopt_long(argc, argv, "dhs:", long_options, &option_index);
int c = getopt_long(argc, argv, "dh", long_options, &option_index);
if(c == -1) {
break;
}
@ -271,15 +253,6 @@ int main(int argc, char **argv)
case 'h':
print_help();
exit(EXIT_SUCCESS);
case 's':
/* --table-size */
errno = 0;
config.table_size = strtoul(optarg, &end, 10);
if(errno == ERANGE || *end != '\0') {
fprintf(stderr, "-s: Bad option value\n");
exit(EXIT_FAILURE);
}
break;
case 'd':
/* --dump-header-table */
config.dump_header_table = 1;

View File

@ -225,8 +225,6 @@ int main(int argc, char* argv[])
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_deflate_buffer",
test_nghttp2_hd_deflate_deflate_buffer) ||
!CU_add_test(pSuite, "hd_deflate_clear_refset",
test_nghttp2_hd_deflate_clear_refset) ||
!CU_add_test(pSuite, "hd_inflate_indname_noinc",

View File

@ -82,8 +82,8 @@ void test_nghttp2_frame_pack_headers()
ssize_t nv_offset;
nva_out_init(&out);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater);
nva = headers();
nvlen = HEADERS_LENGTH;
@ -171,7 +171,7 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
}
nvlen = nghttp2_nv_array_copy(&nva, big_hds, big_hdslen);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
nghttp2_frame_headers_init(&frame,
NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS,
1000000007,
@ -269,8 +269,8 @@ void test_nghttp2_frame_pack_push_promise()
nva_out out;
nva_out_init(&out);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_RESPONSE);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_RESPONSE);
nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater);
nva = headers();
nvlen = HEADERS_LENGTH;

View File

@ -59,8 +59,8 @@ void test_nghttp2_hd_deflate(void)
nva_out out;
nva_out_init(&out);
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST));
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST));
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater));
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater));
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, nv_offset, nva1,
sizeof(nva1)/sizeof(nghttp2_nv));
CU_ASSERT(blocklen > 0);
@ -142,8 +142,8 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
nva_out out;
nva_out_init(&out);
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST));
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST));
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater));
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater));
/* Encode 2 same headers. cookie:alpha is not in the reference set,
so first emit literal repr and then 2 emits of indexed repr. */
@ -198,8 +198,8 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
nva[i].valuelen = sizeof(value);
}
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater);
/* First emit "h1: ..." to put it in the reference set (index
= 0). */
@ -236,174 +236,6 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
nghttp2_hd_deflate_free(&deflater);
}
void test_nghttp2_hd_deflate_deflate_buffer(void)
{
nghttp2_hd_deflater deflater;
nghttp2_hd_inflater inflater;
size_t i;
ssize_t blocklen;
uint8_t *buf = NULL;
size_t buflen = 0;
nghttp2_nv nva1[] = { MAKE_NV("k1", "v1"), /* 36 */
MAKE_NV("k10", "v10"), /* 38 */
MAKE_NV("k100", "v100"), /* 40 */
MAKE_NV("k1000", "v1000") /* 42 */
}; /* Total: 156 */
nghttp2_nv nva2[] = { MAKE_NV("k10", "v10"), /* 38 */
MAKE_NV("k1", "v1") /* 36 */
};
nghttp2_nv nv3;
uint8_t val[256];
nghttp2_nv nva4[] = { MAKE_NV(":method", "GET"),
MAKE_NV(":scheme", "http")
};
nghttp2_hd_entry *ent;
nva_out out;
nva_out_init(&out);
memset(val, 'a', sizeof(val));
nv3.name = nv3.value = val;
nv3.namelen = nv3.valuelen = sizeof(val);
/* Check the case where entry from static table is inserted to
dynamic header table. And it is out of deflate header table
size. */
nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, 32);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
nva4, ARRLEN(nva4));
CU_ASSERT(blocklen > 0);
/* Now header table should look like this:
*
* 0: :scheme, http (-)
* 1: :method, GET (-)
*
* name/value of all entries must be NULL.
*/
CU_ASSERT(2 == deflater.ctx.hd_table.len);
CU_ASSERT(0 == deflater.ctx.deflate_hd_tablelen);
CU_ASSERT(0 == deflater.ctx.deflate_hd_table_bufsize);
for(i = 0; i < 2; ++i) {
ent = nghttp2_hd_table_get(&deflater.ctx, i);
CU_ASSERT(ent->nv.name == NULL);
CU_ASSERT(ent->nv.value == NULL);
CU_ASSERT(0 == (ent->flags & NGHTTP2_HD_FLAG_REFSET));
}
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf, blocklen));
CU_ASSERT(2 == out.nvlen);
assert_nv_equal(nva4, out.nva, 2);
nva_out_reset(&out);
nghttp2_hd_deflate_free(&deflater);
nghttp2_hd_inflate_free(&inflater);
/* 156 buffer size can hold all headers in deflate region */
nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, 156);
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
nva1, ARRLEN(nva1));
CU_ASSERT(blocklen > 0);
/* Now header table should look like this:
*
* 0: k1000, v100
* 1: k100, v100
* 2: k10, v10
* 3: k1, v1
*/
CU_ASSERT(4 == deflater.ctx.hd_table.len);
CU_ASSERT(4 == deflater.ctx.deflate_hd_tablelen);
CU_ASSERT(156 == deflater.ctx.deflate_hd_table_bufsize);
for(i = 0; i < 4; ++i) {
CU_ASSERT(nghttp2_hd_table_get(&deflater.ctx, i)->nv.name != NULL);
CU_ASSERT(nghttp2_hd_table_get(&deflater.ctx, i)->nv.value != NULL);
}
CU_ASSERT(0 == nghttp2_hd_change_table_size(&deflater.ctx, 156));
CU_ASSERT(4 == deflater.ctx.hd_table.len);
CU_ASSERT(4 == deflater.ctx.deflate_hd_tablelen);
CU_ASSERT(156 == deflater.ctx.deflate_hd_table_bufsize);
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, &nv3, 1);
CU_ASSERT(blocklen > 0);
/* Now header table should be unchanged, because we don't index
large header */
CU_ASSERT(4 == deflater.ctx.hd_table.len);
CU_ASSERT(4 == deflater.ctx.deflate_hd_tablelen);
CU_ASSERT(156 == deflater.ctx.deflate_hd_table_bufsize);
nghttp2_hd_deflate_free(&deflater);
/* Check more complex use case */
nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, 155);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
nva1, ARRLEN(nva1));
CU_ASSERT(blocklen > 0);
/* Now header table should look like this:
*
* 0: k1000, v100 (R)
* 1: k100, v100 (R)
* 2: k10, v10 (R)
* 3: k1, v1 (-) <- name, value must be NULL and not in reference set
*
* But due to the deflate table size limit, name/value of index=3 must
* be NULL.
*/
CU_ASSERT(4 == deflater.ctx.hd_table.len);
CU_ASSERT(3 == deflater.ctx.deflate_hd_tablelen);
CU_ASSERT(120 == deflater.ctx.deflate_hd_table_bufsize);
for(i = 0; i < 3; ++i) {
CU_ASSERT(nghttp2_hd_table_get(&deflater.ctx, i)->nv.name != NULL);
CU_ASSERT(nghttp2_hd_table_get(&deflater.ctx, i)->nv.value != NULL);
}
ent = nghttp2_hd_table_get(&deflater.ctx, 3);
CU_ASSERT(ent->nv.name == NULL);
CU_ASSERT(ent->nv.value == NULL);
CU_ASSERT(0 == (ent->flags & NGHTTP2_HD_FLAG_REFSET));
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf, blocklen));
CU_ASSERT(4 == out.nvlen);
assert_nv_equal(nva1, out.nva, 4);
nva_out_reset(&out);
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
nva2, ARRLEN(nva2));
CU_ASSERT(blocklen > 0);
/* Now header table should look like this:
*
* 0: k1, v1 (R)
* 1: k1000, v100 (R)
* 2: k100, v100 (R)
* 3: k10, v10 (-) <- name, value must be NULL
* 4: k1, v1 (-) <- name, value must be NULL
*/
CU_ASSERT(5 == deflater.ctx.hd_table.len);
CU_ASSERT(3 == deflater.ctx.deflate_hd_tablelen);
CU_ASSERT(118 == deflater.ctx.deflate_hd_table_bufsize);
ent = nghttp2_hd_table_get(&deflater.ctx, 3);
CU_ASSERT(0 == (ent->flags & NGHTTP2_HD_FLAG_REFSET));
ent = nghttp2_hd_table_get(&deflater.ctx, 3);
CU_ASSERT(0 == (ent->flags & NGHTTP2_HD_FLAG_REFSET));
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf, blocklen));
CU_ASSERT(2 == out.nvlen);
/* Sort before comparison */
nghttp2_nv_array_sort(nva2, 2);
assert_nv_equal(nva2, out.nva, 2);
nva_out_reset(&out);
free(buf);
nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater);
}
void test_nghttp2_hd_deflate_clear_refset(void)
{
nghttp2_hd_deflater deflater;
@ -419,10 +251,10 @@ void test_nghttp2_hd_deflate_clear_refset(void)
nva_out out;
nva_out_init(&out);
nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST,
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, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
for(i = 0; i < 2; ++i) {
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
@ -457,14 +289,13 @@ void test_nghttp2_hd_inflate_indname_noinc(void)
nva_out out;
nva_out_init(&out);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
for(i = 0; i < ARRLEN(nv); ++i) {
offset = 0;
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 56,
nv[i].value, nv[i].valuelen,
0,
NGHTTP2_HD_SIDE_REQUEST));
0));
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
CU_ASSERT(1 == out.nvlen);
@ -488,11 +319,10 @@ void test_nghttp2_hd_inflate_indname_inc(void)
nva_out out;
nva_out_init(&out);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 56,
nv.value, nv.valuelen, 1,
NGHTTP2_HD_SIDE_REQUEST));
nv.value, nv.valuelen, 1));
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
CU_ASSERT(1 == out.nvlen);
@ -517,21 +347,17 @@ void test_nghttp2_hd_inflate_indname_inc_eviction(void)
nva_out out;
nva_out_init(&out);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
memset(value, '0', sizeof(value));
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 13,
value, sizeof(value), 1,
NGHTTP2_HD_SIDE_REQUEST));
value, sizeof(value), 1));
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 14,
value, sizeof(value), 1,
NGHTTP2_HD_SIDE_REQUEST));
value, sizeof(value), 1));
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 15,
value, sizeof(value), 1,
NGHTTP2_HD_SIDE_REQUEST));
value, sizeof(value), 1));
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 16,
value, sizeof(value), 1,
NGHTTP2_HD_SIDE_REQUEST));
value, sizeof(value), 1));
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
@ -569,12 +395,11 @@ void test_nghttp2_hd_inflate_newname_noinc(void)
nva_out out;
nva_out_init(&out);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
for(i = 0; i < ARRLEN(nv); ++i) {
offset = 0;
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
&nv[i], 0,
NGHTTP2_HD_SIDE_REQUEST));
&nv[i], 0));
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
CU_ASSERT(1 == out.nvlen);
@ -598,11 +423,10 @@ void test_nghttp2_hd_inflate_newname_inc(void)
nva_out out;
nva_out_init(&out);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
&nv, 1,
NGHTTP2_HD_SIDE_REQUEST));
&nv, 1));
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
CU_ASSERT(1 == out.nvlen);
@ -635,11 +459,10 @@ void test_nghttp2_hd_inflate_clearall_inc(void)
nv.value = value;
nv.valuelen = sizeof(value);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
&nv, 1,
NGHTTP2_HD_SIDE_REQUEST));
&nv, 1));
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
CU_ASSERT(1 == out.nvlen);
@ -663,8 +486,7 @@ void test_nghttp2_hd_inflate_clearall_inc(void)
offset = 0;
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
&nv, 1,
NGHTTP2_HD_SIDE_REQUEST));
&nv, 1));
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
CU_ASSERT(1 == out.nvlen);
@ -690,7 +512,7 @@ void test_nghttp2_hd_inflate_zero_length_huffman(void)
buf[2] = 'x';
buf[3] = 0x80;
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(4 == inflate_hd(&inflater, &out, buf, 4));
CU_ASSERT(1 == out.nvlen);
@ -706,35 +528,158 @@ void test_nghttp2_hd_inflate_zero_length_huffman(void)
void test_nghttp2_hd_change_table_size(void)
{
nghttp2_hd_deflater deflater;
nghttp2_hd_inflater inflater;
nghttp2_nv nva[] = { MAKE_NV(":method", "GET"),
MAKE_NV(":path", "/") };
uint8_t *buf = NULL;
size_t buflen = 0;
ssize_t rv;
nva_out out;
size_t offset;
nva_out_init(&out);
nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater);
/* inflater changes notifies 8000 max header table size */
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000));
CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000));
CU_ASSERT(127 == deflater.ctx.hd_table.mask);
CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(255 == inflater.ctx.hd_table.mask);
CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
/* This will emit encoding context update with header table size 4096 */
rv = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva, 2);
CU_ASSERT(rv > 0);
CU_ASSERT(2 == deflater.ctx.hd_table.len);
CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf, rv));
CU_ASSERT(2 == inflater.ctx.hd_table.len);
CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
nva_out_reset(&out);
/* inflater changes header table size to 1024 */
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 1024));
CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 1024));
CU_ASSERT(127 == deflater.ctx.hd_table.mask);
CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(255 == inflater.ctx.hd_table.mask);
CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
rv = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva, 2);
CU_ASSERT(rv >= 0);
CU_ASSERT(2 == deflater.ctx.hd_table.len);
CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf, rv));
CU_ASSERT(2 == inflater.ctx.hd_table.len);
CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
nva_out_reset(&out);
/* inflater changes header table size to 0 */
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 0));
CU_ASSERT(127 == deflater.ctx.hd_table.mask);
CU_ASSERT(0 == deflater.ctx.hd_table.len);
CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(255 == inflater.ctx.hd_table.mask);
CU_ASSERT(0 == inflater.ctx.hd_table.len);
CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
rv = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva, 2);
CU_ASSERT(rv >= 0);
CU_ASSERT(0 == deflater.ctx.hd_table.len);
CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf, rv));
CU_ASSERT(0 == inflater.ctx.hd_table.len);
CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
nva_out_reset(&out);
free(buf);
nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater);
/* Check table buffer is expanded */
buf = NULL;
buflen = 0;
nghttp2_hd_deflate_init2(&deflater, 8192);
nghttp2_hd_inflate_init(&inflater);
/* First inflater changes header table size to 8000 */
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 8000));
CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 8000));
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
CU_ASSERT(0 == nghttp2_hd_change_table_size(&deflater.ctx, 8000));
CU_ASSERT(255 == deflater.ctx.hd_table.mask);
CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(255 == inflater.ctx.hd_table.mask);
CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
rv = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva, 2);
CU_ASSERT(rv > 0);
CU_ASSERT(2 == deflater.ctx.hd_table.len);
CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(0 == nghttp2_hd_change_table_size(&deflater.ctx, 16384));
CU_ASSERT(511 == deflater.ctx.hd_table.mask);
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf, rv));
CU_ASSERT(2 == inflater.ctx.hd_table.len);
CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
nva_out_reset(&out);
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 16383));
CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 16383));
CU_ASSERT(255 == deflater.ctx.hd_table.mask);
CU_ASSERT(16383 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(511 == inflater.ctx.hd_table.mask);
CU_ASSERT(16383 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
rv = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva, 2);
CU_ASSERT(rv >= 0);
CU_ASSERT(2 == deflater.ctx.hd_table.len);
CU_ASSERT(2 == deflater.ctx.deflate_hd_tablelen);
CU_ASSERT(5 ==
deflater.ctx.hd_table.buffer[deflater.ctx.hd_table.first]
->nv.namelen);
CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max);
CU_ASSERT(0 == nghttp2_hd_change_table_size(&deflater.ctx, 0));
CU_ASSERT(511 == deflater.ctx.hd_table.mask);
CU_ASSERT(0 == deflater.ctx.hd_table.len);
CU_ASSERT(0 == deflater.ctx.deflate_hd_tablelen);
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf, rv));
CU_ASSERT(2 == inflater.ctx.hd_table.len);
CU_ASSERT(8192 == inflater.ctx.hd_table_bufsize_max);
CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
nva_out_reset(&out);
/* Lastly, check the error condition */
offset = 0;
rv = nghttp2_hd_emit_table_size(&buf, &buflen, &offset, 25600);
CU_ASSERT(rv == 0);
CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
inflate_hd(&inflater, &out, buf, offset));
nva_out_reset(&out);
free(buf);
nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater);
}
@ -899,8 +844,8 @@ void test_nghttp2_hd_deflate_inflate(void)
MAKE_NV("x-cache-lookup", "HIT from alphabravo:3128"),
};
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater);
check_deflate_inflate(&deflater, &inflater, nv1, ARRLEN(nv1));
check_deflate_inflate(&deflater, &inflater, nv2, ARRLEN(nv2));

View File

@ -28,7 +28,6 @@
void test_nghttp2_hd_deflate(void);
void test_nghttp2_hd_deflate_same_indexed_repr(void);
void test_nghttp2_hd_deflate_common_header_eviction(void);
void test_nghttp2_hd_deflate_deflate_buffer(void);
void test_nghttp2_hd_deflate_clear_refset(void);
void test_nghttp2_hd_inflate_indname_noinc(void);
void test_nghttp2_hd_inflate_indname_inc(void);

View File

@ -363,7 +363,7 @@ void test_nghttp2_session_recv(void)
callbacks.on_frame_recv_callback = on_frame_recv_callback;
user_data.df = &df;
nghttp2_session_server_new(&session, &callbacks, &user_data);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
@ -446,7 +446,7 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
user_data.df = &df;
user_data.invalid_frame_recv_cb_called = 0;
nghttp2_session_server_new(&session, &callbacks, &user_data);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
NGHTTP2_PRI_DEFAULT, NULL, 0);
@ -491,7 +491,7 @@ void test_nghttp2_session_recv_invalid_frame(void)
user_data.df = &df;
user_data.frame_send_cb_called = 0;
nghttp2_session_server_new(&session, &callbacks, &user_data);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NGHTTP2_PRI_DEFAULT, nva, nvlen);
@ -690,7 +690,7 @@ void test_nghttp2_session_recv_continuation(void)
nghttp2_session_server_new(&session, &callbacks, &ud);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
/* Make 1 HEADERS and insert CONTINUATION header */
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
@ -746,7 +746,7 @@ void test_nghttp2_session_recv_continuation(void)
/* Expecting CONTINUATION, but get the other frame */
nghttp2_session_server_new(&session, &callbacks, &ud);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
/* HEADERS without END_HEADERS flag */
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
@ -803,7 +803,7 @@ void test_nghttp2_session_recv_premature_headers(void)
nghttp2_session_server_new(&session, &callbacks, &ud);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
@ -867,7 +867,7 @@ void test_nghttp2_session_continue(void)
nghttp2_session_server_new(&session, &callbacks, &user_data);
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_deflate_init(&deflater);
/* Make 2 HEADERS frames */
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
@ -2255,7 +2255,7 @@ void test_nghttp2_submit_request_without_data(void)
callbacks.send_callback = accumulator_send_callback;
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(0 == nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT,
nva, ARRLEN(nva), &data_prd, NULL));
item = nghttp2_session_get_next_ob_item(session);
@ -2327,7 +2327,7 @@ void test_nghttp2_submit_response_without_data(void)
callbacks.send_callback = accumulator_send_callback;
CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud));
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_RESPONSE);
nghttp2_hd_inflate_init(&inflater);
nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM,
NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_OPENING, NULL);
@ -2499,7 +2499,7 @@ void test_nghttp2_submit_headers(void)
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(0 == nghttp2_submit_headers(session,
NGHTTP2_FLAG_END_STREAM,
1, NGHTTP2_PRI_DEFAULT,