nghttp2_hd: Clear reference set with index 0

This commit is contained in:
Tatsuhiro Tsujikawa 2013-11-16 17:05:18 +09:00
parent 5696a65c5e
commit 3d863ed254
6 changed files with 98 additions and 13 deletions

View File

@ -366,7 +366,8 @@ int main(int argc, char **argv)
break; break;
} }
} }
nghttp2_hd_deflate_init2(&deflater, config.side, config.deflate_table_size); nghttp2_hd_deflate_init2(&deflater, config.side, config.deflate_table_size,
0);
nghttp2_hd_change_table_size(&deflater, config.table_size); nghttp2_hd_change_table_size(&deflater, config.table_size);
if(config.http1text) { if(config.http1text) {
perform_from_http1text(&deflater); perform_from_http1text(&deflater);

View File

@ -246,12 +246,14 @@ static void nghttp2_hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf)
static int nghttp2_hd_context_init(nghttp2_hd_context *context, static int nghttp2_hd_context_init(nghttp2_hd_context *context,
nghttp2_hd_role role, nghttp2_hd_role role,
nghttp2_hd_side side, nghttp2_hd_side side,
size_t deflate_hd_table_bufsize_max) size_t deflate_hd_table_bufsize_max,
uint8_t no_refset)
{ {
int rv; int rv;
context->role = role; context->role = role;
context->side = side; context->side = side;
context->bad = 0; context->bad = 0;
context->no_refset = no_refset;
context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE; context->hd_table_bufsize_max = NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE;
rv = nghttp2_hd_ringbuf_init rv = nghttp2_hd_ringbuf_init
(&context->hd_table, (&context->hd_table,
@ -302,20 +304,24 @@ static int nghttp2_hd_context_init(nghttp2_hd_context *context,
int nghttp2_hd_deflate_init(nghttp2_hd_context *deflater, nghttp2_hd_side side) int nghttp2_hd_deflate_init(nghttp2_hd_context *deflater, nghttp2_hd_side side)
{ {
return nghttp2_hd_context_init(deflater, NGHTTP2_HD_ROLE_DEFLATE, side, return nghttp2_hd_context_init(deflater, NGHTTP2_HD_ROLE_DEFLATE, side,
NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE); NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE,
0);
} }
int nghttp2_hd_deflate_init2(nghttp2_hd_context *deflater, int nghttp2_hd_deflate_init2(nghttp2_hd_context *deflater,
nghttp2_hd_side side, nghttp2_hd_side side,
size_t deflate_hd_table_bufsize_max) size_t deflate_hd_table_bufsize_max,
uint8_t no_refset)
{ {
return nghttp2_hd_context_init(deflater, NGHTTP2_HD_ROLE_DEFLATE, side, return nghttp2_hd_context_init(deflater, NGHTTP2_HD_ROLE_DEFLATE, side,
deflate_hd_table_bufsize_max); deflate_hd_table_bufsize_max,
no_refset);
} }
int nghttp2_hd_inflate_init(nghttp2_hd_context *inflater, nghttp2_hd_side side) int nghttp2_hd_inflate_init(nghttp2_hd_context *inflater, nghttp2_hd_side side)
{ {
return nghttp2_hd_context_init(inflater, NGHTTP2_HD_ROLE_INFLATE, side, 0); return nghttp2_hd_context_init(inflater, NGHTTP2_HD_ROLE_INFLATE, side, 0,
0);
} }
static void nghttp2_hd_context_free(nghttp2_hd_context *context) static void nghttp2_hd_context_free(nghttp2_hd_context *context)
@ -574,6 +580,19 @@ static uint8_t* decode_length(ssize_t *res, uint8_t *in, uint8_t *last,
} }
} }
static int emit_indexed0(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);
if(rv != 0) {
return rv;
}
*(*buf_ptr + *offset_ptr) = 0x80u;
++*offset_ptr;
return 0;
}
static int emit_indexed_block(uint8_t **buf_ptr, size_t *buflen_ptr, static int emit_indexed_block(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t *offset_ptr, size_t index) size_t *offset_ptr, size_t index)
{ {
@ -894,6 +913,15 @@ int nghttp2_hd_change_table_size(nghttp2_hd_context *context,
return 0; return 0;
} }
static void clear_refset(nghttp2_hd_context *context)
{
size_t i;
for(i = 0; i < context->hd_table.len; ++i) {
nghttp2_hd_entry *ent = nghttp2_hd_ringbuf_get(&context->hd_table, i);
ent->flags &= ~NGHTTP2_HD_FLAG_REFSET;
}
}
static int check_index_range(nghttp2_hd_context *context, size_t index) static int check_index_range(nghttp2_hd_context *context, size_t index)
{ {
return index < context->hd_table.len + STATIC_TABLE_LENGTH; return index < context->hd_table.len + STATIC_TABLE_LENGTH;
@ -1066,6 +1094,13 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_context *deflater,
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;
} }
offset = nv_offset; offset = nv_offset;
if(deflater->no_refset) {
rv = emit_indexed0(buf_ptr, buflen_ptr, &offset);
if(rv != 0) {
goto fail;
}
clear_refset(deflater);
}
for(i = 0; i < nvlen; ++i) { for(i = 0; i < nvlen; ++i) {
rv = deflate_nv(deflater, buf_ptr, buflen_ptr, &offset, &nv[i]); rv = deflate_nv(deflater, buf_ptr, buflen_ptr, &offset, &nv[i]);
if(rv != 0) { if(rv != 0) {
@ -1136,10 +1171,14 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
ssize_t index; ssize_t index;
nghttp2_hd_entry *ent; nghttp2_hd_entry *ent;
in = decode_length(&index, in, last, 7); in = decode_length(&index, in, last, 7);
if(index <= 0) { if(index < 0) {
rv = NGHTTP2_ERR_HEADER_COMP; rv = NGHTTP2_ERR_HEADER_COMP;
goto fail; goto fail;
} }
if(index == 0) {
clear_refset(inflater);
continue;
}
--index; --index;
if(!check_index_range(inflater, index)) { if(!check_index_range(inflater, index)) {
rv = NGHTTP2_ERR_HEADER_COMP; rv = NGHTTP2_ERR_HEADER_COMP;

View File

@ -123,6 +123,9 @@ typedef struct {
further invocation of inflate/deflate will fail with further invocation of inflate/deflate will fail with
NGHTTP2_ERR_HEADER_COMP. */ NGHTTP2_ERR_HEADER_COMP. */
uint8_t bad; uint8_t bad;
/* Set to this nonzero to clear reference set on each deflation each
time. */
uint8_t no_refset;
/* Role of this context; deflate or infalte */ /* Role of this context; deflate or infalte */
nghttp2_hd_role role; nghttp2_hd_role role;
/* NGHTTP2_HD_SIDE_REQUEST for processing request, otherwise /* NGHTTP2_HD_SIDE_REQUEST for processing request, otherwise
@ -179,6 +182,9 @@ int nghttp2_hd_deflate_init(nghttp2_hd_context *deflater,
* for header table even if the larger value is specified later in * for header table even if the larger value is specified later in
* nghttp2_hd_change_table_size(). * nghttp2_hd_change_table_size().
* *
* If nonzero is given in the |no_refset|, the encoder first clears
* the reference set each time on deflation.
*
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
@ -187,7 +193,8 @@ int nghttp2_hd_deflate_init(nghttp2_hd_context *deflater,
*/ */
int nghttp2_hd_deflate_init2(nghttp2_hd_context *deflater, int nghttp2_hd_deflate_init2(nghttp2_hd_context *deflater,
nghttp2_hd_side side, nghttp2_hd_side side,
size_t deflate_hd_table_bufsize_max); size_t deflate_hd_table_bufsize_max,
uint8_t no_refset);
/* /*
* Initializes |inflater| for inflating name/values pairs. * Initializes |inflater| for inflating name/values pairs.

View File

@ -233,6 +233,8 @@ int main(int argc, char* argv[])
test_nghttp2_hd_deflate_common_header_eviction) || test_nghttp2_hd_deflate_common_header_eviction) ||
!CU_add_test(pSuite, "hd_deflate_deflate_buffer", !CU_add_test(pSuite, "hd_deflate_deflate_buffer",
test_nghttp2_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", !CU_add_test(pSuite, "hd_inflate_indname_noinc",
test_nghttp2_hd_inflate_indname_noinc) || test_nghttp2_hd_inflate_indname_noinc) ||
!CU_add_test(pSuite, "hd_inflate_indname_inc", !CU_add_test(pSuite, "hd_inflate_indname_inc",

View File

@ -278,7 +278,7 @@ void test_nghttp2_hd_deflate_deflate_buffer(void)
/* Check the case where entry from static table is inserted to /* Check the case where entry from static table is inserted to
dynamic header table. And it is out of deflate header table dynamic header table. And it is out of deflate header table
size. */ size. */
nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, 32); nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, 32, 0);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST); nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
nva4, ARRLEN(nva4)); nva4, ARRLEN(nva4));
@ -310,8 +310,7 @@ void test_nghttp2_hd_deflate_deflate_buffer(void)
nghttp2_hd_inflate_free(&inflater); nghttp2_hd_inflate_free(&inflater);
/* 156 buffer size can hold all headers in deflate region */ /* 156 buffer size can hold all headers in deflate region */
nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, 156, 0);
156);
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
nva1, ARRLEN(nva1)); nva1, ARRLEN(nva1));
CU_ASSERT(blocklen > 0); CU_ASSERT(blocklen > 0);
@ -345,8 +344,7 @@ void test_nghttp2_hd_deflate_deflate_buffer(void)
nghttp2_hd_deflate_free(&deflater); nghttp2_hd_deflate_free(&deflater);
/* Check more complex use case */ /* Check more complex use case */
nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST, 155, 0);
155);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST); nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
nva1, ARRLEN(nva1)); nva1, ARRLEN(nva1));
@ -439,6 +437,43 @@ void test_nghttp2_hd_deflate_deflate_buffer(void)
} }
void test_nghttp2_hd_deflate_clear_refset(void)
{
nghttp2_hd_context deflater, inflater;
uint8_t *buf = NULL;
size_t buflen = 0;
ssize_t blocklen;
nghttp2_nv nv[] = {
MAKE_NV(":path", "/"),
MAKE_NV(":scheme", "http")
};
nghttp2_nv *resnva;
ssize_t nvlen;
size_t i;
nghttp2_hd_deflate_init2(&deflater, NGHTTP2_HD_SIDE_REQUEST,
NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE, 1);
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_REQUEST);
for(i = 0; i < 2; ++i) {
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0,
nv, ARRLEN(nv));
CU_ASSERT(blocklen > 1);
nvlen = nghttp2_hd_inflate_hd(&inflater, &resnva, buf, blocklen);
CU_ASSERT(ARRLEN(nv) == nvlen);
nghttp2_nv_array_sort(resnva, ARRLEN(nv));
assert_nv_equal(nv, resnva, ARRLEN(nv));
nghttp2_hd_end_headers(&inflater);
nghttp2_nv_array_del(resnva);
}
free(buf);
nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater);
}
void test_nghttp2_hd_inflate_indname_noinc(void) void test_nghttp2_hd_inflate_indname_noinc(void)
{ {
nghttp2_hd_context inflater; nghttp2_hd_context inflater;

View File

@ -29,6 +29,7 @@ void test_nghttp2_hd_deflate(void);
void test_nghttp2_hd_deflate_same_indexed_repr(void); void test_nghttp2_hd_deflate_same_indexed_repr(void);
void test_nghttp2_hd_deflate_common_header_eviction(void); void test_nghttp2_hd_deflate_common_header_eviction(void);
void test_nghttp2_hd_deflate_deflate_buffer(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_noinc(void);
void test_nghttp2_hd_inflate_indname_inc(void); void test_nghttp2_hd_inflate_indname_inc(void);
void test_nghttp2_hd_inflate_indname_inc_eviction(void); void test_nghttp2_hd_inflate_indname_inc_eviction(void);