From 6e627548be97644055b57c29ac756c5396d7766e Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 26 Jan 2012 01:04:01 +0900 Subject: [PATCH] Added stream status change after sending SYN_STREAM and SYN_REPLY. --- lib/spdylay_session.c | 80 ++++++++++++++++++++++++++++-------- lib/spdylay_session.h | 19 ++++++++- lib/spdylay_stream.c | 5 ++- lib/spdylay_stream.h | 4 +- tests/main.c | 4 ++ tests/spdylay_session_test.c | 60 ++++++++++++++++++++++++++- tests/spdylay_session_test.h | 2 + 7 files changed, 152 insertions(+), 22 deletions(-) diff --git a/lib/spdylay_session.c b/lib/spdylay_session.c index db1e6b54..0ff62402 100644 --- a/lib/spdylay_session.c +++ b/lib/spdylay_session.c @@ -30,15 +30,10 @@ #include #include -#include "spdylay_stream.h" #include "spdylay_helper.h" -/* - * Returns spdylay_stream* object whose stream ID is |stream_id|. It - * could be NULL if such stream does not exist. - */ -static spdylay_stream* spdylay_session_get_stream(spdylay_session *session, - int32_t stream_id) +spdylay_stream* spdylay_session_get_stream(spdylay_session *session, + int32_t stream_id) { return (spdylay_stream*)spdylay_map_find(&session->streams, stream_id); } @@ -115,6 +110,9 @@ static void spdylay_outbound_item_free(spdylay_outbound_item *item) case SPDYLAY_SYN_STREAM: spdylay_frame_syn_stream_free(&item->frame->syn_stream); break; + case SPDYLAY_SYN_REPLY: + spdylay_frame_syn_reply_free(&item->frame->syn_reply); + break; } free(item->frame); } @@ -201,14 +199,15 @@ int spdylay_session_add_rst_stream(spdylay_session *session, } int spdylay_session_open_stream(spdylay_session *session, int32_t stream_id, - uint8_t flags, uint8_t pri) + uint8_t flags, uint8_t pri, + spdylay_stream_state initial_state) { int r; spdylay_stream *stream = malloc(sizeof(spdylay_stream)); if(stream == NULL) { return SPDYLAY_ERR_NOMEM; } - spdylay_stream_init(stream, stream_id, flags, pri); + spdylay_stream_init(stream, stream_id, flags, pri, initial_state); r = spdylay_map_insert(&session->streams, stream_id, stream); if(r != 0) { free(stream); @@ -216,6 +215,19 @@ int spdylay_session_open_stream(spdylay_session *session, int32_t stream_id, return r; } +int spdylay_session_close_stream(spdylay_session *session, int32_t stream_id) +{ + spdylay_stream *stream = spdylay_session_get_stream(session, stream_id); + if(stream) { + spdylay_map_erase(&session->streams, stream_id); + spdylay_stream_free(stream); + free(stream); + return 0; + } else { + return SPDYLAY_ERR_INVALID_ARGUMENT; + } +} + ssize_t spdylay_session_prep_frame(spdylay_session *session, spdylay_outbound_item *item, uint8_t **framebuf_ptr) @@ -233,20 +245,29 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session, if(framebuflen < 0) { return framebuflen; } - printf("packed %d bytes\n", framebuflen); r = spdylay_session_open_stream(session, item->frame->syn_stream.stream_id, item->frame->syn_stream.hd.flags, - item->frame->syn_stream.pri); + item->frame->syn_stream.pri, + SPDYLAY_STREAM_INITIAL); if(r != 0) { free(framebuf); return r; } - *framebuf_ptr = framebuf; + break; + } + case SPDYLAY_SYN_REPLY: { + framebuflen = spdylay_frame_pack_syn_reply(&framebuf, + &item->frame->syn_reply, + &session->hd_deflater); + if(framebuflen < 0) { + return framebuflen; + } break; } default: framebuflen = SPDYLAY_ERR_INVALID_ARGUMENT; } + *framebuf_ptr = framebuf; return framebuflen; } @@ -259,6 +280,34 @@ static void spdylay_active_outbound_item_reset memset(aob, 0, sizeof(spdylay_active_outbound_item)); } +static int spdylay_session_after_frame_sent(spdylay_session *session) +{ + spdylay_frame *frame = session->aob.item->frame; + switch(session->aob.item->frame_type) { + case SPDYLAY_SYN_STREAM: { + spdylay_stream *stream = + spdylay_session_get_stream(session, frame->syn_stream.stream_id); + if(stream) { + stream->state = SPDYLAY_STREAM_OPENING; + } + break; + } + case SPDYLAY_SYN_REPLY: { + spdylay_stream *stream = + spdylay_session_get_stream(session, frame->syn_reply.stream_id); + if(stream) { + stream->state = SPDYLAY_STREAM_OPENED; + } + break; + } + case SPDYLAY_RST_STREAM: + spdylay_session_close_stream(session, frame->rst_stream.stream_id); + }; + /* TODO If frame is data frame, we need to sent all chunk of + data.*/ + spdylay_active_outbound_item_reset(&session->aob); +} + int spdylay_session_send(spdylay_session *session) { printf("session_send\n"); @@ -298,9 +347,7 @@ int spdylay_session_send(spdylay_session *session) session->aob.framebufoff += sentlen; if(session->aob.framebufoff == session->aob.framebuflen) { /* Frame has completely sent */ - spdylay_active_outbound_item_reset(&session->aob); - /* TODO If frame is data frame, we need to sent all chunk of - data.*/ + spdylay_session_after_frame_sent(session); } else { /* partial write */ break; @@ -441,7 +488,8 @@ int spdylay_session_on_syn_stream_received(spdylay_session *session, if(spdylay_session_validate_syn_stream(session, &frame->syn_stream) == 0) { r = spdylay_session_open_stream(session, frame->syn_stream.stream_id, frame->syn_stream.hd.flags, - frame->syn_stream.pri); + frame->syn_stream.pri, + SPDYLAY_STREAM_OPENING); if(r == 0) { session->last_recv_stream_id = frame->syn_stream.stream_id; spdylay_session_call_on_ctrl_frame_received(session, SPDYLAY_SYN_STREAM, diff --git a/lib/spdylay_session.h b/lib/spdylay_session.h index 89d54e40..164dc4db 100644 --- a/lib/spdylay_session.h +++ b/lib/spdylay_session.h @@ -34,6 +34,7 @@ #include "spdylay_map.h" #include "spdylay_frame.h" #include "spdylay_zlib.h" +#include "spdylay_stream.h" typedef struct { spdylay_frame_type frame_type; @@ -107,13 +108,20 @@ int spdylay_session_add_rst_stream(spdylay_session *session, * SPDYLAY_FLAG_UNIDIRECTIONAL is non-zero, this stream is * unidirectional. |flags| & SPDYLAY_FLAG_FIN is non-zero, the sender * of SYN_STREAM will not send any further data in this stream. + * The state of stream is set to |initial_state|. */ int spdylay_session_open_stream(spdylay_session *session, int32_t stream_id, - uint8_t flags, uint8_t pri); + uint8_t flags, uint8_t pri, + spdylay_stream_state initial_state); +/* + * Closes stream whose stream ID is |stream_id|. This function returns + * 0 if it succeeds, or negative error code. The possible error code + * is SPDYLAY_ERR_INVALID_ARGUMENT, which is used when stream + * |stream_id| does not exist. So the caller may ignore this error. + */ int spdylay_session_close_stream(spdylay_session *session, int32_t stream_id); - /* * Called when SYN_STREAM is received. Received frame is |frame|. * This function does first @@ -132,4 +140,11 @@ int spdylay_session_on_syn_reply_received(spdylay_session *session, spdylay_frame *frame); +/* + * Returns spdylay_stream* object whose stream ID is |stream_id|. It + * could be NULL if such stream does not exist. + */ +spdylay_stream* spdylay_session_get_stream(spdylay_session *session, + int32_t stream_id); + #endif /* SPDYLAY_SESSION_H */ diff --git a/lib/spdylay_stream.c b/lib/spdylay_stream.c index 7fbbedb0..033b4da3 100644 --- a/lib/spdylay_stream.c +++ b/lib/spdylay_stream.c @@ -25,12 +25,13 @@ #include "spdylay_stream.h" void spdylay_stream_init(spdylay_stream *stream, int32_t stream_id, - uint8_t flags, uint8_t pri) + uint8_t flags, uint8_t pri, + spdylay_stream_state initial_state) { stream->stream_id = stream_id; - stream->state = SPDYLAY_STREAM_OPENING; stream->flags = flags; stream->pri = pri; + stream->state = initial_state; } void spdylay_stream_free(spdylay_stream *stream) diff --git a/lib/spdylay_stream.h b/lib/spdylay_stream.h index 253ba1c4..2e4156ae 100644 --- a/lib/spdylay_stream.h +++ b/lib/spdylay_stream.h @@ -41,6 +41,7 @@ * SPDYLAY_STREAM_OPENED : upon sending SYN_REPLY */ typedef enum { + SPDYLAY_STREAM_INITIAL, /* For stream initiator: SYN_STREAM has been sent, but SYN_REPLY is not received yet. For receiver: SYN_STREAM has been received, but it does not send SYN_REPLY yet. */ @@ -63,7 +64,8 @@ typedef struct { } spdylay_stream; void spdylay_stream_init(spdylay_stream *stream, int32_t stream_id, - uint8_t flags, uint8_t pri); + uint8_t flags, uint8_t pri, + spdylay_stream_state initial_state); void spdylay_stream_free(spdylay_stream *stream); diff --git a/tests/main.c b/tests/main.c index 0ba6139d..17bc8ef6 100644 --- a/tests/main.c +++ b/tests/main.c @@ -75,6 +75,10 @@ int main() test_spdylay_session_on_syn_stream_received) || !CU_add_test(pSuite, "session_on_syn_reply_received", test_spdylay_session_on_syn_reply_received) || + !CU_add_test(pSuite, "session_send_syn_stream", + test_spdylay_session_send_syn_stream) || + !CU_add_test(pSuite, "session_send_syn_reply", + test_spdylay_session_send_syn_reply) || !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 bb816f25..719c3c21 100644 --- a/tests/spdylay_session_test.c +++ b/tests/spdylay_session_test.c @@ -62,6 +62,13 @@ static void scripted_data_feed_init(scripted_data_feed *df, df->feedseq[0] = data_length; } +static ssize_t null_send_callback(spdylay_session *session, + const uint8_t* data, size_t len, int flags, + void *user_data) +{ + return len; +} + static ssize_t scripted_recv_callback(spdylay_session *session, uint8_t* data, size_t len, int flags, void *user_data) @@ -293,7 +300,8 @@ void test_spdylay_session_on_syn_reply_received() user_data.invalid = 0; spdylay_session_client_new(&session, &callbacks, &user_data); - spdylay_session_open_stream(session, 1, SPDYLAY_FLAG_NONE, 0); + spdylay_session_open_stream(session, 1, SPDYLAY_FLAG_NONE, 0, + SPDYLAY_STREAM_OPENING); spdylay_frame_syn_reply_init(&frame.syn_reply, SPDYLAY_FLAG_NONE, 1, dup_nv(nv)); @@ -310,3 +318,53 @@ void test_spdylay_session_on_syn_reply_received() spdylay_frame_syn_reply_free(&frame.syn_reply); spdylay_session_del(session); } + +void test_spdylay_session_send_syn_stream() +{ + spdylay_session *session; + spdylay_session_callbacks callbacks = { + null_send_callback, + NULL, + NULL, + NULL + }; + const char *nv[] = { NULL }; + spdylay_frame *frame = malloc(sizeof(spdylay_frame)); + spdylay_stream *stream; + + spdylay_session_client_new(&session, &callbacks, NULL); + spdylay_frame_syn_stream_init(&frame->syn_stream, SPDYLAY_FLAG_NONE, + 0, 0, 3, dup_nv(nv)); + spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame); + CU_ASSERT(0 == spdylay_session_send(session)); + stream = spdylay_session_get_stream(session, 1); + CU_ASSERT(SPDYLAY_STREAM_OPENING == stream->state); + + spdylay_session_del(session); +} + +void test_spdylay_session_send_syn_reply() +{ + spdylay_session *session; + spdylay_session_callbacks callbacks = { + null_send_callback, + NULL, + NULL, + NULL + }; + const char *nv[] = { NULL }; + spdylay_frame *frame = malloc(sizeof(spdylay_frame)); + spdylay_stream *stream; + + CU_ASSERT(0 == spdylay_session_client_new(&session, &callbacks, NULL)); + spdylay_session_open_stream(session, 2, SPDYLAY_FLAG_NONE, 3, + SPDYLAY_STREAM_OPENING); + spdylay_frame_syn_reply_init(&frame->syn_reply, SPDYLAY_FLAG_NONE, + 2, dup_nv(nv)); + spdylay_session_add_frame(session, SPDYLAY_SYN_REPLY, frame); + CU_ASSERT(0 == spdylay_session_send(session)); + stream = spdylay_session_get_stream(session, 2); + CU_ASSERT(SPDYLAY_STREAM_OPENED == stream->state); + + spdylay_session_del(session); +} diff --git a/tests/spdylay_session_test.h b/tests/spdylay_session_test.h index 2f7be521..3dcd0a1d 100644 --- a/tests/spdylay_session_test.h +++ b/tests/spdylay_session_test.h @@ -30,5 +30,7 @@ void test_spdylay_session_recv_invalid_stream_id(); void test_spdylay_session_add_frame(); void test_spdylay_session_on_syn_stream_received(); void test_spdylay_session_on_syn_reply_received(); +void test_spdylay_session_send_syn_stream(); +void test_spdylay_session_send_syn_reply(); #endif // SPDYLAY_SESSION_TEST_H