From 2e5c7f598f375dfada6bf169ff55398d98ef58ce Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 11 May 2014 21:25:27 +0900 Subject: [PATCH] Fix bug HPACK deflater does not send context update after table size change --- lib/nghttp2_hd.c | 30 ++++++++++++++++++------------ lib/nghttp2_hd.h | 3 +++ python/hpackmake.py | 7 +++++-- tests/nghttp2_hd_test.c | 8 ++++---- 4 files changed, 30 insertions(+), 18 deletions(-) diff --git a/lib/nghttp2_hd.c b/lib/nghttp2_hd.c index b0469719..822243fd 100644 --- a/lib/nghttp2_hd.c +++ b/lib/nghttp2_hd.c @@ -326,7 +326,16 @@ int nghttp2_hd_deflate_init2(nghttp2_hd_deflater *deflater, return rv; } deflater->no_refset = 0; + + if(deflate_hd_table_bufsize_max < NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE) { + deflater->notify_table_size_change = 1; + deflater->ctx.hd_table_bufsize_max = deflate_hd_table_bufsize_max; + } else { + deflater->notify_table_size_change = 0; + } + deflater->deflate_hd_table_bufsize_max = deflate_hd_table_bufsize_max; + return 0; } @@ -968,14 +977,10 @@ int nghttp2_hd_deflate_change_table_size(nghttp2_hd_deflater *deflater, return rv; } - deflater->ctx.hd_table_bufsize_max = settings_hd_table_bufsize_max; + deflater->ctx.hd_table_bufsize_max = next_bufsize; + + deflater->notify_table_size_change = 1; - 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; } @@ -1217,14 +1222,15 @@ int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater, return NGHTTP2_ERR_HEADER_COMP; } - if(deflater->ctx.hd_table_bufsize_max > - deflater->deflate_hd_table_bufsize_max) { - rv = emit_table_size(bufs, deflater->deflate_hd_table_bufsize_max); + if(deflater->notify_table_size_change) { + + deflater->notify_table_size_change = 0; + + rv = emit_table_size(bufs, deflater->ctx.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) { diff --git a/lib/nghttp2_hd.h b/lib/nghttp2_hd.h index ef65b4ce..9ec70e72 100644 --- a/lib/nghttp2_hd.h +++ b/lib/nghttp2_hd.h @@ -139,6 +139,9 @@ typedef struct { /* Set to this nonzero to clear reference set on each deflation each time. */ uint8_t no_refset; + /* If nonzero, send header table size using encoding context update + in the next deflate process */ + uint8_t notify_table_size_change; } nghttp2_hd_deflater; struct nghttp2_hd_inflater { diff --git a/python/hpackmake.py b/python/hpackmake.py index 32de2f67..2ab8ea16 100755 --- a/python/hpackmake.py +++ b/python/hpackmake.py @@ -25,7 +25,10 @@ result in less bits on the wire.''' } cases = [] deflater = nghttp2.HDDeflater(deflate_table_size) - deflater.change_table_size(table_size) + + if table_size != 4096: + deflater.change_table_size(table_size) + for casenum, item in enumerate(testdata['cases']): outitem = { 'seqno': casenum, @@ -38,7 +41,7 @@ result in less bits on the wire.''' outitem['wire'] = b2a_hex(deflater.deflate(hdrs)).decode('utf-8') cases.append(outitem) - if cases: + if cases and table_size != 4096: cases[0]['header_table_size'] = table_size res['cases'] = cases diff --git a/tests/nghttp2_hd_test.c b/tests/nghttp2_hd_test.c index a63c481e..36ff165e 100644 --- a/tests/nghttp2_hd_test.c +++ b/tests/nghttp2_hd_test.c @@ -664,7 +664,7 @@ void test_nghttp2_hd_change_table_size(void) 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(4096 == deflater.ctx.hd_table_bufsize_max); CU_ASSERT(255 == inflater.ctx.hd_table.mask); CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max); @@ -702,7 +702,7 @@ void test_nghttp2_hd_change_table_size(void) blocklen = nghttp2_bufs_len(&bufs); CU_ASSERT(0 == rv); - CU_ASSERT(0 == blocklen); + CU_ASSERT(blocklen > 0); CU_ASSERT(2 == deflater.ctx.hd_table.len); CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max); @@ -784,7 +784,7 @@ void test_nghttp2_hd_change_table_size(void) 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(8192 == deflater.ctx.hd_table_bufsize_max); CU_ASSERT(511 == inflater.ctx.hd_table.mask); CU_ASSERT(16383 == inflater.ctx.hd_table_bufsize_max); @@ -824,7 +824,7 @@ void test_nghttp2_hd_change_table_size(void) nghttp2_hd_inflate_init(&inflater); CU_ASSERT(127 == deflater.ctx.hd_table.mask); - CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max); + CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max); /* This emits context update with buffer size 1024 */ rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);