Closes all server-pushed streams when original stream is closed by RST_STREAM with CANCEL from client.
Fixed spdylay_session_is_my_stream_id()
This commit is contained in:
parent
bb6a90dc4d
commit
4030c5ccf5
|
@ -32,11 +32,7 @@
|
|||
|
||||
#include "spdylay_helper.h"
|
||||
|
||||
/*
|
||||
* Returns non-zero value if |stream_id| is initiated by local host.
|
||||
* Otherwrise returns 0.
|
||||
*/
|
||||
static int spdylay_session_is_my_stream_id(spdylay_session *session,
|
||||
int spdylay_session_is_my_stream_id(spdylay_session *session,
|
||||
int32_t stream_id)
|
||||
{
|
||||
int r;
|
||||
|
@ -44,7 +40,7 @@ static int spdylay_session_is_my_stream_id(spdylay_session *session,
|
|||
return 0;
|
||||
}
|
||||
r = stream_id % 2;
|
||||
return (session->server && r == 0) || r == 1;
|
||||
return (session->server && r == 0) || (!session->server && r == 1);
|
||||
}
|
||||
|
||||
spdylay_stream* spdylay_session_get_stream(spdylay_session *session,
|
||||
|
@ -359,6 +355,21 @@ int spdylay_session_close_stream_if_shut_rdwr(spdylay_session *session,
|
|||
}
|
||||
}
|
||||
|
||||
void spdylay_session_close_pushed_streams(spdylay_session *session,
|
||||
int32_t stream_id,
|
||||
spdylay_status_code status_code)
|
||||
{
|
||||
spdylay_stream *stream;
|
||||
stream = spdylay_session_get_stream(session, stream_id);
|
||||
if(stream) {
|
||||
int i;
|
||||
for(i = 0; i < stream->pushed_streams_length; ++i) {
|
||||
spdylay_session_close_stream(session, stream->pushed_streams[i],
|
||||
status_code);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns non-zero value if local peer can send SYN_REPLY with stream
|
||||
* ID |stream_id| at the moment, or 0.
|
||||
|
@ -398,6 +409,7 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
|
|||
uint8_t **framebuf_ptr)
|
||||
{
|
||||
/* TODO Get or validate stream ID here */
|
||||
/* TODO Validate assoc_stream_id here */
|
||||
uint8_t *framebuf;
|
||||
ssize_t framebuflen;
|
||||
switch(item->frame_type) {
|
||||
|
@ -582,6 +594,12 @@ static int spdylay_session_after_frame_sent(spdylay_session *session)
|
|||
break;
|
||||
}
|
||||
case SPDYLAY_RST_STREAM:
|
||||
if(!session->server &&
|
||||
spdylay_session_is_my_stream_id(session, frame->rst_stream.stream_id) &&
|
||||
frame->rst_stream.status_code == SPDYLAY_CANCEL) {
|
||||
spdylay_session_close_pushed_streams(session, frame->rst_stream.stream_id,
|
||||
frame->rst_stream.status_code);
|
||||
}
|
||||
spdylay_session_close_stream(session, frame->rst_stream.stream_id,
|
||||
frame->rst_stream.status_code);
|
||||
break;
|
||||
|
@ -931,6 +949,12 @@ int spdylay_session_on_syn_reply_received(spdylay_session *session,
|
|||
int spdylay_session_on_rst_stream_received(spdylay_session *session,
|
||||
spdylay_frame *frame)
|
||||
{
|
||||
if(session->server &&
|
||||
!spdylay_session_is_my_stream_id(session, frame->rst_stream.stream_id) &&
|
||||
frame->rst_stream.status_code == SPDYLAY_CANCEL) {
|
||||
spdylay_session_close_pushed_streams(session, frame->rst_stream.stream_id,
|
||||
frame->rst_stream.status_code);
|
||||
}
|
||||
spdylay_session_close_stream(session, frame->rst_stream.stream_id,
|
||||
frame->rst_stream.status_code);
|
||||
return 0;
|
||||
|
|
|
@ -125,6 +125,13 @@ struct spdylay_session {
|
|||
|
||||
/* TODO stream timeout etc */
|
||||
|
||||
/*
|
||||
* Returns non-zero value if |stream_id| is initiated by local host.
|
||||
* Otherwrise returns 0.
|
||||
*/
|
||||
int spdylay_session_is_my_stream_id(spdylay_session *session,
|
||||
int32_t stream_id);
|
||||
|
||||
/*
|
||||
* Adds frame |frame| of type |frame_type| to tx queue in |session|.
|
||||
* |aux_data| is a pointer to arbitrary data. Its interpretation is
|
||||
|
@ -169,6 +176,14 @@ spdylay_stream* spdylay_session_open_stream(spdylay_session *session,
|
|||
int spdylay_session_close_stream(spdylay_session *session, int32_t stream_id,
|
||||
spdylay_status_code status_code);
|
||||
|
||||
/*
|
||||
* Closes all pushed streams which associate them to stream
|
||||
* |stream_id| with the status code |status_code|.
|
||||
*/
|
||||
void spdylay_session_close_pushed_streams(spdylay_session *session,
|
||||
int32_t stream_id,
|
||||
spdylay_status_code status_code);
|
||||
|
||||
/*
|
||||
* If further receptions and transmissions over this stream are
|
||||
* disallowed, close this stream. This function returns 0 if it
|
||||
|
|
|
@ -95,6 +95,12 @@ int main()
|
|||
test_spdylay_session_on_goaway_received) ||
|
||||
!CU_add_test(pSuite, "session_on_data_received",
|
||||
test_spdylay_session_on_data_received) ||
|
||||
!CU_add_test(pSuite, "session_on_rst_stream_received",
|
||||
test_spdylay_session_on_rst_received) ||
|
||||
!CU_add_test(pSuite, "session_is_my_stream_id",
|
||||
test_spdylay_session_is_my_stream_id) ||
|
||||
!CU_add_test(pSuite, "session_send_rst_stream",
|
||||
test_spdylay_session_send_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) ||
|
||||
|
|
|
@ -707,3 +707,88 @@ void test_spdylay_session_on_data_received()
|
|||
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
void test_spdylay_session_is_my_stream_id()
|
||||
{
|
||||
spdylay_session *session;
|
||||
spdylay_session_callbacks callbacks;
|
||||
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
|
||||
spdylay_session_server_new(&session, &callbacks, NULL);
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_is_my_stream_id(session, 0));
|
||||
CU_ASSERT(0 == spdylay_session_is_my_stream_id(session, 1));
|
||||
CU_ASSERT(1 == spdylay_session_is_my_stream_id(session, 2));
|
||||
|
||||
spdylay_session_del(session);
|
||||
|
||||
spdylay_session_client_new(&session, &callbacks, NULL);
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_is_my_stream_id(session, 0));
|
||||
CU_ASSERT(1 == spdylay_session_is_my_stream_id(session, 1));
|
||||
CU_ASSERT(0 == spdylay_session_is_my_stream_id(session, 2));
|
||||
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
void test_spdylay_session_on_rst_received()
|
||||
{
|
||||
spdylay_session *session;
|
||||
spdylay_session_callbacks callbacks;
|
||||
my_user_data user_data;
|
||||
spdylay_stream *stream;
|
||||
spdylay_frame frame;
|
||||
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
|
||||
spdylay_session_server_new(&session, &callbacks, &user_data);
|
||||
stream = spdylay_session_open_stream(session, 1, SPDYLAY_FLAG_NONE,
|
||||
3, SPDYLAY_STREAM_OPENING);
|
||||
/* server push */
|
||||
spdylay_session_open_stream(session, 2, SPDYLAY_FLAG_NONE,
|
||||
3, SPDYLAY_STREAM_OPENING);
|
||||
spdylay_stream_add_pushed_stream(stream, 2);
|
||||
spdylay_session_open_stream(session, 4, SPDYLAY_FLAG_NONE,
|
||||
3, SPDYLAY_STREAM_OPENING);
|
||||
spdylay_stream_add_pushed_stream(stream, 4);
|
||||
|
||||
spdylay_frame_rst_stream_init(&frame.rst_stream, 1, SPDYLAY_CANCEL);
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_on_rst_stream_received(session, &frame));
|
||||
|
||||
CU_ASSERT(NULL == spdylay_session_get_stream(session, 1));
|
||||
CU_ASSERT(NULL == spdylay_session_get_stream(session, 2));
|
||||
CU_ASSERT(NULL == spdylay_session_get_stream(session, 4));
|
||||
|
||||
spdylay_frame_rst_stream_free(&frame.rst_stream);
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
void test_spdylay_session_send_rst_stream()
|
||||
{
|
||||
spdylay_session *session;
|
||||
spdylay_session_callbacks callbacks;
|
||||
my_user_data user_data;
|
||||
spdylay_stream *stream;
|
||||
spdylay_frame *frame;
|
||||
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
spdylay_session_client_new(&session, &callbacks, &user_data);
|
||||
stream = spdylay_session_open_stream(session, 1, SPDYLAY_FLAG_NONE,
|
||||
3, SPDYLAY_STREAM_OPENING);
|
||||
/* server push */
|
||||
spdylay_session_open_stream(session, 2, SPDYLAY_FLAG_NONE,
|
||||
3, SPDYLAY_STREAM_OPENING);
|
||||
spdylay_stream_add_pushed_stream(stream, 2);
|
||||
spdylay_session_open_stream(session, 4, SPDYLAY_FLAG_NONE,
|
||||
3, SPDYLAY_STREAM_OPENING);
|
||||
spdylay_stream_add_pushed_stream(stream, 4);
|
||||
|
||||
frame = malloc(sizeof(spdylay_frame));
|
||||
spdylay_frame_rst_stream_init(&frame->rst_stream, 1, SPDYLAY_CANCEL);
|
||||
spdylay_session_add_frame(session, SPDYLAY_RST_STREAM, frame, NULL);
|
||||
CU_ASSERT(0 == spdylay_session_send(session));
|
||||
|
||||
CU_ASSERT(NULL == spdylay_session_get_stream(session, 1));
|
||||
CU_ASSERT(NULL == spdylay_session_get_stream(session, 2));
|
||||
CU_ASSERT(NULL == spdylay_session_get_stream(session, 4));
|
||||
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
|
|
@ -40,5 +40,8 @@ void test_spdylay_session_on_headers_received();
|
|||
void test_spdylay_session_on_ping_received();
|
||||
void test_spdylay_session_on_goaway_received();
|
||||
void test_spdylay_session_on_data_received();
|
||||
void test_spdylay_session_on_rst_received();
|
||||
void test_spdylay_session_is_my_stream_id();
|
||||
void test_spdylay_session_send_rst_stream();
|
||||
|
||||
#endif // SPDYLAY_SESSION_TEST_H
|
||||
|
|
Loading…
Reference in New Issue