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:
parent
082876d92d
commit
fd88c6160d
339
lib/nghttp2_hd.c
339
lib/nghttp2_hd.c
|
@ -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);
|
||||
}
|
||||
|
|
106
lib/nghttp2_hd.h
106
lib/nghttp2_hd.h
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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')))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue