From 9cea986819cfce0583309a7546a0d679066136ce Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 11 Jan 2016 00:31:52 +0900 Subject: [PATCH 1/4] Strict outgoing idle stream detection Previously, we use session->next_stream_id to detect that given stream ID was idle or not. But this was suboptimal, since it was updated when stream ID was assigned, and it did not necessarily mean that it actually has been sent to the peer. Now we introduced session->sent_stream_id, which only updated when HEADERS/PUSH_PROMISE has sent. Using sent_stream_id instead of next_stream_id tightens idle stream detection, and misbehaved peer which sends frame with stream ID that has not been generated. This commit also overhauls test code which involves opening streams. Now we have some wrapper functions for nghttp2_session_open_stream() which also take care of updating next_stream_id and last_recv_stream_id. They are crucial for some tests. --- lib/nghttp2_session.c | 76 +++--- lib/nghttp2_session.h | 4 + tests/nghttp2_session_test.c | 440 ++++++++++++++--------------------- tests/nghttp2_test_helper.c | 116 +++++++++ tests/nghttp2_test_helper.h | 45 ++++ 5 files changed, 384 insertions(+), 297 deletions(-) diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 6fda5442..74c2aefb 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -130,7 +130,7 @@ static int session_detect_idle_stream(nghttp2_session *session, int32_t stream_id) { /* Assume that stream object with stream_id does not exist */ if (nghttp2_session_is_my_stream_id(session, stream_id)) { - if (session->next_stream_id <= (uint32_t)stream_id) { + if (session->sent_stream_id < stream_id) { return 1; } return 0; @@ -1374,7 +1374,9 @@ static int session_predicate_request_headers_send(nghttp2_session *session, * NGHTTP2_ERR_INVALID_STREAM_STATE * The state of the stream is not valid. * NGHTTP2_ERR_SESSION_CLOSING - * This session is closing. + * This session is closing. + * NGHTTP2_ERR_PROTO + * Client side attempted to send response. */ static int session_predicate_response_headers_send(nghttp2_session *session, nghttp2_stream *stream) { @@ -1384,6 +1386,9 @@ static int session_predicate_response_headers_send(nghttp2_session *session, return rv; } assert(stream); + if (!session->server) { + return NGHTTP2_ERR_PROTO; + } if (nghttp2_session_is_my_stream_id(session, stream->stream_id)) { return NGHTTP2_ERR_INVALID_STREAM_ID; } @@ -1417,6 +1422,8 @@ static int session_predicate_response_headers_send(nghttp2_session *session, * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED * New stream cannot be created because GOAWAY is already sent or * received. + * NGHTTP2_ERR_PROTO + * Client side attempted to send push response. */ static int session_predicate_push_response_headers_send(nghttp2_session *session, @@ -1428,6 +1435,9 @@ session_predicate_push_response_headers_send(nghttp2_session *session, return rv; } assert(stream); + if (!session->server) { + return NGHTTP2_ERR_PROTO; + } if (stream->state != NGHTTP2_STREAM_RESERVED) { return NGHTTP2_ERR_PROTO; } @@ -1861,6 +1871,11 @@ static int session_prep_frame(nghttp2_session *session, DEBUGF(fprintf(stderr, "send: HEADERS finally serialized in %zd bytes\n", nghttp2_bufs_len(&session->aob.framebufs))); + if (frame->headers.cat == NGHTTP2_HCAT_REQUEST) { + assert(session->sent_stream_id < frame->hd.stream_id); + session->sent_stream_id = frame->hd.stream_id; + } + break; } case NGHTTP2_PRIORITY: { @@ -1930,6 +1945,10 @@ static int session_prep_frame(nghttp2_session *session, return rv; } + assert(session->sent_stream_id + 2 <= + frame->push_promise.promised_stream_id); + session->sent_stream_id = frame->push_promise.promised_stream_id; + break; } case NGHTTP2_PING: @@ -3714,13 +3733,14 @@ int nghttp2_session_on_rst_stream_received(nghttp2_session *session, return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, "RST_STREAM: stream_id == 0"); } + + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "RST_STREAM: stream in idle"); + } + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); - if (!stream) { - if (session_detect_idle_stream(session, frame->hd.stream_id)) { - return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "RST_STREAM: stream in idle"); - } - } else { + if (stream) { /* We may use stream->shut_flags for strict error checking. */ nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); } @@ -4158,21 +4178,20 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session, session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: invalid promised_stream_id"); } + + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_inflate_handle_invalid_connection( + session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream in idle"); + } + session->last_recv_stream_id = frame->push_promise.promised_stream_id; stream = nghttp2_session_get_stream(session, frame->hd.stream_id); if (!stream || stream->state == NGHTTP2_STREAM_CLOSING || !session->pending_enable_push || session->num_incoming_reserved_streams >= session->max_incoming_reserved_streams) { - if (!stream) { - if (session_detect_idle_stream(session, frame->hd.stream_id)) { - return session_inflate_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "PUSH_PROMISE: stream in idle"); - } - - /* Currently, client does not retain closed stream, so we don't - check NGHTTP2_SHUT_RD condition here. */ - } + /* Currently, client does not retain closed stream, so we don't + check NGHTTP2_SHUT_RD condition here. */ rv = nghttp2_session_add_rst_stream( session, frame->push_promise.promised_stream_id, NGHTTP2_CANCEL); @@ -4324,12 +4343,14 @@ static int session_on_stream_window_update_received(nghttp2_session *session, nghttp2_frame *frame) { int rv; nghttp2_stream *stream; + + if (session_detect_idle_stream(session, frame->hd.stream_id)) { + return session_handle_invalid_connection(session, frame, NGHTTP2_ERR_PROTO, + "WINDOW_UPDATE to idle stream"); + } + stream = nghttp2_session_get_stream(session, frame->hd.stream_id); if (!stream) { - if (session_detect_idle_stream(session, frame->hd.stream_id)) { - return session_handle_invalid_connection( - session, frame, NGHTTP2_ERR_PROTO, "WINDOW_UPDATE to idle stream"); - } return 0; } if (state_reserved_remote(session, stream)) { @@ -4627,14 +4648,15 @@ static int session_on_data_received_fail_fast(nghttp2_session *session) { failure_reason = "DATA: stream_id == 0"; goto fail; } + + if (session_detect_idle_stream(session, stream_id)) { + failure_reason = "DATA: stream in idle"; + error_code = NGHTTP2_PROTOCOL_ERROR; + goto fail; + } + stream = nghttp2_session_get_stream(session, stream_id); if (!stream) { - if (session_detect_idle_stream(session, stream_id)) { - failure_reason = "DATA: stream in idle"; - error_code = NGHTTP2_PROTOCOL_ERROR; - goto fail; - } - stream = nghttp2_session_get_stream_raw(session, stream_id); if (stream && (stream->shut_flags & NGHTTP2_SHUT_RD)) { failure_reason = "DATA: stream closed"; diff --git a/lib/nghttp2_session.h b/lib/nghttp2_session.h index 5b47e94f..11f0b7cc 100644 --- a/lib/nghttp2_session.h +++ b/lib/nghttp2_session.h @@ -246,6 +246,10 @@ struct nghttp2_session { size_t obq_flood_counter_; /* Next Stream ID. Made unsigned int to detect >= (1 << 31). */ uint32_t next_stream_id; + /* The last stream ID this session initiated. For client session, + this is the last stream ID it has sent. For server session, it + is the last promised stream ID sent in PUSH_PROMISE. */ + int32_t sent_stream_id; /* The largest stream ID received so far */ int32_t last_recv_stream_id; /* The largest stream ID which has been processed in some way. This diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 6de1f9fc..3034aed6 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -707,9 +707,8 @@ void test_nghttp2_session_recv_data(void) { nghttp2_session_client_new(&session, &callbacks, &ud); /* Create stream 1 with CLOSING state. DATA is ignored. */ - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_CLOSING, NULL); + stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING); + /* Set initial window size 16383 to check stream flow control, isolating it from the conneciton flow control */ stream->local_window_size = 16383; @@ -796,7 +795,7 @@ void test_nghttp2_session_recv_data(void) { hd.stream_id = 1; nghttp2_frame_pack_frame_hd(data, &hd); - stream = open_stream(session, 1); + stream = open_recv_stream(session, 1); /* Send 32767 bytes of DATA. In our current flow control algorithm, it triggers first WINDOW_UPDATE of window_size_increment @@ -884,7 +883,7 @@ void test_nghttp2_session_recv_data_no_auto_flow_control(void) { /* First create stream 1, then close it. Check that data is consumed for connection in this situation */ - open_stream(session, 1); + open_recv_stream(session, 1); /* Receive first 100 bytes */ sendlen = 100; @@ -916,7 +915,7 @@ void test_nghttp2_session_recv_data_no_auto_flow_control(void) { /* Now we are expecting final response header, which means receiving DATA for that stream is illegal. */ - stream = open_stream(session, 1); + stream = open_recv_stream(session, 1); stream->http_flags |= NGHTTP2_HTTP_FLAG_EXPECT_FINAL_RESPONSE; rv = nghttp2_session_mem_recv(session, data, NGHTTP2_FRAME_HDLEN + hd.length); @@ -931,7 +930,7 @@ void test_nghttp2_session_recv_data_no_auto_flow_control(void) { /* Check window_update_queued flag in both session and stream */ nghttp2_session_server_new2(&session, &callbacks, &ud, option); - stream = open_stream(session, 1); + stream = open_recv_stream(session, 1); hd.length = 4096; hd.type = NGHTTP2_DATA; @@ -1219,7 +1218,7 @@ void test_nghttp2_session_recv_headers_with_priority(void) { nghttp2_hd_deflate_init(&deflater, mem); - open_stream(session, 1); + open_recv_stream(session, 1); /* With NGHTTP2_FLAG_PRIORITY without exclusive flag set */ nvlen = ARRLEN(reqnv); @@ -1448,8 +1447,7 @@ void test_nghttp2_session_server_recv_push_response(void) { nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); + open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); nvlen = ARRLEN(resnv); nghttp2_nv_array_copy(&nva, resnv, nvlen, mem); @@ -1526,8 +1524,8 @@ void test_nghttp2_session_recv_premature_headers(void) { nghttp2_session_client_new(&session, &callbacks, &ud); nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default, + NGHTTP2_STREAM_OPENING, NULL); rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv, ARRLEN(reqnv), mem); @@ -1607,7 +1605,7 @@ void test_nghttp2_session_recv_unexpected_continuation(void) { nghttp2_session_server_new(&session, &callbacks, &ud); - open_stream(session, 1); + open_recv_stream(session, 1); ud.frame_recv_cb_called = 0; @@ -2196,6 +2194,7 @@ void test_nghttp2_session_on_request_headers_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); session->next_stream_id = 5; + session->sent_stream_id = 3; /* Stream ID which is not idle and not in stream map is just ignored */ @@ -2242,8 +2241,7 @@ void test_nghttp2_session_on_request_headers_received(void) { nghttp2_session_server_new(&session, &callbacks, &user_data); /* HEADERS to closed stream */ - stream = open_stream(session, 1); - session->last_recv_stream_id = 1; + stream = open_recv_stream(session, 1); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR); @@ -2273,9 +2271,7 @@ void test_nghttp2_session_on_response_headers_received(void) { callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); @@ -2305,9 +2301,7 @@ void test_nghttp2_session_on_headers_received(void) { callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); + stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENED); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); @@ -2327,9 +2321,7 @@ void test_nghttp2_session_on_headers_received(void) { /* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is discarded. */ - stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_CLOSING, NULL); + stream = open_sent_stream2(session, 3, NGHTTP2_STREAM_CLOSING); frame.hd.stream_id = 3; frame.hd.flags = NGHTTP2_FLAG_END_HEADERS; CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == @@ -2339,17 +2331,14 @@ void test_nghttp2_session_on_headers_received(void) { CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called); /* Server initiated stream */ - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_recv_stream(session, 2); - /* half closed (remote) */ frame.hd.flags = NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM; frame.hd.stream_id = 2; CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream)); CU_ASSERT(3 == user_data.begin_headers_cb_called); - CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); + CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); @@ -2379,9 +2368,7 @@ void test_nghttp2_session_on_push_response_headers_received(void) { callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_RESERVED, NULL); + stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); /* nghttp2_session_on_push_response_headers_received assumes @@ -2403,9 +2390,7 @@ void test_nghttp2_session_on_push_response_headers_received(void) { /* If un-ACKed max concurrent streams limit is exceeded, RST_STREAMed */ session->pending_local_max_concurrent_stream = 1; - stream = nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_RESERVED, NULL); + stream = open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED); frame.hd.stream_id = 4; CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == nghttp2_session_on_push_response_headers_received(session, &frame, @@ -2423,9 +2408,7 @@ void test_nghttp2_session_on_push_response_headers_received(void) { issued */ session->local_settings.max_concurrent_streams = 1; - stream = nghttp2_session_open_stream(session, 6, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_RESERVED, NULL); + stream = open_recv_stream2(session, 6, NGHTTP2_STREAM_RESERVED); frame.hd.stream_id = 6; CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == @@ -2455,9 +2438,7 @@ void test_nghttp2_session_on_priority_received(void) { callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback; nghttp2_session_server_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_recv_stream(session, 1); nghttp2_priority_spec_init(&pri_spec, 0, 2, 0); @@ -2468,13 +2449,8 @@ void test_nghttp2_session_on_priority_received(void) { CU_ASSERT(2 == stream->weight); - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); - - dep_stream = nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_sent_stream(session, 2); + dep_stream = open_recv_stream(session, 3); frame.hd.stream_id = 2; @@ -2500,8 +2476,7 @@ void test_nghttp2_session_on_priority_received(void) { /* Check dep_stream_id == stream_id case */ nghttp2_session_server_new(&session, &callbacks, &user_data); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL); + open_recv_stream(session, 1); nghttp2_priority_spec_init(&pri_spec, 1, 0, 0); @@ -2540,8 +2515,7 @@ void test_nghttp2_session_on_rst_stream_received(void) { nghttp2_frame frame; memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_server_new(&session, &callbacks, &user_data); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream(session, 1); nghttp2_frame_rst_stream_init(&frame.rst_stream, 1, NGHTTP2_PROTOCOL_ERROR); @@ -2587,12 +2561,9 @@ void test_nghttp2_session_on_settings_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); session->remote_settings.initial_window_size = 16 * 1024; - stream1 = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); - stream2 = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream1 = open_sent_stream(session, 1); + stream2 = open_recv_stream(session, 2); + /* Set window size for each streams and will see how settings updates these values */ stream1->remote_window_size = 16 * 1024; @@ -2719,9 +2690,8 @@ void test_nghttp2_session_on_push_promise_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_sent_stream(session, 1); + nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS, 1, 2, NULL, 0); @@ -2759,9 +2729,7 @@ void test_nghttp2_session_on_push_promise_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_sent_stream(session, 1); /* Attempt to PUSH_PROMISE against stream in closing state */ stream->state = NGHTTP2_STREAM_CLOSING; @@ -2803,9 +2771,7 @@ void test_nghttp2_session_on_push_promise_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_sent_stream(session, 1); /* Same ID twice */ frame.hd.stream_id = 1; @@ -2850,8 +2816,8 @@ void test_nghttp2_session_on_push_promise_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); - nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); + open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); + /* Attempt to PUSH_PROMISE against reserved (remote) stream */ nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS, 2, 4, NULL, 0); @@ -2871,8 +2837,7 @@ void test_nghttp2_session_on_push_promise_received(void) { /* Disable PUSH */ nghttp2_session_client_new(&session, &callbacks, &user_data); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); session->local_settings.enable_push = 0; @@ -2894,8 +2859,8 @@ void test_nghttp2_session_on_push_promise_received(void) { /* Check malformed headers. We accept malformed headers */ nghttp2_session_client_new(&session, &callbacks, &user_data); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); + nvlen = ARRLEN(malformed_nva); nghttp2_nv_array_copy(&nva, malformed_nva, nvlen, mem); nghttp2_frame_push_promise_init(&frame.push_promise, NGHTTP2_FLAG_END_HEADERS, @@ -2914,8 +2879,8 @@ void test_nghttp2_session_on_push_promise_received(void) { peer, incoming PUSH_PROMISE is rejected */ nghttp2_session_client_new(&session, &callbacks, &user_data); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); + /* Submit settings with ENABLE_PUSH = 0 (thus disabling push) */ nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1); @@ -2934,10 +2899,8 @@ void test_nghttp2_session_on_push_promise_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); session->max_incoming_reserved_streams = 1; - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); - nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); + open_sent_stream(session, 1); + open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); CU_ASSERT(1 == session->num_incoming_reserved_streams); @@ -3017,7 +2980,11 @@ void test_nghttp2_session_on_goaway_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); for (i = 1; i <= 7; ++i) { - open_stream(session, i); + if (nghttp2_session_is_my_stream_id(session, i)) { + open_sent_stream(session, i); + } else { + open_recv_stream(session, i); + } } nghttp2_frame_goaway_init(&frame.goaway, 3, NGHTTP2_PROTOCOL_ERROR, NULL, 0); @@ -3062,9 +3029,7 @@ void test_nghttp2_session_on_window_update_received(void) { nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); + stream = open_sent_stream(session, 1); data_item = create_data_ob_item(mem); @@ -3091,8 +3056,7 @@ void test_nghttp2_session_on_window_update_received(void) { /* Receiving WINDOW_UPDATE on reserved (remote) stream is a connection error */ - nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); + open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2, 4096); @@ -3108,9 +3072,7 @@ void test_nghttp2_session_on_window_update_received(void) { /* Receiving WINDOW_UPDATE on reserved (local) stream is allowed */ nghttp2_session_server_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_RESERVED, NULL); + stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); nghttp2_frame_window_update_init(&frame.window_update, NGHTTP2_FLAG_NONE, 2, 4096); @@ -3136,9 +3098,7 @@ void test_nghttp2_session_on_data_received(void) { memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_recv_stream(session, 2); nghttp2_frame_hd_init(&frame.hd, 4096, NGHTTP2_DATA, NGHTTP2_FLAG_NONE, 2); @@ -3151,11 +3111,10 @@ void test_nghttp2_session_on_data_received(void) { CU_ASSERT(NGHTTP2_SHUT_RD == stream->shut_flags); /* If NGHTTP2_STREAM_CLOSING state, DATA frame is discarded. */ - nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_CLOSING, NULL); + open_sent_stream2(session, 1, NGHTTP2_STREAM_CLOSING); frame.hd.flags = NGHTTP2_FLAG_NONE; - frame.hd.stream_id = 4; + frame.hd.stream_id = 1; CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame)); CU_ASSERT(NULL == nghttp2_outbound_queue_top(&session->ob_reg)); @@ -3163,14 +3122,12 @@ void test_nghttp2_session_on_data_received(void) { /* Check INVALID_STREAM case: DATA frame with stream ID which does not exist. */ - frame.hd.stream_id = 6; + frame.hd.stream_id = 3; CU_ASSERT(0 == nghttp2_session_on_data_received(session, &frame)); top = nghttp2_outbound_queue_top(&session->ob_reg); - /* DATA against nonexistent stream is just ignored for now */ + /* DATA against nonexistent stream is just ignored for now. */ CU_ASSERT(top == NULL); - /* CU_ASSERT(NGHTTP2_RST_STREAM == top->frame.hd.type); */ - /* CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == top->frame.rst_stream.error_code); */ nghttp2_session_del(session); } @@ -3191,7 +3148,7 @@ void test_nghttp2_session_on_data_received_fail_fast(void) { nghttp2_session_server_new(&session, &callbacks, NULL); /* DATA to closed (remote) */ - stream = open_stream(session, 1); + stream = open_recv_stream(session, 1); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); CU_ASSERT((ssize_t)sizeof(buf) == @@ -3207,7 +3164,7 @@ void test_nghttp2_session_on_data_received_fail_fast(void) { nghttp2_session_server_new(&session, &callbacks, NULL); /* DATA to closed stream with explicit closed (remote) */ - stream = open_stream(session, 1); + stream = open_recv_stream(session, 1); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD); nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR); @@ -3269,9 +3226,8 @@ void test_nghttp2_session_send_headers_reply(void) { memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; - CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); - nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL)); + open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); @@ -3279,11 +3235,11 @@ void test_nghttp2_session_send_headers_reply(void) { frame = &item->frame; - nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2, + nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 1, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0); nghttp2_session_add_item(session, item); CU_ASSERT(0 == nghttp2_session_send(session)); - stream = nghttp2_session_get_stream(session, 2); + stream = nghttp2_session_get_stream(session, 1); CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state); nghttp2_session_del(session); @@ -3365,8 +3321,7 @@ void test_nghttp2_session_send_headers_push_reply(void) { callbacks.send_callback = null_send_callback; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL)); - nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); + open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); @@ -3399,8 +3354,7 @@ void test_nghttp2_session_send_rst_stream(void) { memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; nghttp2_session_client_new(&session, &callbacks, &user_data); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); @@ -3433,8 +3387,7 @@ void test_nghttp2_session_send_push_promise(void) { callbacks.on_frame_not_send_callback = on_frame_not_send_callback; nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream(session, 1); item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); @@ -3485,8 +3438,7 @@ void test_nghttp2_session_send_push_promise(void) { /* PUSH_PROMISE from client is error */ nghttp2_session_client_new(&session, &callbacks, &ud); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); item = mem->malloc(sizeof(nghttp2_outbound_item), NULL); nghttp2_outbound_item_init(item); @@ -3606,9 +3558,7 @@ void test_nghttp2_session_reprioritize_stream(void) { nghttp2_session_server_new(&session, &callbacks, &ud); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_recv_stream(session, 1); nghttp2_priority_spec_init(&pri_spec, 0, 10, 0); @@ -3630,7 +3580,7 @@ void test_nghttp2_session_reprioritize_stream(void) { CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == dep_stream->weight); - dep_stream = open_stream(session, 3); + dep_stream = open_recv_stream(session, 3); /* Change weight */ pri_spec.weight = 128; @@ -3682,9 +3632,7 @@ void test_nghttp2_session_reprioritize_stream_with_idle_stream_dep(void) { nghttp2_session_server_new(&session, &callbacks, NULL); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_recv_stream(session, 1); session->pending_local_max_concurrent_stream = 1; @@ -3724,8 +3672,8 @@ void test_nghttp2_submit_data(void) { aob = &session->aob; framebufs = &aob->framebufs; - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); + CU_ASSERT( 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd)); @@ -3766,8 +3714,8 @@ void test_nghttp2_submit_data_read_length_too_large(void) { aob = &session->aob; framebufs = &aob->framebufs; - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); + CU_ASSERT( 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd)); @@ -3793,8 +3741,8 @@ void test_nghttp2_submit_data_read_length_too_large(void) { session->remote_settings.max_frame_size = NGHTTP2_MAX_FRAME_SIZE_MAX; - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); + CU_ASSERT( 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd)); @@ -3845,8 +3793,8 @@ void test_nghttp2_submit_data_read_length_smallest(void) { aob = &session->aob; framebufs = &aob->framebufs; - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); + CU_ASSERT( 0 == nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd)); @@ -3912,11 +3860,9 @@ void test_nghttp2_submit_data_twice(void) { CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &data_prd)); - CU_ASSERT(0 == nghttp2_session_send(session)); /* We should have sent 2 DATA frame with 16 bytes payload each */ @@ -4027,8 +3973,7 @@ void test_nghttp2_submit_response_with_data(void) { data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 64 * 1024 - 1; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), &data_prd)); item = nghttp2_session_get_next_ob_item(session); @@ -4065,8 +4010,7 @@ void test_nghttp2_submit_response_without_data(void) { CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); nghttp2_hd_inflate_init(&inflater, mem); - nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), &data_prd)); item = nghttp2_session_get_next_ob_item(session); @@ -4102,8 +4046,7 @@ void test_nghttp2_submit_response_push_response(void) { nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_session_open_stream(session, 2, NGHTTP2_FLAG_NONE, &pri_spec_default, - NGHTTP2_STREAM_RESERVED, NULL); + open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); session->goaway_flags |= NGHTTP2_GOAWAY_RECV; @@ -4143,8 +4086,7 @@ void test_nghttp2_submit_trailer(void) { CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); nghttp2_hd_inflate_init(&inflater, mem); - nghttp2_session_open_stream(session, 1, NGHTTP2_FLAG_END_STREAM, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); CU_ASSERT(0 == nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), &data_prd)); CU_ASSERT(0 == nghttp2_session_send(session)); @@ -4229,9 +4171,7 @@ void test_nghttp2_submit_headers_reply(void) { CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == ud.frame_send_cb_called); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL, resnv, ARRLEN(resnv), NULL)); @@ -4255,9 +4195,7 @@ void test_nghttp2_submit_headers_push_reply(void) { callbacks.on_frame_send_callback = on_frame_send_callback; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_RESERVED, NULL); + stream = open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL, resnv, ARRLEN(resnv), &foo)); @@ -4274,8 +4212,7 @@ void test_nghttp2_submit_headers_push_reply(void) { /* Sending HEADERS from client against stream in reserved state is error */ CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); - nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); + open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 2, NULL, reqnv, ARRLEN(reqnv), NULL)); @@ -4330,9 +4267,7 @@ void test_nghttp2_submit_headers(void) { CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == ud.frame_send_cb_called); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_sent_stream(session, 1); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 1, NULL, reqnv, ARRLEN(reqnv), NULL)); @@ -4423,9 +4358,7 @@ void test_nghttp2_submit_priority(void) { callbacks.on_frame_send_callback = on_frame_send_callback; nghttp2_session_client_new(&session, &callbacks, &ud); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_sent_stream(session, 1); nghttp2_priority_spec_init(&pri_spec, 0, 3, 0); @@ -4554,14 +4487,11 @@ void test_nghttp2_submit_settings_update_local_window_size(void) { nghttp2_session_server_new(&session, &callbacks, NULL); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); + stream = open_recv_stream(session, 1); stream->local_window_size = NGHTTP2_INITIAL_WINDOW_SIZE + 100; stream->recv_window_size = 32768; - nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL); + open_recv_stream(session, 3); CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1)); CU_ASSERT(0 == nghttp2_session_send(session)); @@ -4583,9 +4513,7 @@ void test_nghttp2_submit_settings_update_local_window_size(void) { /* Check overflow case */ iv[0].value = 128 * 1024; nghttp2_session_server_new(&session, &callbacks, NULL); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); + stream = open_recv_stream(session, 1); stream->local_window_size = NGHTTP2_MAX_WINDOW_SIZE; CU_ASSERT(0 == nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, iv, 1)); @@ -4689,8 +4617,7 @@ void test_nghttp2_submit_push_promise(void) { callbacks.on_frame_not_send_callback = on_frame_not_send_callback; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream(session, 1); CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, reqnv, ARRLEN(reqnv), &ud)); @@ -4731,9 +4658,7 @@ void test_nghttp2_submit_window_update(void) { callbacks.send_callback = null_send_callback; nghttp2_session_client_new(&session, &callbacks, &ud); - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); + stream = open_recv_stream(session, 2); stream->recv_window_size = 4096; CU_ASSERT(0 == @@ -4780,9 +4705,7 @@ void test_nghttp2_submit_window_update_local_window_size(void) { callbacks.send_callback = null_send_callback; nghttp2_session_client_new(&session, &callbacks, NULL); - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); + stream = open_recv_stream(session, 2); stream->recv_window_size = 4096; CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2, @@ -4941,7 +4864,7 @@ void test_nghttp2_submit_invalid_nv(void) { NULL)); /* nghttp2_submit_push_promise */ - open_stream(session, 1); + open_recv_stream(session, 1); CU_ASSERT(0 < nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, empty_name_nv, @@ -5017,6 +4940,7 @@ void test_nghttp2_session_open_stream(void) { NGHTTP2_STREAM_OPENED, NULL); CU_ASSERT(NGHTTP2_DEFAULT_WEIGHT == stream->weight); + CU_ASSERT(&session->root == stream->dep_prev); nghttp2_session_del(session); @@ -5081,7 +5005,7 @@ void test_nghttp2_session_get_next_ob_item(void) { memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; - nghttp2_session_server_new(&session, &callbacks, NULL); + nghttp2_session_client_new(&session, &callbacks, NULL); session->remote_settings.max_concurrent_streams = 2; CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); @@ -5089,7 +5013,7 @@ void test_nghttp2_session_get_next_ob_item(void) { CU_ASSERT(NGHTTP2_PING == nghttp2_session_get_next_ob_item(session)->frame.hd.type); - nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL); + CU_ASSERT(1 == nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL)); CU_ASSERT(NGHTTP2_PING == nghttp2_session_get_next_ob_item(session)->frame.hd.type); @@ -5098,17 +5022,18 @@ void test_nghttp2_session_get_next_ob_item(void) { /* Incoming stream does not affect the number of outgoing max concurrent streams. */ - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream(session, 2); nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0); - nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL); + CU_ASSERT(3 == + nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL)); CU_ASSERT(NGHTTP2_HEADERS == nghttp2_session_get_next_ob_item(session)->frame.hd.type); CU_ASSERT(0 == nghttp2_session_send(session)); - nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL); + CU_ASSERT(5 == + nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL)); CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); session->remote_settings.max_concurrent_streams = 3; @@ -5117,6 +5042,16 @@ void test_nghttp2_session_get_next_ob_item(void) { nghttp2_session_get_next_ob_item(session)->frame.hd.type); nghttp2_session_del(session); + + /* Check that push reply HEADERS are queued into ob_ss_pq */ + nghttp2_session_server_new(&session, &callbacks, NULL); + session->remote_settings.max_concurrent_streams = 0; + open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); + CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2, + NULL, NULL, 0, NULL)); + CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session)); + CU_ASSERT(1 == nghttp2_outbound_queue_size(&session->ob_syn)); + nghttp2_session_del(session); } void test_nghttp2_session_pop_next_ob_item(void) { @@ -5213,8 +5148,7 @@ void test_nghttp2_session_reply_fail(void) { data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 4 * 1024; CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, &ud)); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); CU_ASSERT(0 == nghttp2_submit_response(session, 1, NULL, 0, &data_prd)); CU_ASSERT(NGHTTP2_ERR_CALLBACK_FAILURE == nghttp2_session_send(session)); nghttp2_session_del(session); @@ -5232,8 +5166,7 @@ void test_nghttp2_session_max_concurrent_streams(void) { callbacks.send_callback = null_send_callback; nghttp2_session_server_new(&session, &callbacks, NULL); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, NULL); + open_recv_stream(session, 1); /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */ nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3, @@ -5280,8 +5213,7 @@ void test_nghttp2_session_stop_data_with_rst_stream(void) { ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4; nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); nghttp2_submit_response(session, 1, NULL, 0, &data_prd); ud.block_count = 2; @@ -5325,9 +5257,7 @@ void test_nghttp2_session_defer_data(void) { ud.data_source_length = NGHTTP2_DATA_PAYLOADLEN * 4; nghttp2_session_server_new(&session, &callbacks, &ud); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); session->remote_window_size = 1 << 20; stream->remote_window_size = 1 << 20; @@ -5507,11 +5437,7 @@ void test_nghttp2_session_flow_control_data_recv(void) { /* Initial window size to 64KiB - 1*/ nghttp2_session_client_new(&session, &callbacks, NULL); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); - - session->next_stream_id = 3; + stream = open_sent_stream(session, 1); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); @@ -5577,9 +5503,7 @@ void test_nghttp2_session_flow_control_data_with_padding_recv(void) { nghttp2_option_del(option); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); + stream = open_sent_stream(session, 1); /* Create DATA frame */ memset(data, 0, sizeof(data)); @@ -5720,9 +5644,9 @@ void test_nghttp2_session_on_stream_close(void) { user_data.stream_close_cb_called = 0; nghttp2_session_client_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - &user_data); + stream = + open_sent_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default, + NGHTTP2_STREAM_OPENED, &user_data); CU_ASSERT(stream != NULL); CU_ASSERT(nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR) == 0); CU_ASSERT(user_data.stream_close_cb_called == 1); @@ -5743,9 +5667,9 @@ void test_nghttp2_session_on_ctrl_not_send(void) { user_data.not_sent_error = 0; nghttp2_session_server_new(&session, &callbacks, &user_data); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, &user_data); + stream = + open_recv_stream3(session, 1, NGHTTP2_STREAM_FLAG_NONE, &pri_spec_default, + NGHTTP2_STREAM_OPENING, &user_data); /* Check response HEADERS */ /* Send bogus stream ID */ @@ -5830,9 +5754,7 @@ void test_nghttp2_session_get_effective_local_window_size(void) { memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENED, - NULL); + stream = open_sent_stream(session, 1); CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE == nghttp2_session_get_effective_local_window_size(session)); @@ -5986,8 +5908,7 @@ static void check_session_recv_data_with_padding(nghttp2_bufs *bufs, callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; nghttp2_session_server_new(&session, &callbacks, &ud); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream(session, 1); inlen = (size_t)nghttp2_bufs_remove(bufs, &in); @@ -7636,7 +7557,7 @@ void test_nghttp2_session_find_stream(void) { nghttp2_session_server_new(&session, &callbacks, NULL); - open_stream(session, 1); + open_recv_stream(session, 1); stream = nghttp2_session_find_stream(session, 1); @@ -7671,7 +7592,7 @@ void test_nghttp2_session_keep_closed_stream(void) { nghttp2_submit_settings(session, NGHTTP2_FLAG_NONE, &iv, 1); for (i = 0; i < max_concurrent_streams; ++i) { - open_stream(session, (int)i * 2 + 1); + open_recv_stream(session, (int32_t)i * 2 + 1); } CU_ASSERT(0 == session->num_closed_streams); @@ -7694,7 +7615,7 @@ void test_nghttp2_session_keep_closed_stream(void) { session->closed_stream_head->closed_next); CU_ASSERT(NULL == session->closed_stream_head->closed_prev); - open_stream(session, 11); + open_recv_stream(session, 11); nghttp2_session_adjust_closed_stream(session); CU_ASSERT(1 == session->num_closed_streams); @@ -7703,7 +7624,7 @@ void test_nghttp2_session_keep_closed_stream(void) { CU_ASSERT(NULL == session->closed_stream_head->closed_prev); CU_ASSERT(NULL == session->closed_stream_head->closed_next); - open_stream(session, 13); + open_recv_stream(session, 13); nghttp2_session_adjust_closed_stream(session); CU_ASSERT(0 == session->num_closed_streams); @@ -7716,7 +7637,7 @@ void test_nghttp2_session_keep_closed_stream(void) { CU_ASSERT(3 == session->closed_stream_head->stream_id); /* server initiated stream is not counted to max concurrent limit */ - open_stream(session, 2); + open_sent_stream(session, 2); nghttp2_session_adjust_closed_stream(session); CU_ASSERT(1 == session->num_closed_streams); @@ -7749,8 +7670,7 @@ void test_nghttp2_session_keep_idle_stream(void) { /* We at least allow NGHTTP2_MIN_IDLE_STREAM idle streams even if max concurrent streams is very low. */ for (i = 0; i < NGHTTP2_MIN_IDLE_STREAMS; ++i) { - nghttp2_session_open_stream(session, i * 2 + 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL); + open_recv_stream2(session, i * 2 + 1, NGHTTP2_STREAM_IDLE); nghttp2_session_adjust_idle_stream(session); } @@ -7762,8 +7682,7 @@ void test_nghttp2_session_keep_idle_stream(void) { stream_id += 2; - nghttp2_session_open_stream(session, stream_id, NGHTTP2_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_IDLE, NULL); + open_recv_stream2(session, stream_id, NGHTTP2_STREAM_IDLE); nghttp2_session_adjust_idle_stream(session); CU_ASSERT(NGHTTP2_MIN_IDLE_STREAMS == session->num_idle_streams); @@ -7895,11 +7814,11 @@ void test_nghttp2_session_graceful_shutdown(void) { nghttp2_session_server_new(&session, &callbacks, &ud); - open_stream(session, 301); - open_stream(session, 302); - open_stream(session, 309); - open_stream(session, 311); - open_stream(session, 319); + open_recv_stream(session, 301); + open_sent_stream(session, 302); + open_recv_stream(session, 309); + open_recv_stream(session, 311); + open_recv_stream(session, 319); CU_ASSERT(0 == nghttp2_submit_shutdown_notice(session)); @@ -8014,8 +7933,7 @@ void test_nghttp2_session_on_header_temporal_failure(void) { nghttp2_hd_deflate_init(&deflater, mem); nghttp2_session_client_new(&session, &callbacks, &ud); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv, ARRLEN(reqnv), mem); @@ -8103,16 +8021,14 @@ void test_nghttp2_session_delete_data_item(void) { nghttp2_session_server_new(&session, &callbacks, NULL); - a = open_stream(session, 1); - open_stream_with_dep(session, 3, a); + a = open_recv_stream(session, 1); + open_recv_stream_with_dep(session, 3, a); /* We don't care about these members, since we won't send data */ prd.source.ptr = NULL; prd.read_callback = fail_data_source_read_callback; - /* This data item will be marked as TOP */ CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 1, &prd)); - /* This data item will be marked as REST */ CU_ASSERT(0 == nghttp2_submit_data(session, NGHTTP2_FLAG_NONE, 3, &prd)); nghttp2_session_del(session); @@ -8145,9 +8061,7 @@ void test_nghttp2_session_open_idle_stream(void) { 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, - NGHTTP2_STREAM_OPENING, NULL); + opened_stream = open_recv_stream2(session, 1, NGHTTP2_STREAM_OPENING); CU_ASSERT(stream == opened_stream); CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state); @@ -8182,11 +8096,7 @@ void test_nghttp2_session_cancel_reserved_remote(void) { nghttp2_hd_deflate_init(&deflater, mem); - stream = nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_RESERVED, NULL); - - session->last_recv_stream_id = 2; + stream = open_recv_stream2(session, 2, NGHTTP2_STREAM_RESERVED); nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL); @@ -8217,10 +8127,7 @@ void test_nghttp2_session_cancel_reserved_remote(void) { /* Check that we can receive push response HEADERS while RST_STREAM is just queued. */ - nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); - - session->last_recv_stream_id = 4; + open_recv_stream2(session, 4, NGHTTP2_STREAM_RESERVED); nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, 2, NGHTTP2_CANCEL); @@ -8320,8 +8227,7 @@ void test_nghttp2_session_send_data_callback(void) { nghttp2_session_client_new(&session, &callbacks, &ud); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); nghttp2_submit_data(session, NGHTTP2_FLAG_END_STREAM, 1, &data_prd); @@ -8391,8 +8297,7 @@ void test_nghttp2_session_on_begin_headers_temporal_failure(void) { nghttp2_hd_deflate_init(&deflater, mem); nghttp2_session_client_new(&session, &callbacks, &ud); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv, ARRLEN(reqnv), mem); @@ -8488,8 +8393,8 @@ void test_nghttp2_session_detach_item_from_closed_stream(void) { nghttp2_session_server_new(&session, &callbacks, NULL); - open_stream(session, 1); - open_stream(session, 3); + open_recv_stream(session, 1); + open_recv_stream(session, 3); nghttp2_session_close_stream(session, 1, NGHTTP2_NO_ERROR); nghttp2_session_close_stream(session, 3, NGHTTP2_NO_ERROR); @@ -8569,9 +8474,9 @@ void test_nghttp2_session_change_stream_priority(void) { nghttp2_session_server_new(&session, &callbacks, NULL); - stream1 = open_stream(session, 1); - stream3 = open_stream_with_dep_weight(session, 3, 199, stream1); - stream2 = open_stream_with_dep_weight(session, 2, 101, stream3); + stream1 = open_recv_stream(session, 1); + stream3 = open_recv_stream_with_dep_weight(session, 3, 199, stream1); + stream2 = open_sent_stream_with_dep_weight(session, 2, 101, stream3); nghttp2_priority_spec_init(&pri_spec, 1, 256, 0); @@ -8614,7 +8519,7 @@ void test_nghttp2_session_change_stream_priority(void) { /* Check that this works in client session too */ nghttp2_session_client_new(&session, &callbacks, NULL); - stream1 = open_stream(session, 1); + stream1 = open_sent_stream(session, 1); nghttp2_priority_spec_init(&pri_spec, 5, 9, 1); @@ -8645,7 +8550,7 @@ void test_nghttp2_session_create_idle_stream(void) { nghttp2_session_server_new(&session, &callbacks, NULL); - stream2 = open_stream(session, 2); + stream2 = open_sent_stream(session, 2); nghttp2_priority_spec_init(&pri_spec, 2, 111, 1); @@ -8884,9 +8789,11 @@ static void check_nghttp2_http_recv_headers_fail( ud = session->user_data; if (stream_state != -1) { - nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - (nghttp2_stream_state)stream_state, NULL); + if (nghttp2_session_is_my_stream_id(session, stream_id)) { + open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state); + } else { + open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state); + } } rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva, @@ -8924,9 +8831,11 @@ static void check_nghttp2_http_recv_headers_ok( ud = session->user_data; if (stream_state != -1) { - nghttp2_session_open_stream(session, stream_id, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - (nghttp2_stream_state)stream_state, NULL); + if (nghttp2_session_is_my_stream_id(session, stream_id)) { + open_sent_stream2(session, stream_id, (nghttp2_stream_state)stream_state); + } else { + open_recv_stream2(session, stream_id, (nghttp2_stream_state)stream_state); + } } rv = pack_headers(&bufs, deflater, stream_id, NGHTTP2_FLAG_END_HEADERS, nva, @@ -9169,9 +9078,7 @@ void test_nghttp2_http_content_length(void) { nghttp2_hd_deflate_init(&deflater, mem); - stream = nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, - NGHTTP2_STREAM_OPENING, NULL); + stream = open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, cl_resnv, ARRLEN(cl_resnv), mem); @@ -9332,8 +9239,7 @@ void test_nghttp2_http_non_final_response(void) { nghttp2_hd_deflate_init(&deflater, mem); /* non-final HEADERS with END_STREAM is illegal */ - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, @@ -9353,8 +9259,7 @@ void test_nghttp2_http_non_final_response(void) { nghttp2_bufs_reset(&bufs); /* non-final HEADERS followed by non-empty DATA is illegal */ - nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream2(session, 3, NGHTTP2_STREAM_OPENING); rv = pack_headers(&bufs, &deflater, 3, NGHTTP2_FLAG_END_HEADERS, nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); @@ -9378,8 +9283,7 @@ void test_nghttp2_http_non_final_response(void) { /* non-final HEADERS followed by empty DATA (without END_STREAM) is ok */ - nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream2(session, 5, NGHTTP2_STREAM_OPENING); rv = pack_headers(&bufs, &deflater, 5, NGHTTP2_FLAG_END_HEADERS, nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); @@ -9400,8 +9304,7 @@ void test_nghttp2_http_non_final_response(void) { /* non-final HEADERS followed by empty DATA (with END_STREAM) is illegal */ - nghttp2_session_open_stream(session, 7, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream2(session, 7, NGHTTP2_STREAM_OPENING); rv = pack_headers(&bufs, &deflater, 7, NGHTTP2_FLAG_END_HEADERS, nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); @@ -9425,8 +9328,7 @@ void test_nghttp2_http_non_final_response(void) { nghttp2_bufs_reset(&bufs); /* non-final HEADERS followed by final HEADERS is OK */ - nghttp2_session_open_stream(session, 9, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream2(session, 9, NGHTTP2_STREAM_OPENING); rv = pack_headers(&bufs, &deflater, 9, NGHTTP2_FLAG_END_HEADERS, nonfinal_resnv, ARRLEN(nonfinal_resnv), mem); @@ -9657,8 +9559,7 @@ void test_nghttp2_http_ignore_content_length(void) { nghttp2_hd_deflate_init(&deflater, mem); /* If status 304, content-length must be ignored */ - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); rv = pack_headers(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM, @@ -9775,8 +9676,7 @@ void test_nghttp2_http_push_promise(void) { nghttp2_hd_deflate_init(&deflater, mem); - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream2(session, 1, NGHTTP2_STREAM_OPENING); rv = pack_push_promise(&bufs, &deflater, 1, NGHTTP2_FLAG_END_HEADERS, 2, reqnv, ARRLEN(reqnv), mem); diff --git a/tests/nghttp2_test_helper.c b/tests/nghttp2_test_helper.c index 68599680..b21e5e45 100644 --- a/tests/nghttp2_test_helper.c +++ b/tests/nghttp2_test_helper.c @@ -306,3 +306,119 @@ nghttp2_outbound_item *create_data_ob_item(nghttp2_mem *mem) { return item; } + +nghttp2_stream *open_sent_stream(nghttp2_session *session, int32_t stream_id) { + nghttp2_priority_spec pri_spec; + + nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_DEFAULT_WEIGHT, 0); + return open_sent_stream3(session, stream_id, NGHTTP2_FLAG_NONE, &pri_spec, + NGHTTP2_STREAM_OPENED, NULL); +} + +nghttp2_stream *open_sent_stream2(nghttp2_session *session, int32_t stream_id, + nghttp2_stream_state initial_state) { + nghttp2_priority_spec pri_spec; + + nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_DEFAULT_WEIGHT, 0); + return open_sent_stream3(session, stream_id, NGHTTP2_FLAG_NONE, &pri_spec, + initial_state, NULL); +} + +nghttp2_stream *open_sent_stream3(nghttp2_session *session, int32_t stream_id, + uint8_t flags, + nghttp2_priority_spec *pri_spec_in, + nghttp2_stream_state initial_state, + void *stream_user_data) { + nghttp2_stream *stream; + + assert(nghttp2_session_is_my_stream_id(session, stream_id)); + + stream = nghttp2_session_open_stream(session, stream_id, flags, pri_spec_in, + initial_state, stream_user_data); + session->sent_stream_id = nghttp2_max(session->sent_stream_id, stream_id); + session->next_stream_id = + nghttp2_max(session->next_stream_id, (uint32_t)stream_id + 2); + + return stream; +} + +nghttp2_stream *open_sent_stream_with_dep(nghttp2_session *session, + int32_t stream_id, + nghttp2_stream *dep_stream) { + return open_sent_stream_with_dep_weight(session, stream_id, + NGHTTP2_DEFAULT_WEIGHT, dep_stream); +} + +nghttp2_stream *open_sent_stream_with_dep_weight(nghttp2_session *session, + int32_t stream_id, + int32_t weight, + nghttp2_stream *dep_stream) { + nghttp2_stream *stream; + + assert(nghttp2_session_is_my_stream_id(session, stream_id)); + + stream = open_stream_with_all(session, stream_id, weight, 0, dep_stream); + + session->sent_stream_id = nghttp2_max(session->sent_stream_id, stream_id); + session->next_stream_id = + nghttp2_max(session->next_stream_id, (uint32_t)stream_id + 2); + + return stream; +} + +nghttp2_stream *open_recv_stream(nghttp2_session *session, int32_t stream_id) { + nghttp2_priority_spec pri_spec; + + nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_DEFAULT_WEIGHT, 0); + return open_recv_stream3(session, stream_id, NGHTTP2_FLAG_NONE, &pri_spec, + NGHTTP2_STREAM_OPENED, NULL); +} + +nghttp2_stream *open_recv_stream2(nghttp2_session *session, int32_t stream_id, + nghttp2_stream_state initial_state) { + nghttp2_priority_spec pri_spec; + + nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_DEFAULT_WEIGHT, 0); + return open_recv_stream3(session, stream_id, NGHTTP2_FLAG_NONE, &pri_spec, + initial_state, NULL); +} + +nghttp2_stream *open_recv_stream3(nghttp2_session *session, int32_t stream_id, + uint8_t flags, + nghttp2_priority_spec *pri_spec_in, + nghttp2_stream_state initial_state, + void *stream_user_data) { + nghttp2_stream *stream; + + assert(!nghttp2_session_is_my_stream_id(session, stream_id)); + + stream = nghttp2_session_open_stream(session, stream_id, flags, pri_spec_in, + initial_state, stream_user_data); + session->last_recv_stream_id = + nghttp2_max(session->last_recv_stream_id, stream_id); + + return stream; +} + +nghttp2_stream *open_recv_stream_with_dep(nghttp2_session *session, + int32_t stream_id, + nghttp2_stream *dep_stream) { + return open_recv_stream_with_dep_weight(session, stream_id, + NGHTTP2_DEFAULT_WEIGHT, dep_stream); +} + +nghttp2_stream *open_recv_stream_with_dep_weight(nghttp2_session *session, + int32_t stream_id, + int32_t weight, + nghttp2_stream *dep_stream) { + nghttp2_stream *stream; + + assert(!nghttp2_session_is_my_stream_id(session, stream_id)); + + stream = open_stream_with_all(session, stream_id, weight, 0, dep_stream); + + session->last_recv_stream_id = + nghttp2_max(session->last_recv_stream_id, stream_id); + + return stream; +} diff --git a/tests/nghttp2_test_helper.h b/tests/nghttp2_test_helper.h index c044a064..f23625b8 100644 --- a/tests/nghttp2_test_helper.h +++ b/tests/nghttp2_test_helper.h @@ -110,4 +110,49 @@ nghttp2_stream *open_stream_with_dep_excl(nghttp2_session *session, nghttp2_outbound_item *create_data_ob_item(nghttp2_mem *mem); +/* Opens stream. This stream is assumed to be sent from |session|, + and session->sent_stream_id and session->next_stream_id will be + adjusted accordingly. */ +nghttp2_stream *open_sent_stream(nghttp2_session *session, int32_t stream_id); + +nghttp2_stream *open_sent_stream2(nghttp2_session *session, int32_t stream_id, + nghttp2_stream_state initial_state); + +nghttp2_stream *open_sent_stream3(nghttp2_session *session, int32_t stream_id, + uint8_t flags, + nghttp2_priority_spec *pri_spec_in, + nghttp2_stream_state initial_state, + void *stream_user_data); + +nghttp2_stream *open_sent_stream_with_dep(nghttp2_session *session, + int32_t stream_id, + nghttp2_stream *dep_stream); + +nghttp2_stream *open_sent_stream_with_dep_weight(nghttp2_session *session, + int32_t stream_id, + int32_t weight, + nghttp2_stream *dep_stream); + +/* Opens stream. This stream is assumed to be received by |session|, + and session->last_recv_stream_id will be adjusted accordingly. */ +nghttp2_stream *open_recv_stream(nghttp2_session *session, int32_t stream_id); + +nghttp2_stream *open_recv_stream2(nghttp2_session *session, int32_t stream_id, + nghttp2_stream_state initial_state); + +nghttp2_stream *open_recv_stream3(nghttp2_session *session, int32_t stream_id, + uint8_t flags, + nghttp2_priority_spec *pri_spec_in, + nghttp2_stream_state initial_state, + void *stream_user_data); + +nghttp2_stream *open_recv_stream_with_dep(nghttp2_session *session, + int32_t stream_id, + nghttp2_stream *dep_stream); + +nghttp2_stream *open_recv_stream_with_dep_weight(nghttp2_session *session, + int32_t stream_id, + int32_t weight, + nghttp2_stream *dep_stream); + #endif /* NGHTTP2_TEST_HELPER_H */ From 8f225ae88de456b24f35f0a5399abc016942b551 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 11 Jan 2016 00:46:44 +0900 Subject: [PATCH 2/4] Fix broken test_nghttp2_session_pop_next_ob_item --- tests/nghttp2_session_test.c | 24 ++++-------------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 3034aed6..dcc8220f 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -5059,14 +5059,13 @@ void test_nghttp2_session_pop_next_ob_item(void) { nghttp2_session_callbacks callbacks; nghttp2_outbound_item *item; nghttp2_priority_spec pri_spec; - nghttp2_stream *stream; nghttp2_mem *mem; mem = nghttp2_mem_default(); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); callbacks.send_callback = null_send_callback; - nghttp2_session_server_new(&session, &callbacks, NULL); + nghttp2_session_client_new(&session, &callbacks, NULL); session->remote_settings.max_concurrent_streams = 1; CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session)); @@ -5091,27 +5090,13 @@ void test_nghttp2_session_pop_next_ob_item(void) { /* Incoming stream does not affect the number of outgoing max concurrent streams. */ - nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_recv_stream(session, 4); /* In-flight outgoing stream */ - nghttp2_session_open_stream(session, 4, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_OPENING, NULL); + open_sent_stream(session, 1); nghttp2_priority_spec_init(&pri_spec, 0, NGHTTP2_MAX_WEIGHT, 0); nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL); - nghttp2_submit_response(session, 1, NULL, 0, NULL); - - item = nghttp2_session_pop_next_ob_item(session); - CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type); - CU_ASSERT(1 == item->frame.hd.stream_id); - - stream = nghttp2_session_get_stream(session, 1); - - nghttp2_stream_detach_item(stream); - - nghttp2_outbound_item_free(item, mem); - mem->free(item, NULL); CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session)); @@ -5127,8 +5112,7 @@ void test_nghttp2_session_pop_next_ob_item(void) { /* Check that push reply HEADERS are queued into ob_ss_pq */ nghttp2_session_server_new(&session, &callbacks, NULL); session->remote_settings.max_concurrent_streams = 0; - nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE, - &pri_spec_default, NGHTTP2_STREAM_RESERVED, NULL); + open_sent_stream2(session, 2, NGHTTP2_STREAM_RESERVED); CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, 2, NULL, NULL, 0, NULL)); CU_ASSERT(NULL == nghttp2_session_pop_next_ob_item(session)); From bb6f842b37b57c3d8e191db948e9165c59af7daf Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 11 Jan 2016 16:18:39 +0900 Subject: [PATCH 3/4] Check request/response submission error based side of session Disallow request from server, and response from client respectively. When the violation is detected, return NGHTTP2_ERR_PROTO from nghttp2_submit_request, nghttp2_submit_response, nghttp2_submit_headers. We also did some refactoring, and now self-dependency detection is placed where it is only required. --- lib/includes/nghttp2/nghttp2.h | 6 +++ lib/nghttp2_submit.c | 89 +++++++++++++++++++++++++++------- tests/nghttp2_session_test.c | 79 ++++++++++++++++++++++++++---- 3 files changed, 146 insertions(+), 28 deletions(-) diff --git a/lib/includes/nghttp2/nghttp2.h b/lib/includes/nghttp2/nghttp2.h index 3c985332..27c4710b 100644 --- a/lib/includes/nghttp2/nghttp2.h +++ b/lib/includes/nghttp2/nghttp2.h @@ -3164,6 +3164,8 @@ nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec); * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT` * Trying to depend on itself (new stream ID equals * ``pri_spec->stream_id``). + * :enum:`NGHTTP2_ERR_PROTO` + * The |session| is server session. * * .. warning:: * @@ -3236,6 +3238,8 @@ nghttp2_submit_request(nghttp2_session *session, * processed yet. Normally, this does not happen, but when * application wrongly calls `nghttp2_submit_response()` twice, * this may happen. + * :enum:`NGHTTP2_ERR_PROTO` + * The |session| is client session. * * .. warning:: * @@ -3380,6 +3384,8 @@ NGHTTP2_EXTERN int nghttp2_submit_trailer(nghttp2_session *session, * DATA or HEADERS has been already submitted and not fully * processed yet. This happens if stream denoted by |stream_id| * is in reserved state. + * :enum:`NGHTTP2_ERR_PROTO` + * The |stream_id| is -1, and |session| is server session. * * .. warning:: * diff --git a/lib/nghttp2_submit.c b/lib/nghttp2_submit.c index 67ecf4f6..70271b7b 100644 --- a/lib/nghttp2_submit.c +++ b/lib/nghttp2_submit.c @@ -32,6 +32,35 @@ #include "nghttp2_helper.h" #include "nghttp2_priority_spec.h" +/* + * Detects the dependency error, that is stream attempted to depend on + * itself. If |stream_id| is -1, we use session->next_stream_id as + * stream ID. + * + * This function returns 0 if it succeeds, or one of the following + * error codes: + * + * NGHTTP2_ERR_INVALID_ARGUMENT + * Stream attempted to depend on itself. + */ +static int detect_self_dependency(nghttp2_session *session, int32_t stream_id, + const nghttp2_priority_spec *pri_spec) { + assert(pri_spec); + + if (stream_id == -1) { + if ((int32_t)session->next_stream_id == pri_spec->stream_id) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + return 0; + } + + if (stream_id == pri_spec->stream_id) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + return 0; +} + /* This function takes ownership of |nva_copy|. Regardless of the return value, the caller must not free |nva_copy| after this function returns. */ @@ -50,21 +79,6 @@ static int32_t submit_headers_shared(nghttp2_session *session, uint8_t flags, mem = &session->mem; - if (stream_id == 0) { - rv = NGHTTP2_ERR_INVALID_ARGUMENT; - goto fail; - } - - if (stream_id == -1) { - if ((int32_t)session->next_stream_id == pri_spec->stream_id) { - rv = NGHTTP2_ERR_INVALID_ARGUMENT; - goto fail; - } - } else if (stream_id == pri_spec->stream_id) { - rv = NGHTTP2_ERR_INVALID_ARGUMENT; - goto fail; - } - item = nghttp2_mem_malloc(mem, sizeof(nghttp2_outbound_item)); if (item == NULL) { rv = NGHTTP2_ERR_NOMEM; @@ -156,6 +170,10 @@ static int32_t submit_headers_shared_nva(nghttp2_session *session, int nghttp2_submit_trailer(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen) { + if (stream_id <= 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + return (int)submit_headers_shared_nva(session, NGHTTP2_FLAG_END_STREAM, stream_id, NULL, nva, nvlen, NULL, NULL); @@ -166,9 +184,24 @@ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, const nghttp2_priority_spec *pri_spec, const nghttp2_nv *nva, size_t nvlen, void *stream_user_data) { + int rv; + + if (stream_id == -1) { + if (session->server) { + return NGHTTP2_ERR_PROTO; + } + } else if (stream_id <= 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + flags &= NGHTTP2_FLAG_END_STREAM; if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) { + rv = detect_self_dependency(session, stream_id, pri_spec); + if (rv != 0) { + return rv; + } + flags |= NGHTTP2_FLAG_PRIORITY; } else { pri_spec = NULL; @@ -281,7 +314,7 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags _U_, mem = &session->mem; - if (stream_id == 0 || nghttp2_session_is_my_stream_id(session, stream_id)) { + if (stream_id <= 0 || nghttp2_session_is_my_stream_id(session, stream_id)) { return NGHTTP2_ERR_INVALID_ARGUMENT; } @@ -396,8 +429,18 @@ int32_t nghttp2_submit_request(nghttp2_session *session, const nghttp2_data_provider *data_prd, void *stream_user_data) { uint8_t flags; + int rv; - if (pri_spec && nghttp2_priority_spec_check_default(pri_spec)) { + if (session->server) { + return NGHTTP2_ERR_PROTO; + } + + if (pri_spec && !nghttp2_priority_spec_check_default(pri_spec)) { + rv = detect_self_dependency(session, -1, pri_spec); + if (rv != 0) { + return rv; + } + } else { pri_spec = NULL; } @@ -418,7 +461,17 @@ static uint8_t set_response_flags(const nghttp2_data_provider *data_prd) { int nghttp2_submit_response(nghttp2_session *session, int32_t stream_id, const nghttp2_nv *nva, size_t nvlen, const nghttp2_data_provider *data_prd) { - uint8_t flags = set_response_flags(data_prd); + uint8_t flags; + + if (stream_id <= 0) { + return NGHTTP2_ERR_INVALID_ARGUMENT; + } + + if (!session->server) { + return NGHTTP2_ERR_PROTO; + } + + flags = set_response_flags(data_prd); return submit_headers_shared_nva(session, flags, stream_id, NULL, nva, nvlen, data_prd, NULL); } diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index dcc8220f..aeb5c8db 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -3897,6 +3897,15 @@ void test_nghttp2_submit_request_with_data(void) { CU_ASSERT(0 == ud.data_source_length); nghttp2_session_del(session); + + /* nghttp2_submit_request() with server session is error */ + nghttp2_session_server_new(&session, &callbacks, NULL); + + CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_submit_request(session, NULL, reqnv, + ARRLEN(reqnv), NULL, + NULL)); + + nghttp2_session_del(session); } void test_nghttp2_submit_request_without_data(void) { @@ -3984,6 +3993,19 @@ void test_nghttp2_submit_response_with_data(void) { CU_ASSERT(0 == ud.data_source_length); nghttp2_session_del(session); + + /* Various error cases */ + nghttp2_session_client_new(&session, &callbacks, NULL); + + /* Calling nghttp2_submit_response() with client session is error */ + CU_ASSERT(NGHTTP2_ERR_PROTO == + nghttp2_submit_response(session, 1, resnv, ARRLEN(resnv), NULL)); + + /* Stream ID <= 0 is error */ + CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == + nghttp2_submit_response(session, 0, resnv, ARRLEN(resnv), NULL)); + + nghttp2_session_del(session); } void test_nghttp2_submit_response_without_data(void) { @@ -4115,6 +4137,18 @@ void test_nghttp2_submit_trailer(void) { nghttp2_frame_headers_free(&frame.headers, mem); nghttp2_hd_inflate_free(&inflater); nghttp2_session_del(session); + + /* Specifying stream ID <= 0 is error */ + nghttp2_session_server_new(&session, &callbacks, NULL); + open_recv_stream(session, 1); + + CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == + nghttp2_submit_trailer(session, 0, trailernv, ARRLEN(trailernv))); + + CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == + nghttp2_submit_trailer(session, -1, trailernv, ARRLEN(trailernv))); + + nghttp2_session_del(session); } void test_nghttp2_submit_headers_start_stream(void) { @@ -4305,6 +4339,22 @@ void test_nghttp2_submit_headers(void) { reqnv, ARRLEN(reqnv), NULL)); nghttp2_session_del(session); + + /* Error cases with invalid stream ID */ + nghttp2_session_server_new(&session, &callbacks, NULL); + + /* Sending nghttp2_submit_headers() with stream_id == 1 and server + session is error */ + CU_ASSERT(NGHTTP2_ERR_PROTO == + nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, reqnv, + ARRLEN(reqnv), NULL)); + + /* Sending stream ID <= 0 is error */ + CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == + nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, 0, NULL, resnv, + ARRLEN(resnv), NULL)); + + nghttp2_session_del(session); } void test_nghttp2_submit_headers_continuation(void) { @@ -4642,7 +4692,12 @@ void test_nghttp2_submit_push_promise(void) { /* submit PUSH_PROMISE while associated stream is not opened */ CU_ASSERT(NGHTTP2_ERR_STREAM_CLOSED == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 3, reqnv, - ARRLEN(reqnv), &ud)); + ARRLEN(reqnv), NULL)); + + /* Stream ID <= 0 is error */ + CU_ASSERT(NGHTTP2_ERR_INVALID_ARGUMENT == + nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 0, reqnv, + ARRLEN(reqnv), NULL)); nghttp2_session_del(session); } @@ -4850,19 +4905,10 @@ void test_nghttp2_submit_invalid_nv(void) { CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL)); - /* nghttp2_submit_request */ - CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv, - ARRLEN(empty_name_nv), NULL, NULL)); - /* nghttp2_submit_response */ CU_ASSERT(0 == nghttp2_submit_response(session, 2, empty_name_nv, ARRLEN(empty_name_nv), NULL)); - /* nghttp2_submit_headers */ - CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, - empty_name_nv, ARRLEN(empty_name_nv), - NULL)); - /* nghttp2_submit_push_promise */ open_recv_stream(session, 1); @@ -4871,6 +4917,19 @@ void test_nghttp2_submit_invalid_nv(void) { ARRLEN(empty_name_nv), NULL)); nghttp2_session_del(session); + + CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); + + /* nghttp2_submit_request */ + CU_ASSERT(0 < nghttp2_submit_request(session, NULL, empty_name_nv, + ARRLEN(empty_name_nv), NULL, NULL)); + + /* nghttp2_submit_headers */ + CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, NULL, + empty_name_nv, ARRLEN(empty_name_nv), + NULL)); + + nghttp2_session_del(session); } void test_nghttp2_session_open_stream(void) { From 863addcd5a2cfe4d2e13d688c920240756be1995 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Mon, 11 Jan 2016 16:23:32 +0900 Subject: [PATCH 4/4] Update man pages --- doc/h2load.1 | 13 +++++++------ doc/h2load.1.rst | 9 +++++---- doc/nghttp.1 | 4 ++-- doc/nghttpd.1 | 9 +++++++-- doc/nghttpd.1.rst | 4 ++++ doc/nghttpx.1 | 13 +++++++------ doc/nghttpx.1.rst | 9 +++++---- 7 files changed, 37 insertions(+), 24 deletions(-) diff --git a/doc/h2load.1 b/doc/h2load.1 index 50ad4f8c..7c2d3201 100644 --- a/doc/h2load.1 +++ b/doc/h2load.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "H2LOAD" "1" "December 23, 2015" "1.6.0" "nghttp2" +.TH "H2LOAD" "1" "January 11, 2016" "1.6.1-DEV" "nghttp2" .SH NAME h2load \- HTTP/2 benchmarking tool . @@ -88,11 +88,12 @@ scheme, host or port values. .UNINDENT .INDENT 0.0 .TP -.B \-m, \-\-max\-concurrent\-streams=(auto|) -Max concurrent streams to issue per session. If "auto" -is given, the number of given URIs is used. +.B \-m, \-\-max\-concurrent\-streams= +Max concurrent streams to issue per session. When +http/1.1 is used, this specifies the number of HTTP +pipelining requests in\-flight. .sp -Default: \fBauto\fP +Default: \fB1\fP .UNINDENT .INDENT 0.0 .TP @@ -410,6 +411,6 @@ window size described in HTTP/2 and SPDY protocol specification. .SH AUTHOR Tatsuhiro Tsujikawa .SH COPYRIGHT -2012, 2015, Tatsuhiro Tsujikawa +2012, 2015, 2016, Tatsuhiro Tsujikawa .\" Generated by docutils manpage writer. . diff --git a/doc/h2load.1.rst b/doc/h2load.1.rst index 368c6ab5..85feeb63 100644 --- a/doc/h2load.1.rst +++ b/doc/h2load.1.rst @@ -63,12 +63,13 @@ OPTIONS are used solely. Definition of a base URI overrides all scheme, host or port values. -.. option:: -m, --max-concurrent-streams=(auto|) +.. option:: -m, --max-concurrent-streams= - Max concurrent streams to issue per session. If "auto" - is given, the number of given URIs is used. + Max concurrent streams to issue per session. When + http/1.1 is used, this specifies the number of HTTP + pipelining requests in-flight. - Default: ``auto`` + Default: ``1`` .. option:: -w, --window-bits= diff --git a/doc/nghttp.1 b/doc/nghttp.1 index 6d7feb45..4239f424 100644 --- a/doc/nghttp.1 +++ b/doc/nghttp.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "NGHTTP" "1" "December 23, 2015" "1.6.0" "nghttp2" +.TH "NGHTTP" "1" "January 11, 2016" "1.6.1-DEV" "nghttp2" .SH NAME nghttp \- HTTP/2 client . @@ -296,6 +296,6 @@ on stream 11 with the weight 2. .SH AUTHOR Tatsuhiro Tsujikawa .SH COPYRIGHT -2012, 2015, Tatsuhiro Tsujikawa +2012, 2015, 2016, Tatsuhiro Tsujikawa .\" Generated by docutils manpage writer. . diff --git a/doc/nghttpd.1 b/doc/nghttpd.1 index 6d841e82..5d5b0c99 100644 --- a/doc/nghttpd.1 +++ b/doc/nghttpd.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "NGHTTPD" "1" "December 23, 2015" "1.6.0" "nghttp2" +.TH "NGHTTPD" "1" "January 11, 2016" "1.6.1-DEV" "nghttp2" .SH NAME nghttpd \- HTTP/2 server . @@ -180,6 +180,11 @@ Default: \fB/etc/mime.types\fP .UNINDENT .INDENT 0.0 .TP +.B \-\-no\-content\-length +Don\(aqt send content\-length header field. +.UNINDENT +.INDENT 0.0 +.TP .B \-\-version Display version information and exit. .UNINDENT @@ -197,6 +202,6 @@ The argument is an integer and an optional unit (e.g., 10K is .SH AUTHOR Tatsuhiro Tsujikawa .SH COPYRIGHT -2012, 2015, Tatsuhiro Tsujikawa +2012, 2015, 2016, Tatsuhiro Tsujikawa .\" Generated by docutils manpage writer. . diff --git a/doc/nghttpd.1.rst b/doc/nghttpd.1.rst index 6b33b0ea..cdb80c31 100644 --- a/doc/nghttpd.1.rst +++ b/doc/nghttpd.1.rst @@ -139,6 +139,10 @@ OPTIONS Default: ``/etc/mime.types`` +.. option:: --no-content-length + + Don't send content-length header field. + .. option:: --version Display version information and exit. diff --git a/doc/nghttpx.1 b/doc/nghttpx.1 index 093a7fb9..2bee266c 100644 --- a/doc/nghttpx.1 +++ b/doc/nghttpx.1 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "NGHTTPX" "1" "December 23, 2015" "1.6.0" "nghttp2" +.TH "NGHTTPX" "1" "January 11, 2016" "1.6.1-DEV" "nghttp2" .SH NAME nghttpx \- HTTP/2 proxy . @@ -896,8 +896,8 @@ Example: \fI\%\-\-add\-response\-header\fP="foo: bar" .INDENT 0.0 .TP .B \-\-header\-field\-buffer= -Set maximum buffer size for incoming HTTP header field -list. This is the sum of header name and value in +Set maximum buffer size for incoming HTTP request header +field list. This is the sum of header name and value in bytes. .sp Default: \fB64K\fP @@ -905,8 +905,9 @@ Default: \fB64K\fP .INDENT 0.0 .TP .B \-\-max\-header\-fields= -Set maximum number of incoming HTTP header fields, which -appear in one request or response header field list. +Set maximum number of incoming HTTP request header +fields, which appear in one request or response header +field list. .sp Default: \fB100\fP .UNINDENT @@ -1458,6 +1459,6 @@ App.new .SH AUTHOR Tatsuhiro Tsujikawa .SH COPYRIGHT -2012, 2015, Tatsuhiro Tsujikawa +2012, 2015, 2016, Tatsuhiro Tsujikawa .\" Generated by docutils manpage writer. . diff --git a/doc/nghttpx.1.rst b/doc/nghttpx.1.rst index e87377cd..39d954ae 100644 --- a/doc/nghttpx.1.rst +++ b/doc/nghttpx.1.rst @@ -797,16 +797,17 @@ HTTP .. option:: --header-field-buffer= - Set maximum buffer size for incoming HTTP header field - list. This is the sum of header name and value in + Set maximum buffer size for incoming HTTP request header + field list. This is the sum of header name and value in bytes. Default: ``64K`` .. option:: --max-header-fields= - Set maximum number of incoming HTTP header fields, which - appear in one request or response header field list. + Set maximum number of incoming HTTP request header + fields, which appear in one request or response header + field list. Default: ``100``