Added handling when HEADERS is received.
This commit is contained in:
parent
74673013ae
commit
a59c3efedb
|
@ -131,6 +131,10 @@ static void spdylay_outbound_item_free(spdylay_outbound_item *item)
|
||||||
case SPDYLAY_RST_STREAM:
|
case SPDYLAY_RST_STREAM:
|
||||||
spdylay_frame_rst_stream_free(&item->frame->rst_stream);
|
spdylay_frame_rst_stream_free(&item->frame->rst_stream);
|
||||||
break;
|
break;
|
||||||
|
case SPDYLAY_HEADERS:
|
||||||
|
/* Currently we don't have any API to send HEADERS frame, so this
|
||||||
|
is unreachable. */
|
||||||
|
abort();
|
||||||
case SPDYLAY_DATA:
|
case SPDYLAY_DATA:
|
||||||
spdylay_frame_data_free(&item->frame->data);
|
spdylay_frame_data_free(&item->frame->data);
|
||||||
break;
|
break;
|
||||||
|
@ -191,6 +195,10 @@ int spdylay_session_add_frame(spdylay_session *session,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SPDYLAY_HEADERS:
|
||||||
|
/* Currently we don't have any API to send HEADERS frame, so this
|
||||||
|
is unreachable. */
|
||||||
|
abort();
|
||||||
case SPDYLAY_DATA: {
|
case SPDYLAY_DATA: {
|
||||||
spdylay_stream *stream = spdylay_session_get_stream
|
spdylay_stream *stream = spdylay_session_get_stream
|
||||||
(session, frame->data.stream_id);
|
(session, frame->data.stream_id);
|
||||||
|
@ -331,6 +339,10 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case SPDYLAY_HEADERS:
|
||||||
|
/* Currently we don't have any API to send HEADERS frame, so this
|
||||||
|
is unreachable. */
|
||||||
|
abort();
|
||||||
case SPDYLAY_DATA: {
|
case SPDYLAY_DATA: {
|
||||||
if(!spdylay_session_is_data_allowed(session, item->frame->data.stream_id)) {
|
if(!spdylay_session_is_data_allowed(session, item->frame->data.stream_id)) {
|
||||||
return SPDYLAY_ERR_INVALID_FRAME;
|
return SPDYLAY_ERR_INVALID_FRAME;
|
||||||
|
@ -389,6 +401,10 @@ static int spdylay_session_after_frame_sent(spdylay_session *session)
|
||||||
case SPDYLAY_RST_STREAM:
|
case SPDYLAY_RST_STREAM:
|
||||||
spdylay_session_close_stream(session, frame->rst_stream.stream_id);
|
spdylay_session_close_stream(session, frame->rst_stream.stream_id);
|
||||||
break;
|
break;
|
||||||
|
case SPDYLAY_HEADERS:
|
||||||
|
/* Currently we don't have any API to send HEADERS frame, so this
|
||||||
|
is unreachable. */
|
||||||
|
abort();
|
||||||
case SPDYLAY_DATA:
|
case SPDYLAY_DATA:
|
||||||
if(frame->data.flags & SPDYLAY_FLAG_FIN) {
|
if(frame->data.flags & SPDYLAY_FLAG_FIN) {
|
||||||
if(spdylay_session_is_my_stream_id(session, frame->data.stream_id)) {
|
if(spdylay_session_is_my_stream_id(session, frame->data.stream_id)) {
|
||||||
|
@ -672,6 +688,52 @@ int spdylay_session_on_syn_reply_received(spdylay_session *session,
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int spdylay_session_on_headers_received(spdylay_session *session,
|
||||||
|
spdylay_frame *frame)
|
||||||
|
{
|
||||||
|
int r = 0;
|
||||||
|
int valid = 0;
|
||||||
|
if(spdylay_session_is_my_stream_id(session, frame->headers.stream_id)) {
|
||||||
|
spdylay_stream *stream = spdylay_session_get_stream
|
||||||
|
(session, frame->headers.stream_id);
|
||||||
|
if(stream) {
|
||||||
|
if(stream->state == SPDYLAY_STREAM_OPENED) {
|
||||||
|
valid = 1;
|
||||||
|
spdylay_session_call_on_ctrl_frame_received(session, SPDYLAY_HEADERS,
|
||||||
|
frame);
|
||||||
|
if(frame->headers.hd.flags & SPDYLAY_FLAG_FIN) {
|
||||||
|
/* Close the stream because this is the last frame of the
|
||||||
|
stream. */
|
||||||
|
spdylay_session_close_stream(session, frame->headers.stream_id);
|
||||||
|
}
|
||||||
|
} else if(stream->state == SPDYLAY_STREAM_CLOSING) {
|
||||||
|
/* This is race condition. SPDYLAY_STREAM_CLOSING indicates
|
||||||
|
that we queued RST_STREAM but it has not been sent. It will
|
||||||
|
eventually sent, so we just ignore this frame. */
|
||||||
|
valid = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
spdylay_stream *stream = spdylay_session_get_stream
|
||||||
|
(session, frame->headers.stream_id);
|
||||||
|
if(stream) {
|
||||||
|
if((stream->flags & SPDYLAY_FLAG_FIN) == 0) {
|
||||||
|
valid = 1;
|
||||||
|
spdylay_session_call_on_ctrl_frame_received(session, SPDYLAY_HEADERS,
|
||||||
|
frame);
|
||||||
|
if(frame->headers.hd.flags & SPDYLAY_FLAG_FIN) {
|
||||||
|
stream->flags |= SPDYLAY_FLAG_FIN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!valid) {
|
||||||
|
r = spdylay_session_handle_invalid_ctrl_frame
|
||||||
|
(session, frame->headers.stream_id, SPDYLAY_HEADERS, frame);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
||||||
{
|
{
|
||||||
int r = 0;
|
int r = 0;
|
||||||
|
@ -708,6 +770,18 @@ int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
||||||
spdylay_frame_syn_reply_free(&frame.syn_reply);
|
spdylay_frame_syn_reply_free(&frame.syn_reply);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case SPDYLAY_HEADERS:
|
||||||
|
r = spdylay_frame_unpack_headers(&frame.headers,
|
||||||
|
session->iframe.headbuf,
|
||||||
|
sizeof(session->iframe.headbuf),
|
||||||
|
session->iframe.buf,
|
||||||
|
session->iframe.len,
|
||||||
|
&session->hd_inflater);
|
||||||
|
if(r == 0) {
|
||||||
|
r = spdylay_session_on_headers_received(session, &frame);
|
||||||
|
spdylay_frame_headers_free(&frame.headers);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if(r < SPDYLAY_ERR_FATAL) {
|
if(r < SPDYLAY_ERR_FATAL) {
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -124,22 +124,27 @@ int spdylay_session_close_stream(spdylay_session *session, int32_t stream_id);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when SYN_STREAM is received. Received frame is |frame|.
|
* Called when SYN_STREAM is received. Received frame is |frame|.
|
||||||
* This function does first
|
* This function does first validate received frame and then open
|
||||||
* validate received frame and then open stream and call callback
|
* stream and call callback functions. This function returns 0 if it
|
||||||
* functions.
|
* succeeds, or negative error code. This function does not return
|
||||||
|
* error if frame is not valid.
|
||||||
*/
|
*/
|
||||||
int spdylay_session_on_syn_stream_received(spdylay_session *session,
|
int spdylay_session_on_syn_stream_received(spdylay_session *session,
|
||||||
spdylay_frame *frame);
|
spdylay_frame *frame);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Called when SYN_STREAM is received. Received frame is |frame|.
|
* Called when SYN_REPLY is received. Received frame is |frame|.
|
||||||
* This function does first validate received frame and then open
|
|
||||||
* stream and call callback functions.
|
|
||||||
*/
|
*/
|
||||||
int spdylay_session_on_syn_reply_received(spdylay_session *session,
|
int spdylay_session_on_syn_reply_received(spdylay_session *session,
|
||||||
spdylay_frame *frame);
|
spdylay_frame *frame);
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Called when HEADERS is recieved. Received frame is |frame|.
|
||||||
|
*/
|
||||||
|
int spdylay_session_on_headers_received(spdylay_session *session,
|
||||||
|
spdylay_frame *frame);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Returns spdylay_stream* object whose stream ID is |stream_id|. It
|
* Returns spdylay_stream* object whose stream ID is |stream_id|. It
|
||||||
* could be NULL if such stream does not exist.
|
* could be NULL if such stream does not exist.
|
||||||
|
|
|
@ -82,6 +82,8 @@ int main()
|
||||||
!CU_add_test(pSuite, "reply_submit", test_spdylay_reply_submit) ||
|
!CU_add_test(pSuite, "reply_submit", test_spdylay_reply_submit) ||
|
||||||
!CU_add_test(pSuite, "session_reply_fail",
|
!CU_add_test(pSuite, "session_reply_fail",
|
||||||
test_spdylay_session_reply_fail) ||
|
test_spdylay_session_reply_fail) ||
|
||||||
|
!CU_add_test(pSuite, "session_on_headers_received",
|
||||||
|
test_spdylay_session_on_headers_received) ||
|
||||||
!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) ||
|
||||||
|
|
|
@ -478,3 +478,58 @@ void test_spdylay_session_on_syn_stream_received_with_unidir_fin()
|
||||||
spdylay_frame_syn_stream_free(&frame.syn_stream);
|
spdylay_frame_syn_stream_free(&frame.syn_stream);
|
||||||
spdylay_session_del(session);
|
spdylay_session_del(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_spdylay_session_on_headers_received()
|
||||||
|
{
|
||||||
|
spdylay_session *session;
|
||||||
|
spdylay_session_callbacks callbacks = {
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
on_ctrl_recv_callback,
|
||||||
|
on_invalid_ctrl_recv_callback
|
||||||
|
};
|
||||||
|
my_user_data user_data;
|
||||||
|
const char *nv[] = { NULL };
|
||||||
|
spdylay_frame frame;
|
||||||
|
user_data.valid = 0;
|
||||||
|
user_data.invalid = 0;
|
||||||
|
|
||||||
|
spdylay_session_client_new(&session, &callbacks, &user_data);
|
||||||
|
spdylay_session_open_stream(session, 1, SPDYLAY_FLAG_NONE, 0,
|
||||||
|
SPDYLAY_STREAM_OPENED);
|
||||||
|
spdylay_frame_headers_init(&frame.headers, SPDYLAY_FLAG_NONE, 1,
|
||||||
|
dup_nv(nv));
|
||||||
|
|
||||||
|
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
|
||||||
|
CU_ASSERT(1 == user_data.valid);
|
||||||
|
CU_ASSERT(SPDYLAY_STREAM_OPENED ==
|
||||||
|
spdylay_session_get_stream(session, 1)->state);
|
||||||
|
|
||||||
|
frame.headers.hd.flags |= SPDYLAY_FLAG_FIN;
|
||||||
|
|
||||||
|
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
|
||||||
|
CU_ASSERT(2 == user_data.valid);
|
||||||
|
CU_ASSERT(NULL == spdylay_session_get_stream(session, 1));
|
||||||
|
|
||||||
|
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
|
||||||
|
CU_ASSERT(1 == user_data.invalid);
|
||||||
|
|
||||||
|
/* Server initiated stream */
|
||||||
|
spdylay_session_open_stream(session, 2, SPDYLAY_FLAG_NONE, 0,
|
||||||
|
SPDYLAY_STREAM_OPENING);
|
||||||
|
|
||||||
|
frame.headers.hd.flags = SPDYLAY_FLAG_FIN;
|
||||||
|
frame.headers.stream_id = 2;
|
||||||
|
|
||||||
|
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
|
||||||
|
CU_ASSERT(3 == user_data.valid);
|
||||||
|
CU_ASSERT(SPDYLAY_STREAM_OPENING ==
|
||||||
|
spdylay_session_get_stream(session, 2)->state);
|
||||||
|
CU_ASSERT(spdylay_session_get_stream(session, 2)->flags & SPDYLAY_FLAG_FIN);
|
||||||
|
|
||||||
|
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
|
||||||
|
CU_ASSERT(2 == user_data.invalid);
|
||||||
|
|
||||||
|
spdylay_frame_headers_free(&frame.headers);
|
||||||
|
spdylay_session_del(session);
|
||||||
|
}
|
||||||
|
|
|
@ -34,5 +34,6 @@ void test_spdylay_session_send_syn_stream();
|
||||||
void test_spdylay_session_send_syn_reply();
|
void test_spdylay_session_send_syn_reply();
|
||||||
void test_spdylay_reply_submit();
|
void test_spdylay_reply_submit();
|
||||||
void test_spdylay_session_reply_fail();
|
void test_spdylay_session_reply_fail();
|
||||||
|
void test_spdylay_session_on_headers_received();
|
||||||
|
|
||||||
#endif // SPDYLAY_SESSION_TEST_H
|
#endif // SPDYLAY_SESSION_TEST_H
|
||||||
|
|
Loading…
Reference in New Issue