diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 7483c9b3..938f27c9 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -1023,6 +1023,7 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, int rv; nghttp2_stream *stream; nghttp2_mem *mem; + int is_my_stream_id; mem = &session->mem; stream = nghttp2_session_get_stream(session, stream_id); @@ -1070,14 +1071,16 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id, } } + is_my_stream_id = nghttp2_session_is_my_stream_id(session, stream_id); + /* pushed streams which is not opened yet is not counted toward max concurrent limits */ if ((stream->flags & NGHTTP2_STREAM_FLAG_PUSH)) { - if (!nghttp2_session_is_my_stream_id(session, stream_id)) { + if (!is_my_stream_id) { --session->num_incoming_reserved_streams; } } else { - if (nghttp2_session_is_my_stream_id(session, stream_id)) { + if (is_my_stream_id) { --session->num_outgoing_streams; } else { --session->num_incoming_streams; @@ -1087,7 +1090,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 && nghttp2_stream_in_dep_tree(stream)) { + if (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 dependency tree work better. */ diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h index 34c06e53..dd69b5e3 100644 --- a/lib/nghttp2_session.h +++ b/lib/nghttp2_session.h @@ -190,11 +190,13 @@ struct nghttp2_session { updated when one frame was written. */ uint64_t last_cycle; void *user_data; - /* Points to the latest closed stream. NULL if there is no closed - stream. Only used when session is initialized as server. */ + /* Points to the latest incoming closed stream. NULL if there is no + closed stream. Only used when session is initialized as + server. */ nghttp2_stream *closed_stream_head; - /* Points to the oldest closed stream. NULL if there is no closed - stream. Only used when session is initialized as server. */ + /* Points to the oldest incoming closed stream. NULL if there is no + closed stream. Only used when session is initialized as + server. */ nghttp2_stream *closed_stream_tail; /* Points to the latest idle stream. NULL if there is no idle stream. Only used when session is initialized as server .*/ diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 36f36d05..1c896535 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -7378,7 +7378,8 @@ void test_nghttp2_session_stream_get_state(void) { stream = nghttp2_session_find_stream(session, 2); - CU_ASSERT(NGHTTP2_STREAM_STATE_CLOSED == nghttp2_stream_get_state(stream)); + /* At server, pushed stream object is not retained after closed */ + CU_ASSERT(NULL == stream); /* Push stream 4 associated to stream 5 */ rv = nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 5, reqnv, @@ -7599,6 +7600,22 @@ void test_nghttp2_session_keep_closed_stream(void) { CU_ASSERT(NULL == session->closed_stream_tail); CU_ASSERT(NULL == session->closed_stream_head); + nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR); + + CU_ASSERT(1 == session->num_closed_streams); + CU_ASSERT(3 == session->closed_stream_head->stream_id); + + /* server initiated stream is not counted to max concurrent limit */ + open_stream(session, 2); + + CU_ASSERT(1 == session->num_closed_streams); + CU_ASSERT(3 == session->closed_stream_head->stream_id); + + nghttp2_session_close_stream(session, 2, NGHTTP2_NO_ERROR); + + CU_ASSERT(1 == session->num_closed_streams); + CU_ASSERT(3 == session->closed_stream_head->stream_id); + nghttp2_session_del(session); }