diff --git a/lib/nghttp2_session.c b/lib/nghttp2_session.c index 713e71bd..034ae11d 100644 --- a/lib/nghttp2_session.c +++ b/lib/nghttp2_session.c @@ -3582,7 +3582,7 @@ int32_t nghttp2_session_get_stream_effective_recv_data_length if(stream->local_flow_control == 0) { return 0; } - return stream->recv_window_size; + return stream->recv_window_size < 0 ? 0 : stream->recv_window_size; } int32_t nghttp2_session_get_stream_effective_local_window_size @@ -3602,7 +3602,7 @@ int32_t nghttp2_session_get_effective_recv_data_length if(session->local_flow_control == 0) { return 0; } - return session->recv_window_size; + return session->recv_window_size < 0 ? 0 : session->recv_window_size; } int32_t nghttp2_session_get_effective_local_window_size diff --git a/tests/main.c b/tests/main.c index 3d4865d2..9a4fd601 100644 --- a/tests/main.c +++ b/tests/main.c @@ -193,6 +193,8 @@ int main(int argc, char* argv[]) test_nghttp2_session_on_ctrl_not_send) || !CU_add_test(pSuite, "session_get_outbound_queue_size", test_nghttp2_session_get_outbound_queue_size) || + !CU_add_test(pSuite, "session_get_effective_local_window_size", + test_nghttp2_session_get_effective_local_window_size) || !CU_add_test(pSuite, "session_set_option", test_nghttp2_session_set_option) || !CU_add_test(pSuite, "session_data_backoff_by_high_pri_frame", diff --git a/tests/nghttp2_session_test.c b/tests/nghttp2_session_test.c index 1fd5ac84..f9738bcf 100644 --- a/tests/nghttp2_session_test.c +++ b/tests/nghttp2_session_test.c @@ -3482,6 +3482,79 @@ void test_nghttp2_session_get_outbound_queue_size(void) nghttp2_session_del(session); } +void test_nghttp2_session_get_effective_local_window_size(void) +{ + nghttp2_session *session; + nghttp2_session_callbacks callbacks; + nghttp2_stream *stream; + + 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_FLAG_NONE, + NGHTTP2_PRI_DEFAULT, + NGHTTP2_STREAM_OPENED, NULL); + + CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE == + nghttp2_session_get_effective_local_window_size(session)); + CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session)); + + CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE == + nghttp2_session_get_stream_effective_local_window_size + (session, 1)); + CU_ASSERT(0 == + nghttp2_session_get_stream_effective_recv_data_length(session, 1)); + + /* Check connection flow control */ + session->recv_window_size = 100; + nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 1100); + + CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1000 == + nghttp2_session_get_effective_local_window_size(session)); + CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session)); + + nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, -50); + /* Now session->recv_window_size = -50 */ + CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 950 == + nghttp2_session_get_effective_local_window_size(session)); + CU_ASSERT(0 == nghttp2_session_get_effective_recv_data_length(session)); + + session->recv_window_size += 50; + /* Now session->recv_window_size = 0 */ + nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 0, 100); + CU_ASSERT(NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE + 1050 == + nghttp2_session_get_effective_local_window_size(session)); + CU_ASSERT(50 == nghttp2_session_get_effective_recv_data_length(session)); + + /* Check stream flow control */ + stream->recv_window_size = 100; + nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 1100); + + CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1000 == + nghttp2_session_get_stream_effective_local_window_size + (session, 1)); + CU_ASSERT(0 == nghttp2_session_get_stream_effective_recv_data_length + (session, 1)); + + nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, -50); + /* Now stream->recv_window_size = -50 */ + CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 950 == + nghttp2_session_get_stream_effective_local_window_size + (session, 1)); + CU_ASSERT(0 == nghttp2_session_get_stream_effective_recv_data_length + (session, 1)); + + stream->recv_window_size += 50; + /* Now stream->recv_window_size = 0 */ + nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 1, 100); + CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1050 == + nghttp2_session_get_stream_effective_local_window_size + (session, 1)); + CU_ASSERT(50 == + nghttp2_session_get_stream_effective_recv_data_length + (session, 1)); +} + void test_nghttp2_session_set_option(void) { nghttp2_session* session; diff --git a/tests/nghttp2_session_test.h b/tests/nghttp2_session_test.h index 1cac4884..796cd071 100644 --- a/tests/nghttp2_session_test.h +++ b/tests/nghttp2_session_test.h @@ -87,6 +87,7 @@ void test_nghttp2_session_on_request_recv_callback(void); void test_nghttp2_session_on_stream_close(void); void test_nghttp2_session_on_ctrl_not_send(void); void test_nghttp2_session_get_outbound_queue_size(void); +void test_nghttp2_session_get_effective_local_window_size(void); void test_nghttp2_session_set_option(void); void test_nghttp2_session_data_backoff_by_high_pri_frame(void); void test_nghttp2_pack_settings_payload(void);