Commit 3d863ed2 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttp2_hd: Clear reference set with index 0

parent 5696a65c
...@@ -366,7 +366,8 @@ int main(int argc, char **argv) ...@@ -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);
......
...@@ -246,12 +246,14 @@ static void nghttp2_hd_ringbuf_pop_back(nghttp2_hd_ringbuf *ringbuf) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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;
......
...@@ -123,6 +123,9 @@ typedef struct { ...@@ -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, ...@@ -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, ...@@ -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.
......
...@@ -233,6 +233,8 @@ int main(int argc, char* argv[]) ...@@ -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",
......
...@@ -278,7 +278,7 @@ void test_nghttp2_hd_deflate_deflate_buffer(void) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
...@@ -29,6 +29,7 @@ void test_nghttp2_hd_deflate(void); ...@@ -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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment