Keep idle streams in separate list

Previously we handle idle streams as closed streams.  We only keeps
sum of closed streams and active streams under max concurrent streams
limit, idle streams gets deleted earlier than client expects.

In this change, idle streams are kept in separate list and not handled
as closed streams.  To mitigate possible attack vector to make
unlimited idle streams, we cap the number of idle streams in a half of
max concurrent streams.  This is arbitrary choice.  It may be adjusted
in the future when we have interop experience.
This commit is contained in:
Tatsuhiro Tsujikawa 2014-12-13 00:03:19 +09:00
parent e4c59dd164
commit 280c9dfcf3
5 changed files with 210 additions and 145 deletions

View File

@ -588,21 +588,15 @@ nghttp2_session_reprioritize_stream(nghttp2_session *session,
if (session->server && !dep_stream &&
session_detect_idle_stream(session, pri_spec->stream_id)) {
nghttp2_session_adjust_closed_stream(session, 1);
nghttp2_priority_spec_default_init(&pri_spec_default);
if (nghttp2_session_can_add_closed_stream(session, 1)) {
dep_stream = nghttp2_session_open_stream(
session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default,
NGHTTP2_STREAM_IDLE, NULL);
dep_stream = nghttp2_session_open_stream(
session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default,
NGHTTP2_STREAM_IDLE, NULL);
if (dep_stream == NULL) {
return NGHTTP2_ERR_NOMEM;
}
} else {
pri_spec = &pri_spec_default;
if (dep_stream == NULL) {
return NGHTTP2_ERR_NOMEM;
}
} else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
nghttp2_priority_spec_default_init(&pri_spec_default);
@ -831,7 +825,6 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
int stream_alloc = 0;
nghttp2_priority_spec pri_spec_default;
nghttp2_priority_spec *pri_spec = pri_spec_in;
ssize_t num_adjust_closed = 0;
nghttp2_mem *mem;
mem = &session->mem;
@ -840,13 +833,12 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
if (stream) {
assert(stream->state == NGHTTP2_STREAM_IDLE);
assert(nghttp2_stream_in_dep_tree(stream));
nghttp2_session_detach_closed_stream(session, stream);
nghttp2_session_detach_idle_stream(session, stream);
nghttp2_stream_dep_remove(stream);
} else {
if (session->server &&
(!nghttp2_session_is_my_stream_id(session, stream_id) ||
initial_state == NGHTTP2_STREAM_IDLE)) {
num_adjust_closed = 1;
if (session->server && initial_state != NGHTTP2_STREAM_IDLE &&
!nghttp2_session_is_my_stream_id(session, stream_id)) {
nghttp2_session_adjust_closed_stream(session, 1);
}
@ -863,26 +855,20 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
if (session->server && !dep_stream &&
session_detect_idle_stream(session, pri_spec->stream_id)) {
++num_adjust_closed;
nghttp2_session_adjust_closed_stream(session, num_adjust_closed);
/* Depends on idle stream, which does not exist in memory.
Assign default priority for it. */
nghttp2_priority_spec_default_init(&pri_spec_default);
if (nghttp2_session_can_add_closed_stream(session, num_adjust_closed)) {
dep_stream = nghttp2_session_open_stream(
session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default,
NGHTTP2_STREAM_IDLE, NULL);
dep_stream = nghttp2_session_open_stream(
session, pri_spec->stream_id, NGHTTP2_FLAG_NONE, &pri_spec_default,
NGHTTP2_STREAM_IDLE, NULL);
if (dep_stream == NULL) {
if (stream_alloc) {
nghttp2_mem_free(mem, stream);
}
return NULL;
if (dep_stream == NULL) {
if (stream_alloc) {
nghttp2_mem_free(mem, stream);
}
} else {
pri_spec = &pri_spec_default;
return NULL;
}
} else if (!dep_stream || !nghttp2_stream_in_dep_tree(dep_stream)) {
/* If dep_stream is not part of dependency tree, stream will get
@ -921,7 +907,7 @@ nghttp2_stream *nghttp2_session_open_stream(nghttp2_session *session,
/* Idle stream does not count toward the concurrent streams limit.
This is used as anchor node in dependency tree. */
assert(session->server);
nghttp2_session_keep_closed_stream(session, stream);
nghttp2_session_keep_idle_stream(session, stream);
break;
default:
if (nghttp2_session_is_my_stream_id(session, stream_id)) {
@ -1021,8 +1007,7 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
hang the stream in a local endpoint.
*/
if (stream->state != NGHTTP2_STREAM_IDLE &&
session->callbacks.on_stream_close_callback) {
if (session->callbacks.on_stream_close_callback) {
if (session->callbacks.on_stream_close_callback(
session, stream_id, error_code, session->user_data) != 0) {
@ -1032,7 +1017,6 @@ int nghttp2_session_close_stream(nghttp2_session *session, int32_t stream_id,
switch (stream->state) {
case NGHTTP2_STREAM_RESERVED:
case NGHTTP2_STREAM_IDLE:
break;
default:
if (nghttp2_session_is_my_stream_id(session, stream_id)) {
@ -1091,11 +1075,29 @@ void nghttp2_session_keep_closed_stream(nghttp2_session *session,
nghttp2_session_adjust_closed_stream(session, 0);
}
void nghttp2_session_detach_closed_stream(nghttp2_session *session,
nghttp2_stream *stream) {
void nghttp2_session_keep_idle_stream(nghttp2_session *session,
nghttp2_stream *stream) {
DEBUGF(fprintf(stderr, "stream: keep idle stream(%p)=%d, state=%d\n", stream,
stream->stream_id, stream->state));
if (session->idle_stream_tail) {
session->idle_stream_tail->closed_next = stream;
stream->closed_prev = session->idle_stream_tail;
} else {
session->idle_stream_head = stream;
}
session->idle_stream_tail = stream;
++session->num_idle_streams;
nghttp2_session_adjust_idle_stream(session);
}
void nghttp2_session_detach_idle_stream(nghttp2_session *session,
nghttp2_stream *stream) {
nghttp2_stream *prev_stream, *next_stream;
DEBUGF(fprintf(stderr, "stream: detach closed stream(%p)=%d, state=%d\n",
DEBUGF(fprintf(stderr, "stream: detach idle stream(%p)=%d, state=%d\n",
stream, stream->stream_id, stream->state));
prev_stream = stream->closed_prev;
@ -1104,29 +1106,19 @@ void nghttp2_session_detach_closed_stream(nghttp2_session *session,
if (prev_stream) {
prev_stream->closed_next = next_stream;
} else {
session->closed_stream_head = next_stream;
session->idle_stream_head = next_stream;
}
if (next_stream) {
next_stream->closed_prev = prev_stream;
} else {
session->closed_stream_tail = prev_stream;
session->idle_stream_tail = prev_stream;
}
stream->closed_prev = NULL;
stream->closed_next = NULL;
--session->num_closed_streams;
}
int nghttp2_session_can_add_closed_stream(nghttp2_session *session,
ssize_t offset) {
size_t num_stream_max;
num_stream_max = nghttp2_min(session->local_settings.max_concurrent_streams,
session->pending_local_max_concurrent_stream);
return offset + session->num_incoming_streams <= num_stream_max;
--session->num_idle_streams;
}
void nghttp2_session_adjust_closed_stream(nghttp2_session *session,
@ -1165,6 +1157,41 @@ void nghttp2_session_adjust_closed_stream(nghttp2_session *session,
}
}
void nghttp2_session_adjust_idle_stream(nghttp2_session *session) {
size_t max;
/* Make minimum number of idle streams 2 so that allocating 2
streams at once is easy. This happens when PRIORITY frame to
idle stream, which depends on idle stream which does not
exist. */
max =
nghttp2_max(2, nghttp2_min(session->local_settings.max_concurrent_streams,
session->pending_local_max_concurrent_stream));
DEBUGF(fprintf(stderr, "stream: adjusting kept idle streams "
"num_idle_streams=%zu, max=%zu\n",
session->num_idle_streams, max));
while (session->num_idle_streams > max) {
nghttp2_stream *head;
head = session->idle_stream_head;
assert(head);
session->idle_stream_head = head->closed_next;
if (session->idle_stream_head) {
session->idle_stream_head->closed_prev = NULL;
} else {
session->idle_stream_tail = NULL;
}
nghttp2_session_destroy_stream(session, head);
/* head is now destroyed */
--session->num_idle_streams;
}
}
/*
* Closes stream with stream ID |stream_id| if both transmission and
* reception of the stream were disallowed. The |error_code| indicates
@ -3325,8 +3352,7 @@ int nghttp2_session_on_priority_received(nghttp2_session *session,
if (!stream) {
/* PRIORITY against idle stream can create anchor node in
dependency tree. */
if (!session_detect_idle_stream(session, frame->hd.stream_id) ||
!nghttp2_session_can_add_closed_stream(session, 1)) {
if (!session_detect_idle_stream(session, frame->hd.stream_id)) {
return 0;
}

View File

@ -173,6 +173,12 @@ struct nghttp2_session {
/* Points to the oldest 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 .*/
nghttp2_stream *idle_stream_head;
/* Points to the oldest idle stream. NULL if there is no idle
stream. Only used when session is initialized as erver. */
nghttp2_stream *idle_stream_tail;
/* In-flight SETTINGS values. NULL does not necessarily mean there
is no in-flight SETTINGS. */
nghttp2_settings_entry *inflight_iv;
@ -190,6 +196,11 @@ struct nghttp2_session {
|closed_stream_head|. The current implementation only keeps
incoming streams and session is initialized as server. */
size_t num_closed_streams;
/* The number of idle streams kept in |streams| hash. The idle
streams can be accessed through doubly linked list
|idle_stream_head|. The current implementation only keeps idle
streams if session is initialized as server. */
size_t num_idle_streams;
/* The number of bytes allocated for nvbuf */
size_t nvbuflen;
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
@ -433,17 +444,18 @@ void nghttp2_session_keep_closed_stream(nghttp2_session *session,
nghttp2_stream *stream);
/*
* Detaches |stream| from closed streams linked list.
* Appends |stream| to linked list |session->idle_stream_head|. We
* apply fixed limit for list size. To fit into that limit, one or
* more oldest streams are removed from list as necessary.
*/
void nghttp2_session_detach_closed_stream(nghttp2_session *session,
nghttp2_stream *stream);
void nghttp2_session_keep_idle_stream(nghttp2_session *session,
nghttp2_stream *stream);
/*
* Returns nonzero if |offset| closed stream(s) can be added to closed
* linked list now.
* Detaches |stream| from idle streams linked list.
*/
int nghttp2_session_can_add_closed_stream(nghttp2_session *session,
ssize_t offset);
void nghttp2_session_detach_idle_stream(nghttp2_session *session,
nghttp2_stream *stream);
/*
* Deletes closed stream to ensure that number of incoming streams
@ -455,6 +467,12 @@ int nghttp2_session_can_add_closed_stream(nghttp2_session *session,
void nghttp2_session_adjust_closed_stream(nghttp2_session *session,
ssize_t offset);
/*
* Deletes idle stream to ensure that number of idle streams is in
* certain limit.
*/
void nghttp2_session_adjust_idle_stream(nghttp2_session *session);
/*
* If further receptions and transmissions over the stream |stream_id|
* are disallowed, close the stream with error code NGHTTP2_NO_ERROR.

View File

@ -139,8 +139,8 @@ int main(int argc _U_, char *argv[] _U_) {
!CU_add_test(pSuite, "session_reprioritize_stream",
test_nghttp2_session_reprioritize_stream) ||
!CU_add_test(
pSuite, "session_reprioritize_stream_with_closed_stream_limit",
test_nghttp2_session_reprioritize_stream_with_closed_stream_limit) ||
pSuite, "session_reprioritize_stream_with_idle_stream_dep",
test_nghttp2_session_reprioritize_stream_with_idle_stream_dep) ||
!CU_add_test(pSuite, "submit_data", test_nghttp2_submit_data) ||
!CU_add_test(pSuite, "submit_data_read_length_too_large",
test_nghttp2_submit_data_read_length_too_large) ||
@ -178,8 +178,8 @@ int main(int argc _U_, char *argv[] _U_) {
test_nghttp2_submit_invalid_nv) ||
!CU_add_test(pSuite, "session_open_stream",
test_nghttp2_session_open_stream) ||
!CU_add_test(pSuite, "session_open_stream_with_closed_stream_limit",
test_nghttp2_session_open_stream_with_closed_stream_limit) ||
!CU_add_test(pSuite, "session_open_stream_with_idle_stream_dep",
test_nghttp2_session_open_stream_with_idle_stream_dep) ||
!CU_add_test(pSuite, "session_get_next_ob_item",
test_nghttp2_session_get_next_ob_item) ||
!CU_add_test(pSuite, "session_pop_next_ob_item",
@ -237,8 +237,10 @@ int main(int argc _U_, char *argv[] _U_) {
test_nghttp2_session_stream_attach_data_subtree) ||
!CU_add_test(pSuite, "session_stream_keep_closed_stream",
test_nghttp2_session_keep_closed_stream) ||
!CU_add_test(pSuite, "session_detach_closed_stream",
test_nghttp2_session_detach_closed_stream) ||
!CU_add_test(pSuite, "session_stream_keep_idle_stream",
test_nghttp2_session_keep_idle_stream) ||
!CU_add_test(pSuite, "session_detach_idle_stream",
test_nghttp2_session_detach_idle_stream) ||
!CU_add_test(pSuite, "session_large_dep_tree",
test_nghttp2_session_large_dep_tree) ||
!CU_add_test(pSuite, "session_graceful_shutdown",

View File

@ -3033,7 +3033,7 @@ void test_nghttp2_session_reprioritize_stream(void) {
nghttp2_session_del(session);
}
void test_nghttp2_session_reprioritize_stream_with_closed_stream_limit(void) {
void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_stream *stream;
@ -3054,16 +3054,7 @@ void test_nghttp2_session_reprioritize_stream_with_closed_stream_limit(void) {
nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
/* No room to create idle stream, so default priority was applied. */
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
CU_ASSERT(NULL == stream->dep_prev);
session->pending_local_max_concurrent_stream = 2;
/* Now idle stream can be created */
nghttp2_session_reprioritize_stream(session, stream, &pri_spec);
/* idle stream is not counteed to max concurrent streams */
CU_ASSERT(10 == stream->weight);
CU_ASSERT(101 == stream->dep_prev->stream_id);
@ -4124,7 +4115,7 @@ void test_nghttp2_session_open_stream(void) {
nghttp2_session_del(session);
}
void test_nghttp2_session_open_stream_with_closed_stream_limit(void) {
void test_nghttp2_session_open_stream_with_idle_stream_dep(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_stream *stream;
@ -4133,22 +4124,12 @@ void test_nghttp2_session_open_stream_with_closed_stream_limit(void) {
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
nghttp2_session_server_new(&session, &callbacks, NULL);
session->pending_local_max_concurrent_stream = 1;
/* Dependency to idle stream */
nghttp2_priority_spec_init(&pri_spec, 101, 245, 0);
stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec, NGHTTP2_STREAM_OPENED, NULL);
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
session->pending_local_max_concurrent_stream = 3;
/* Now another 2 streams can be added */
stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec, NGHTTP2_STREAM_OPENED, NULL);
CU_ASSERT(245 == stream->weight);
CU_ASSERT(101 == stream->dep_prev->stream_id);
@ -4157,14 +4138,9 @@ void test_nghttp2_session_open_stream_with_closed_stream_limit(void) {
CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight);
session->pending_local_max_concurrent_stream = 4;
/* Now another 1 stream can be added */
nghttp2_priority_spec_init(&pri_spec, 211, 1, 0);
/* stream 101 was already created and does not consume another
limit. */
/* stream 101 was already created as idle. */
stream = nghttp2_session_open_stream(session, 101, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec, NGHTTP2_STREAM_OPENED, NULL);
@ -6218,7 +6194,45 @@ void test_nghttp2_session_keep_closed_stream(void) {
nghttp2_session_del(session);
}
void test_nghttp2_session_detach_closed_stream(void) {
void test_nghttp2_session_keep_idle_stream(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
const size_t max_concurrent_streams = 1;
nghttp2_settings_entry iv = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS,
max_concurrent_streams};
int i;
memset(&callbacks, 0, sizeof(callbacks));
callbacks.send_callback = null_send_callback;
nghttp2_session_server_new(&session, &callbacks, NULL);
nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1);
/* We at least allow 2 idle streams even if max concurrent streams
is very low. */
for (i = 0; i < 2; ++i) {
nghttp2_session_open_stream(session, i * 2 + 1, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
}
CU_ASSERT(2 == session->num_idle_streams);
CU_ASSERT(1 == session->idle_stream_head->stream_id);
CU_ASSERT(3 == session->idle_stream_tail->stream_id);
nghttp2_session_open_stream(session, 5, NGHTTP2_FLAG_NONE, &pri_spec_default,
NGHTTP2_STREAM_IDLE, NULL);
CU_ASSERT(2 == session->num_idle_streams);
CU_ASSERT(3 == session->idle_stream_head->stream_id);
CU_ASSERT(5 == session->idle_stream_tail->stream_id);
nghttp2_session_del(session);
}
void test_nghttp2_session_detach_idle_stream(void) {
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
int i;
@ -6229,72 +6243,76 @@ void test_nghttp2_session_detach_closed_stream(void) {
nghttp2_session_server_new(&session, &callbacks, NULL);
for (i = 0; i < 3; ++i) {
open_stream(session, i);
nghttp2_session_close_stream(session, i, NGHTTP2_NO_ERROR);
for (i = 1; i <= 3; ++i) {
nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
}
CU_ASSERT(3 == session->num_closed_streams);
CU_ASSERT(3 == session->num_idle_streams);
stream = nghttp2_session_get_stream_raw(session, 1);
/* Detach middle stream */
stream = nghttp2_session_get_stream_raw(session, 2);
CU_ASSERT(session->closed_stream_head == stream->closed_prev);
CU_ASSERT(session->closed_stream_tail == stream->closed_next);
CU_ASSERT(stream == session->closed_stream_head->closed_next);
CU_ASSERT(stream == session->closed_stream_tail->closed_prev);
CU_ASSERT(session->idle_stream_head == stream->closed_prev);
CU_ASSERT(session->idle_stream_tail == stream->closed_next);
CU_ASSERT(stream == session->idle_stream_head->closed_next);
CU_ASSERT(stream == session->idle_stream_tail->closed_prev);
nghttp2_session_detach_closed_stream(session, stream);
nghttp2_session_detach_idle_stream(session, stream);
CU_ASSERT(2 == session->num_closed_streams);
CU_ASSERT(2 == session->num_idle_streams);
CU_ASSERT(NULL == stream->closed_prev);
CU_ASSERT(NULL == stream->closed_next);
CU_ASSERT(session->closed_stream_head ==
session->closed_stream_tail->closed_prev);
CU_ASSERT(session->closed_stream_tail ==
session->closed_stream_head->closed_next);
CU_ASSERT(session->idle_stream_head ==
session->idle_stream_tail->closed_prev);
CU_ASSERT(session->idle_stream_tail ==
session->idle_stream_head->closed_next);
/* Close head stream */
stream = session->closed_stream_head;
/* Detach head stream */
stream = session->idle_stream_head;
nghttp2_session_detach_closed_stream(session, stream);
nghttp2_session_detach_idle_stream(session, stream);
CU_ASSERT(1 == session->num_closed_streams);
CU_ASSERT(1 == session->num_idle_streams);
CU_ASSERT(session->closed_stream_head == session->closed_stream_tail);
CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
CU_ASSERT(NULL == session->closed_stream_head->closed_next);
CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
fprintf(stderr, "head=%p, tail=%p\n", session->idle_stream_head,
session->idle_stream_tail);
/* Close last stream */
CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
CU_ASSERT(NULL == session->idle_stream_head->closed_next);
stream = session->closed_stream_head;
/* Detach last stream */
nghttp2_session_detach_closed_stream(session, stream);
stream = session->idle_stream_head;
CU_ASSERT(0 == session->num_closed_streams);
nghttp2_session_detach_idle_stream(session, stream);
CU_ASSERT(NULL == session->closed_stream_head);
CU_ASSERT(NULL == session->closed_stream_tail);
CU_ASSERT(0 == session->num_idle_streams);
for (i = 3; i < 5; ++i) {
open_stream(session, i);
nghttp2_session_close_stream(session, i, NGHTTP2_NO_ERROR);
CU_ASSERT(NULL == session->idle_stream_head);
CU_ASSERT(NULL == session->idle_stream_tail);
for (i = 4; i <= 5; ++i) {
nghttp2_session_open_stream(session, i, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default, NGHTTP2_STREAM_IDLE, NULL);
}
CU_ASSERT(2 == session->num_closed_streams);
CU_ASSERT(2 == session->num_idle_streams);
/* Close tail stream */
/* Detach tail stream */
stream = session->closed_stream_tail;
stream = session->idle_stream_tail;
nghttp2_session_detach_closed_stream(session, stream);
nghttp2_session_detach_idle_stream(session, stream);
CU_ASSERT(1 == session->num_closed_streams);
CU_ASSERT(1 == session->num_idle_streams);
CU_ASSERT(session->closed_stream_head == session->closed_stream_tail);
CU_ASSERT(NULL == session->closed_stream_head->closed_prev);
CU_ASSERT(NULL == session->closed_stream_head->closed_next);
CU_ASSERT(session->idle_stream_head == session->idle_stream_tail);
CU_ASSERT(NULL == session->idle_stream_head->closed_prev);
CU_ASSERT(NULL == session->idle_stream_head->closed_next);
nghttp2_session_del(session);
}
@ -6556,9 +6574,9 @@ void test_nghttp2_session_open_idle_stream(void) {
CU_ASSERT(NGHTTP2_STREAM_IDLE == stream->state);
CU_ASSERT(NULL == stream->closed_prev);
CU_ASSERT(NULL == stream->closed_next);
CU_ASSERT(1 == session->num_closed_streams);
CU_ASSERT(session->closed_stream_head == stream);
CU_ASSERT(session->closed_stream_tail == stream);
CU_ASSERT(1 == session->num_idle_streams);
CU_ASSERT(session->idle_stream_head == stream);
CU_ASSERT(session->idle_stream_tail == stream);
opened_stream = nghttp2_session_open_stream(
session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default,
@ -6566,9 +6584,9 @@ void test_nghttp2_session_open_idle_stream(void) {
CU_ASSERT(stream == opened_stream);
CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
CU_ASSERT(0 == session->num_closed_streams);
CU_ASSERT(NULL == session->closed_stream_head);
CU_ASSERT(NULL == session->closed_stream_tail);
CU_ASSERT(0 == session->num_idle_streams);
CU_ASSERT(NULL == session->idle_stream_head);
CU_ASSERT(NULL == session->idle_stream_tail);
nghttp2_frame_priority_free(&frame.priority);

View File

@ -60,7 +60,7 @@ void test_nghttp2_session_send_push_promise(void);
void test_nghttp2_session_is_my_stream_id(void);
void test_nghttp2_session_upgrade(void);
void test_nghttp2_session_reprioritize_stream(void);
void test_nghttp2_session_reprioritize_stream_with_closed_stream_limit(void);
void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void);
void test_nghttp2_submit_data(void);
void test_nghttp2_submit_data_read_length_too_large(void);
void test_nghttp2_submit_data_read_length_smallest(void);
@ -82,7 +82,7 @@ void test_nghttp2_submit_window_update(void);
void test_nghttp2_submit_window_update_local_window_size(void);
void test_nghttp2_submit_invalid_nv(void);
void test_nghttp2_session_open_stream(void);
void test_nghttp2_session_open_stream_with_closed_stream_limit(void);
void test_nghttp2_session_open_stream_with_idle_stream_dep(void);
void test_nghttp2_session_get_next_ob_item(void);
void test_nghttp2_session_pop_next_ob_item(void);
void test_nghttp2_session_reply_fail(void);
@ -111,7 +111,8 @@ void test_nghttp2_session_stream_dep_all_your_stream_are_belong_to_us(void);
void test_nghttp2_session_stream_attach_data(void);
void test_nghttp2_session_stream_attach_data_subtree(void);
void test_nghttp2_session_keep_closed_stream(void);
void test_nghttp2_session_detach_closed_stream(void);
void test_nghttp2_session_keep_idle_stream(void);
void test_nghttp2_session_detach_idle_stream(void);
void test_nghttp2_session_large_dep_tree(void);
void test_nghttp2_session_graceful_shutdown(void);
void test_nghttp2_session_on_header_temporal_failure(void);