diff --git a/lib/spdylay_session.c b/lib/spdylay_session.c index 5c0f877f..d5aa73c2 100644 --- a/lib/spdylay_session.c +++ b/lib/spdylay_session.c @@ -756,7 +756,9 @@ static int spdylay_session_after_frame_sent(spdylay_session *session) }; if(type == SPDYLAY_DATA) { int r; - if(frame->data.flags & SPDYLAY_FLAG_FIN) { + /* If session is canceled by RST_STREAM, we won't send further data. */ + if((frame->data.flags & SPDYLAY_FLAG_FIN) || + spdylay_session_get_stream(session, frame->data.stream_id) == NULL) { spdylay_active_outbound_item_reset(&session->aob); } else { spdylay_outbound_item* item = spdylay_session_get_next_ob_item(session); diff --git a/tests/main.c b/tests/main.c index e0a542d7..6d46bf86 100644 --- a/tests/main.c +++ b/tests/main.c @@ -115,6 +115,8 @@ int main(int argc, char* argv[]) test_spdylay_session_max_concurrent_streams) || !CU_add_test(pSuite, "session_data_backoff_by_high_pri_frame", test_spdylay_session_data_backoff_by_high_pri_frame) || + !CU_add_test(pSuite, "session_stop_data_with_rst_stream", + test_spdylay_session_stop_data_with_rst_stream) || !CU_add_test(pSuite, "frame_unpack_nv", test_spdylay_frame_unpack_nv) || !CU_add_test(pSuite, "frame_count_nv_space", test_spdylay_frame_count_nv_space) || diff --git a/tests/spdylay_session_test.c b/tests/spdylay_session_test.c index 3bdd64fe..f1d3927b 100644 --- a/tests/spdylay_session_test.c +++ b/tests/spdylay_session_test.c @@ -1078,3 +1078,49 @@ void test_spdylay_session_data_backoff_by_high_pri_frame() spdylay_session_del(session); } + +void test_spdylay_session_stop_data_with_rst_stream() +{ + spdylay_session *session; + spdylay_session_callbacks callbacks; + const char *nv[] = { NULL }; + my_user_data ud; + spdylay_data_provider data_prd; + spdylay_frame frame; + + memset(&callbacks, 0, sizeof(spdylay_session_callbacks)); + callbacks.on_ctrl_send_callback = on_ctrl_send_callback; + callbacks.send_callback = block_count_send_callback; + data_prd.read_callback = fixed_length_data_source_read_callback; + + ud.ctrl_send_cb_called = 0; + ud.data_source_length = 16*1024; + + spdylay_session_server_new(&session, &callbacks, &ud); + spdylay_session_open_stream(session, 1, SPDYLAY_FLAG_NONE, 3, + SPDYLAY_STREAM_OPENING, NULL); + spdylay_submit_response(session, 1, nv, &data_prd); + + ud.block_count = 2; + /* Sends SYN_REPLY + DATA[0] */ + CU_ASSERT(0 == spdylay_session_send(session)); + CU_ASSERT(SPDYLAY_SYN_REPLY == ud.sent_frame_type); + /* data for DATA[1] is read from data_prd but it is not sent */ + CU_ASSERT(ud.data_source_length == 8*1024); + + spdylay_frame_rst_stream_init(&frame.rst_stream, 1, SPDYLAY_CANCEL); + CU_ASSERT(0 == spdylay_session_on_rst_stream_received(session, &frame)); + spdylay_frame_rst_stream_free(&frame.rst_stream); + + /* Big enough number to send all DATA frames potentially. */ + ud.block_count = 100; + /* Nothing will be sent in the following call. */ + CU_ASSERT(0 == spdylay_session_send(session)); + /* With RST_STREAM, stream is canceled and further DATA on that + stream are not sent. */ + CU_ASSERT(ud.data_source_length == 8*1024); + + CU_ASSERT(NULL == spdylay_session_get_stream(session, 1)); + + spdylay_session_del(session); +} diff --git a/tests/spdylay_session_test.h b/tests/spdylay_session_test.h index 083022e4..63a7f97f 100644 --- a/tests/spdylay_session_test.h +++ b/tests/spdylay_session_test.h @@ -49,5 +49,6 @@ void test_spdylay_session_on_request_recv_callback(); void test_spdylay_session_on_stream_close(); void test_spdylay_session_max_concurrent_streams(); void test_spdylay_session_data_backoff_by_high_pri_frame(); +void test_spdylay_session_stop_data_with_rst_stream(); #endif // SPDYLAY_SESSION_TEST_H