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,19 +32,15 @@
|
||||||
|
|
||||||
#include "spdylay_helper.h"
|
#include "spdylay_helper.h"
|
||||||
|
|
||||||
/*
|
int spdylay_session_is_my_stream_id(spdylay_session *session,
|
||||||
* Returns non-zero value if |stream_id| is initiated by local host.
|
int32_t stream_id)
|
||||||
* Otherwrise returns 0.
|
|
||||||
*/
|
|
||||||
static int spdylay_session_is_my_stream_id(spdylay_session *session,
|
|
||||||
int32_t stream_id)
|
|
||||||
{
|
{
|
||||||
int r;
|
int r;
|
||||||
if(stream_id == 0) {
|
if(stream_id == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
r = stream_id % 2;
|
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,
|
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
|
* Returns non-zero value if local peer can send SYN_REPLY with stream
|
||||||
* ID |stream_id| at the moment, or 0.
|
* 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)
|
uint8_t **framebuf_ptr)
|
||||||
{
|
{
|
||||||
/* TODO Get or validate stream ID here */
|
/* TODO Get or validate stream ID here */
|
||||||
|
/* TODO Validate assoc_stream_id here */
|
||||||
uint8_t *framebuf;
|
uint8_t *framebuf;
|
||||||
ssize_t framebuflen;
|
ssize_t framebuflen;
|
||||||
switch(item->frame_type) {
|
switch(item->frame_type) {
|
||||||
|
@ -582,6 +594,12 @@ static int spdylay_session_after_frame_sent(spdylay_session *session)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPDYLAY_RST_STREAM:
|
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,
|
spdylay_session_close_stream(session, frame->rst_stream.stream_id,
|
||||||
frame->rst_stream.status_code);
|
frame->rst_stream.status_code);
|
||||||
break;
|
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,
|
int spdylay_session_on_rst_stream_received(spdylay_session *session,
|
||||||
spdylay_frame *frame)
|
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,
|
spdylay_session_close_stream(session, frame->rst_stream.stream_id,
|
||||||
frame->rst_stream.status_code);
|
frame->rst_stream.status_code);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -125,6 +125,13 @@ struct spdylay_session {
|
||||||
|
|
||||||
/* TODO stream timeout etc */
|
/* 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|.
|
* Adds frame |frame| of type |frame_type| to tx queue in |session|.
|
||||||
* |aux_data| is a pointer to arbitrary data. Its interpretation is
|
* |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,
|
int spdylay_session_close_stream(spdylay_session *session, int32_t stream_id,
|
||||||
spdylay_status_code status_code);
|
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
|
* If further receptions and transmissions over this stream are
|
||||||
* disallowed, close this stream. This function returns 0 if it
|
* disallowed, close this stream. This function returns 0 if it
|
||||||
|
|
|
@ -95,6 +95,12 @@ int main()
|
||||||
test_spdylay_session_on_goaway_received) ||
|
test_spdylay_session_on_goaway_received) ||
|
||||||
!CU_add_test(pSuite, "session_on_data_received",
|
!CU_add_test(pSuite, "session_on_data_received",
|
||||||
test_spdylay_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_unpack_nv", test_spdylay_frame_unpack_nv) ||
|
||||||
!CU_add_test(pSuite, "frame_count_nv_space",
|
!CU_add_test(pSuite, "frame_count_nv_space",
|
||||||
test_spdylay_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);
|
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_ping_received();
|
||||||
void test_spdylay_session_on_goaway_received();
|
void test_spdylay_session_on_goaway_received();
|
||||||
void test_spdylay_session_on_data_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
|
#endif // SPDYLAY_SESSION_TEST_H
|
||||||
|
|
Loading…
Reference in New Issue