From 392256e542ad4202360fb94c87c155309473aa6e Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 11 Sep 2016 22:13:59 +0900 Subject: [PATCH] Add nghttp2_option_set_max_deflate_dynamic_table_size() API function nghttp2_option_set_max_deflate_dynamic_table_size function sets the maximum dynamic table size for header block deflater. The default value is 4KiB. --- lib/includes/nghttp2/nghttp2.h | 13 +++++++++++ lib/nghttp2_option.c | 6 +++++ lib/nghttp2_option.h | 5 +++++ lib/nghttp2_session.c | 33 +++++++++++++++++----------- tests/nghttp2_session_test.c | 40 ++++++++++++++++++++++++++++++---- 5 files changed, 80 insertions(+), 17 deletions(-) diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index 59615fb4..d1ec9dea 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -2532,6 +2532,19 @@ NGHTTP2_EXTERN void nghttp2_option_set_max_send_header_block_length(nghttp2_option *option, size_t val); +/** + * @function + * + * This option sets the maximum dynamic table size for deflating + * header fields. The default value is 4KiB. In HTTP/2, receiver of + * deflated header block can specify maximum dynamic table size. The + * actual maximum size is the minimum of the size receiver specified + * and this option value. + */ +NGHTTP2_EXTERN void +nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option, + size_t val); + /** * @function * diff --git a/lib/nghttp2_option.c b/lib/nghttp2_option.c index 860c9f17..77e7db54 100644 --- a/lib/nghttp2_option.c +++ b/lib/nghttp2_option.c @@ -101,3 +101,9 @@ void nghttp2_option_set_max_send_header_block_length(nghttp2_option *option, option->opt_set_mask |= NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH; option->max_send_header_block_length = val; } + +void nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option, + size_t val) { + option->opt_set_mask |= NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE; + option->max_deflate_dynamic_table_size = val; +} diff --git a/lib/nghttp2_option.h b/lib/nghttp2_option.h index fb79b920..e750d1be 100644 --- a/lib/nghttp2_option.h +++ b/lib/nghttp2_option.h @@ -64,6 +64,7 @@ typedef enum { NGHTTP2_OPT_NO_AUTO_PING_ACK = 1 << 6, NGHTTP2_OPT_BUILTIN_RECV_EXT_TYPES = 1 << 7, NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH = 1 << 8, + NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE = 1 << 9, } nghttp2_option_flag; /** @@ -74,6 +75,10 @@ struct nghttp2_option { * NGHTTP2_OPT_MAX_SEND_HEADER_BLOCK_LENGTH */ size_t max_send_header_block_length; + /** + * NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE + */ + size_t max_deflate_dynamic_table_size; /** * Bitwise OR of nghttp2_option_flag to determine that which fields * are specified. diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index da5a6e55..a4123b48 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -390,6 +390,8 @@ static int session_new(nghttp2_session **session_ptr, const nghttp2_option *option, nghttp2_mem *mem) { int rv; size_t nbuffer; + size_t max_deflate_dynamic_table_size = + NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE; if (mem == NULL) { mem = nghttp2_mem_default(); @@ -407,19 +409,6 @@ static int session_new(nghttp2_session **session_ptr, /* next_stream_id is initialized in either nghttp2_session_client_new2 or nghttp2_session_server_new2 */ - rv = nghttp2_hd_deflate_init(&(*session_ptr)->hd_deflater, mem); - if (rv != 0) { - goto fail_hd_deflater; - } - rv = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater, mem); - if (rv != 0) { - goto fail_hd_inflater; - } - rv = nghttp2_map_init(&(*session_ptr)->streams, mem); - if (rv != 0) { - goto fail_map; - } - nghttp2_stream_init(&(*session_ptr)->root, 0, NGHTTP2_STREAM_FLAG_NONE, NGHTTP2_STREAM_IDLE, NGHTTP2_DEFAULT_WEIGHT, 0, 0, NULL, mem); @@ -502,6 +491,24 @@ static int session_new(nghttp2_session **session_ptr, (*session_ptr)->max_send_header_block_length = option->max_send_header_block_length; } + + if (option->opt_set_mask & NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE) { + max_deflate_dynamic_table_size = option->max_deflate_dynamic_table_size; + } + } + + rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater, + max_deflate_dynamic_table_size, mem); + if (rv != 0) { + goto fail_hd_deflater; + } + rv = nghttp2_hd_inflate_init(&(*session_ptr)->hd_inflater, mem); + if (rv != 0) { + goto fail_hd_inflater; + } + rv = nghttp2_map_init(&(*session_ptr)->streams, mem); + if (rv != 0) { + goto fail_map; } nbuffer = ((*session_ptr)->max_send_header_block_length + diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index de6c557a..5187b9af 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -6666,33 +6666,45 @@ void test_nghttp2_session_set_option(void) { nghttp2_session *session; nghttp2_session_callbacks callbacks; nghttp2_option *option; - - nghttp2_option_new(&option); - - nghttp2_option_set_no_auto_window_update(option, 1); + nghttp2_hd_deflater *deflater; + int rv; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); + callbacks.send_callback = null_send_callback; + + /* Test for nghttp2_option_set_no_auto_window_update */ + nghttp2_option_new(&option); + nghttp2_option_set_no_auto_window_update(option, 1); + nghttp2_session_client_new2(&session, &callbacks, NULL, option); CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE); nghttp2_session_del(session); + nghttp2_option_del(option); + /* Test for nghttp2_option_set_peer_max_concurrent_streams */ + nghttp2_option_new(&option); nghttp2_option_set_peer_max_concurrent_streams(option, 100); nghttp2_session_client_new2(&session, &callbacks, NULL, option); CU_ASSERT(100 == session->remote_settings.max_concurrent_streams); nghttp2_session_del(session); + nghttp2_option_del(option); + /* Test for nghttp2_option_set_max_reserved_remote_streams */ + nghttp2_option_new(&option); nghttp2_option_set_max_reserved_remote_streams(option, 99); nghttp2_session_client_new2(&session, &callbacks, NULL, option); CU_ASSERT(99 == session->max_incoming_reserved_streams); nghttp2_session_del(session); + nghttp2_option_del(option); /* Test for nghttp2_option_set_no_auto_ping_ack */ + nghttp2_option_new(&option); nghttp2_option_set_no_auto_ping_ack(option, 1); nghttp2_session_client_new2(&session, &callbacks, NULL, option); @@ -6700,7 +6712,27 @@ void test_nghttp2_session_set_option(void) { CU_ASSERT(session->opt_flags & NGHTTP2_OPTMASK_NO_AUTO_PING_ACK); nghttp2_session_del(session); + nghttp2_option_del(option); + /* Test for nghttp2_option_set_max_deflate_dynamic_table_size */ + nghttp2_option_new(&option); + nghttp2_option_set_max_deflate_dynamic_table_size(option, 0); + + nghttp2_session_client_new2(&session, &callbacks, NULL, option); + + deflater = &session->hd_deflater; + + rv = nghttp2_submit_request(session, NULL, reqnv, ARRLEN(reqnv), NULL, NULL); + + CU_ASSERT(1 == rv); + + rv = nghttp2_session_send(session); + + CU_ASSERT(0 == rv); + CU_ASSERT(0 == deflater->deflate_hd_table_bufsize_max); + CU_ASSERT(0 == deflater->ctx.hd_table_bufsize); + + nghttp2_session_del(session); nghttp2_option_del(option); }