nghttp2_hd: Add static table entry to dynamic table on emission
This commit is contained in:
parent
b193069110
commit
5a81e03497
|
@ -796,7 +796,28 @@ static int deflate_nv(nghttp2_hd_context *deflater,
|
||||||
if(rv != -1) {
|
if(rv != -1) {
|
||||||
size_t index = rv;
|
size_t index = rv;
|
||||||
ent = nghttp2_hd_table_get(deflater, index);
|
ent = nghttp2_hd_table_get(deflater, index);
|
||||||
if((ent->flags & NGHTTP2_HD_FLAG_REFSET) == 0) {
|
if(index >= deflater->hd_table.len) {
|
||||||
|
nghttp2_hd_entry *new_ent;
|
||||||
|
/* It is important to first add entry to the header table and
|
||||||
|
let eviction go. If NGHTTP2_HD_FLAG_IMPLICIT_EMIT entry is
|
||||||
|
evicted, it must be emitted before the |nv|. */
|
||||||
|
new_ent = add_hd_table_incremental(deflater, buf_ptr, buflen_ptr,
|
||||||
|
offset_ptr, &ent->nv,
|
||||||
|
NGHTTP2_HD_FLAG_NONE);
|
||||||
|
if(!new_ent) {
|
||||||
|
return NGHTTP2_ERR_HEADER_COMP;
|
||||||
|
}
|
||||||
|
if(new_ent->ref == 0) {
|
||||||
|
nghttp2_hd_entry_free(new_ent);
|
||||||
|
free(new_ent);
|
||||||
|
} else {
|
||||||
|
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
|
||||||
|
}
|
||||||
|
rv = emit_indexed_block(buf_ptr, buflen_ptr, offset_ptr, index);
|
||||||
|
if(rv != 0) {
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
} else if((ent->flags & NGHTTP2_HD_FLAG_REFSET) == 0) {
|
||||||
ent->flags |= NGHTTP2_HD_FLAG_REFSET | NGHTTP2_HD_FLAG_EMIT;
|
ent->flags |= NGHTTP2_HD_FLAG_REFSET | NGHTTP2_HD_FLAG_EMIT;
|
||||||
rv = emit_indexed_block(buf_ptr, buflen_ptr, offset_ptr, index);
|
rv = emit_indexed_block(buf_ptr, buflen_ptr, offset_ptr, index);
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
|
@ -859,7 +880,12 @@ static int deflate_nv(nghttp2_hd_context *deflater,
|
||||||
if(!new_ent) {
|
if(!new_ent) {
|
||||||
return NGHTTP2_ERR_HEADER_COMP;
|
return NGHTTP2_ERR_HEADER_COMP;
|
||||||
}
|
}
|
||||||
|
if(new_ent->ref == 0) {
|
||||||
|
nghttp2_hd_entry_free(new_ent);
|
||||||
|
free(new_ent);
|
||||||
|
} else {
|
||||||
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
|
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
|
||||||
|
}
|
||||||
incidx = 1;
|
incidx = 1;
|
||||||
}
|
}
|
||||||
if(index == -1) {
|
if(index == -1) {
|
||||||
|
@ -923,14 +949,6 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_context *deflater,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i = 0; deflater->static_hd_table[i]; ++i) {
|
|
||||||
nghttp2_hd_entry *ent = deflater->static_hd_table[i];
|
|
||||||
rv = deflate_post_process_hd_entry(ent, i + deflater->hd_table.len,
|
|
||||||
buf_ptr, buflen_ptr, &offset);
|
|
||||||
if(rv != 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return offset - nv_offset;
|
return offset - nv_offset;
|
||||||
fail:
|
fail:
|
||||||
deflater->bad = 1;
|
deflater->bad = 1;
|
||||||
|
@ -1003,13 +1021,26 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
ent = nghttp2_hd_table_get(inflater, index);
|
ent = nghttp2_hd_table_get(inflater, index);
|
||||||
|
if(index >= (ssize_t)inflater->hd_table.len) {
|
||||||
|
nghttp2_hd_entry *new_ent;
|
||||||
|
new_ent = add_hd_table_incremental(inflater, NULL, NULL, NULL,
|
||||||
|
&ent->nv, NGHTTP2_HD_FLAG_NONE);
|
||||||
|
if(!new_ent) {
|
||||||
|
rv = NGHTTP2_ERR_HEADER_COMP;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
/* new_ent->ref == 0 may be hold but emit_indexed_header
|
||||||
|
tracks new_ent, so there is no leak. */
|
||||||
|
rv = emit_indexed_header(inflater, &nva_out, new_ent);
|
||||||
|
} else {
|
||||||
ent->flags ^= NGHTTP2_HD_FLAG_REFSET;
|
ent->flags ^= NGHTTP2_HD_FLAG_REFSET;
|
||||||
if(ent->flags & NGHTTP2_HD_FLAG_REFSET) {
|
if(ent->flags & NGHTTP2_HD_FLAG_REFSET) {
|
||||||
rv = emit_indexed_header(inflater, &nva_out, ent);
|
rv = emit_indexed_header(inflater, &nva_out, ent);
|
||||||
|
}
|
||||||
|
}
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else if(c == 0x40u || c == 0) {
|
} else if(c == 0x40u || c == 0) {
|
||||||
/* Literal Header Repr - New Name */
|
/* Literal Header Repr - New Name */
|
||||||
nghttp2_nv nv;
|
nghttp2_nv nv;
|
||||||
|
@ -1191,13 +1222,6 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(i = 0; inflater->static_hd_table[i]; ++i) {
|
|
||||||
nghttp2_hd_entry *ent = inflater->static_hd_table[i];
|
|
||||||
rv = inflater_post_process_hd_entry(inflater, ent, &nva_out);
|
|
||||||
if(rv != 0) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nghttp2_nv_array_sort(nva_out.nva, nva_out.nvlen);
|
nghttp2_nv_array_sort(nva_out.nva, nva_out.nvlen);
|
||||||
*nva_ptr = nva_out.nva;
|
*nva_ptr = nva_out.nva;
|
||||||
return nva_out.nvlen;
|
return nva_out.nvlen;
|
||||||
|
|
|
@ -198,13 +198,13 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
|
||||||
size_t buflen = 0;
|
size_t buflen = 0;
|
||||||
ssize_t blocklen;
|
ssize_t blocklen;
|
||||||
nghttp2_nv *resnva;
|
nghttp2_nv *resnva;
|
||||||
/* Default header table capacity is 1262. Adding 2835 bytes,
|
/* Default header table capacity is 4096. Adding 2 byte header name
|
||||||
including overhead, to the table evicts first entry.
|
and 4060 byte value, which is 4094 bytes including overhead, to
|
||||||
use name ":host" which index 2 and value length 2798. */
|
the table evicts first entry. */
|
||||||
uint8_t value[2798];
|
uint8_t value[4060];
|
||||||
|
|
||||||
memset(value, '0', sizeof(value));
|
memset(value, '0', sizeof(value));
|
||||||
nva[1].name = (uint8_t*)":host";
|
nva[1].name = (uint8_t*)"hd";
|
||||||
nva[1].namelen = strlen((const char*)nva[1].name);
|
nva[1].namelen = strlen((const char*)nva[1].name);
|
||||||
nva[1].value = value;
|
nva[1].value = value;
|
||||||
nva[1].valuelen = sizeof(value);
|
nva[1].valuelen = sizeof(value);
|
||||||
|
@ -212,11 +212,20 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
|
||||||
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
|
nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_REQUEST);
|
||||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
|
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
|
||||||
|
|
||||||
/* Put :scheme: http (index = 0) in reference set */
|
/* First emit ":scheme: http" to put it in the reference set (index
|
||||||
GET_TABLE_ENT(&deflater, 0)->flags |= NGHTTP2_HD_FLAG_REFSET;
|
= 0). */
|
||||||
GET_TABLE_ENT(&inflater, 0)->flags |= NGHTTP2_HD_FLAG_REFSET;
|
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva, 1);
|
||||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva,
|
CU_ASSERT(blocklen > 0);
|
||||||
sizeof(nva)/sizeof(nghttp2_nv));
|
nghttp2_hd_end_headers(&deflater);
|
||||||
|
|
||||||
|
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, blocklen));
|
||||||
|
nghttp2_nv_array_sort(nva, 1);
|
||||||
|
assert_nv_equal(nva, resnva, 1);
|
||||||
|
nghttp2_nv_array_del(resnva);
|
||||||
|
nghttp2_hd_end_headers(&inflater);
|
||||||
|
|
||||||
|
/* Encode with large header */
|
||||||
|
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva, 2);
|
||||||
CU_ASSERT(blocklen > 0);
|
CU_ASSERT(blocklen > 0);
|
||||||
nghttp2_hd_end_headers(&deflater);
|
nghttp2_hd_end_headers(&deflater);
|
||||||
|
|
||||||
|
@ -230,6 +239,9 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
|
||||||
nghttp2_nv_array_del(resnva);
|
nghttp2_nv_array_del(resnva);
|
||||||
nghttp2_hd_end_headers(&inflater);
|
nghttp2_hd_end_headers(&inflater);
|
||||||
|
|
||||||
|
CU_ASSERT(1 == deflater.hd_table.len);
|
||||||
|
CU_ASSERT(1 == inflater.hd_table.len);
|
||||||
|
|
||||||
free(buf);
|
free(buf);
|
||||||
nghttp2_hd_inflate_free(&inflater);
|
nghttp2_hd_inflate_free(&inflater);
|
||||||
nghttp2_hd_deflate_free(&deflater);
|
nghttp2_hd_deflate_free(&deflater);
|
||||||
|
|
Loading…
Reference in New Issue