Add nghttp2_option_no_closed_streams

nghttp2_option_no_closed_streams controls whether closed streams are
retained or not.  If nonzero is passed to that function's parameter
val, a session does not retain closed streams.  It may hurt the shape
of priority tree, but can save memory.
This commit is contained in:
Tatsuhiro Tsujikawa 2017-02-13 22:15:42 +09:00
parent 001d45efad
commit f3a5a0a0ec
9 changed files with 55 additions and 2 deletions

View File

@ -62,6 +62,7 @@ APIDOCS= \
nghttp2_option_set_max_send_header_block_length.rst \
nghttp2_option_set_no_auto_ping_ack.rst \
nghttp2_option_set_no_auto_window_update.rst \
nghttp2_option_set_no_closed_streams.rst \
nghttp2_option_set_no_http_messaging.rst \
nghttp2_option_set_no_recv_client_magic.rst \
nghttp2_option_set_peer_max_concurrent_streams.rst \

View File

@ -2551,6 +2551,16 @@ NGHTTP2_EXTERN void
nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
size_t val);
/**
* @function
*
* This option prevents the library from retaining closed streams to
* maintain the priority tree. If this option is set to nonzero,
* applications can discard closed stream completely to save memory.
*/
NGHTTP2_EXTERN void nghttp2_option_set_no_closed_streams(nghttp2_option *option,
int val);
/**
* @function
*

View File

@ -107,3 +107,8 @@ void nghttp2_option_set_max_deflate_dynamic_table_size(nghttp2_option *option,
option->opt_set_mask |= NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE;
option->max_deflate_dynamic_table_size = val;
}
void nghttp2_option_set_no_closed_streams(nghttp2_option *option, int val) {
option->opt_set_mask |= NGHTTP2_OPT_NO_CLOSED_STREAMS;
option->no_closed_streams = val;
}

View File

@ -65,6 +65,7 @@ typedef enum {
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_OPT_NO_CLOSED_STREAMS = 1 << 10,
} nghttp2_option_flag;
/**
@ -112,6 +113,10 @@ struct nghttp2_option {
* NGHTTP2_OPT_NO_AUTO_PING_ACK
*/
int no_auto_ping_ack;
/**
* NGHTTP2_OPT_NO_CLOSED_STREAMS
*/
int no_closed_streams;
/**
* NGHTTP2_OPT_USER_RECV_EXT_TYPES
*/

View File

@ -494,6 +494,11 @@ static int session_new(nghttp2_session **session_ptr,
if (option->opt_set_mask & NGHTTP2_OPT_MAX_DEFLATE_DYNAMIC_TABLE_SIZE) {
max_deflate_dynamic_table_size = option->max_deflate_dynamic_table_size;
}
if ((option->opt_set_mask & NGHTTP2_OPT_NO_CLOSED_STREAMS) &&
option->no_closed_streams) {
(*session_ptr)->opt_flags |= NGHTTP2_OPTMASK_NO_CLOSED_STREAMS;
}
}
rv = nghttp2_hd_deflate_init2(&(*session_ptr)->hd_deflater,
@ -1186,7 +1191,8 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
/* Closes both directions just in case they are not closed yet */
stream->flags |= NGHTTP2_STREAM_FLAG_CLOSED;
if (session->server && !is_my_stream_id &&
if ((session->opt_flags & NGHTTP2_OPTMASK_NO_CLOSED_STREAMS) == 0 &&
session->server && !is_my_stream_id &&
nghttp2_stream_in_dep_tree(stream)) {
/* On server side, retain stream at most MAX_CONCURRENT_STREAMS
combined with the current active incoming streams to make

View File

@ -51,7 +51,8 @@ typedef enum {
NGHTTP2_OPTMASK_NO_AUTO_WINDOW_UPDATE = 1 << 0,
NGHTTP2_OPTMASK_NO_RECV_CLIENT_MAGIC = 1 << 1,
NGHTTP2_OPTMASK_NO_HTTP_MESSAGING = 1 << 2,
NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3
NGHTTP2_OPTMASK_NO_AUTO_PING_ACK = 1 << 3,
NGHTTP2_OPTMASK_NO_CLOSED_STREAMS = 1 << 4
} nghttp2_optmask;
/*

View File

@ -312,6 +312,8 @@ int main(int argc _U_, char *argv[] _U_) {
test_nghttp2_session_removed_closed_stream) ||
!CU_add_test(pSuite, "session_pause_data",
test_nghttp2_session_pause_data) ||
!CU_add_test(pSuite, "session_no_closed_streams",
test_nghttp2_session_no_closed_streams) ||
!CU_add_test(pSuite, "http_mandatory_headers",
test_nghttp2_http_mandatory_headers) ||
!CU_add_test(pSuite, "http_content_length",

View File

@ -10098,6 +10098,28 @@ void test_nghttp2_session_pause_data(void) {
nghttp2_session_del(session);
}
void test_nghttp2_session_no_closed_streams(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_option *option;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
nghttp2_option_new(&option);
nghttp2_option_set_no_closed_streams(option, 1);
nghttp2_session_server_new2(&session, &callbacks, NULL, option);
open_recv_stream(session, 1);
nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR);
CU_ASSERT(0 == session->num_closed_streams);
nghttp2_session_del(session);
nghttp2_option_del(option);
}
static void check_nghttp2_http_recv_headers_fail(
nghttp2_session *session, nghttp2_hd_deflater *deflater, int32_t stream_id,
int stream_state, const nghttp2_nv *nva, size_t nvlen) {

View File

@ -154,6 +154,7 @@ void test_nghttp2_session_set_local_window_size(void);
void test_nghttp2_session_cancel_from_before_frame_send(void);
void test_nghttp2_session_removed_closed_stream(void);
void test_nghttp2_session_pause_data(void);
void test_nghttp2_session_no_closed_streams(void);
void test_nghttp2_http_mandatory_headers(void);
void test_nghttp2_http_content_length(void);
void test_nghttp2_http_content_length_mismatch(void);