From 938f51964d62a6dc958e2afe02428a88c17dbc2a Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 15 Feb 2012 22:11:42 +0900 Subject: [PATCH 1/5] Respond RST_STREAM with PROTOCOL_ERROR when upper cased name is present in nv. --- lib/spdylay_session.c | 54 ++++++++++++++++++++++++++---------- tests/spdylay_session_test.c | 34 +++++++++++++++++++++++ 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/lib/spdylay_session.c b/lib/spdylay_session.c index 1983fb73..52593381 100644 --- a/lib/spdylay_session.c +++ b/lib/spdylay_session.c @@ -949,6 +949,33 @@ static int spdylay_session_is_new_peer_stream_id(spdylay_session *session, } } +/* + * Returns non-zero iff version == SPDYLAY_PROTO_VERSION + */ +static int spdylay_session_check_version(uint16_t version) +{ + return version == SPDYLAY_PROTO_VERSION; +} + +/* + * Returns non-zero iff name/value pairs |nv| are good shape. + * Currently, we only checks whether names are lower cased. The spdy/2 + * spec requires that names must be lower cased. + */ +static int spdylay_session_check_nv(char **nv) +{ + int i; + for(i = 0; nv[i]; i += 2) { + int j; + for(j = 0; nv[i][j] != '\0'; ++j) { + if('A' <= nv[i][j] && nv[i][j] <= 'Z') { + return 0; + } + } + } + return 1; +} + /* * Validates SYN_STREAM frame |frame|. This function returns 0 if it * succeeds, or non-zero spdylay_status_code. @@ -959,7 +986,7 @@ static int spdylay_session_validate_syn_stream(spdylay_session *session, if(!spdylay_session_is_new_peer_stream_id(session, frame->stream_id)) { return SPDYLAY_PROTOCOL_ERROR; } - if(frame->hd.version != SPDYLAY_PROTO_VERSION) { + if(!spdylay_session_check_version(frame->hd.version)) { return SPDYLAY_UNSUPPORTED_VERSION; } if(session->server) { @@ -988,9 +1015,13 @@ static int spdylay_session_validate_syn_stream(spdylay_session *session, follow it. */ return SPDYLAY_REFUSED_STREAM; } + if(!spdylay_session_check_nv(frame->nv)) { + return SPDYLAY_PROTOCOL_ERROR; + } return 0; } + static int spdylay_session_handle_invalid_stream (spdylay_session *session, int32_t stream_id, @@ -1070,14 +1101,6 @@ int spdylay_session_on_syn_stream_received(spdylay_session *session, return r; } -/* - * Returns non-zero iff version == SPDYLAY_PROTOCOL_ERROR. - */ -static int spdylay_session_check_version(uint16_t version) -{ - return version == SPDYLAY_PROTO_VERSION; -} - int spdylay_session_on_syn_reply_received(spdylay_session *session, spdylay_frame *frame) { @@ -1087,8 +1110,10 @@ int spdylay_session_on_syn_reply_received(spdylay_session *session, if(!spdylay_session_check_version(frame->syn_reply.hd.version)) { return 0; } - stream = spdylay_session_get_stream(session, frame->syn_reply.stream_id); - if(stream && (stream->shut_flags & SPDYLAY_SHUT_RD) == 0) { + if((stream = spdylay_session_get_stream(session, + frame->syn_reply.stream_id)) && + (stream->shut_flags & SPDYLAY_SHUT_RD) == 0 && + spdylay_session_check_nv(frame->syn_reply.nv)) { if(spdylay_session_is_my_stream_id(session, frame->syn_reply.stream_id)) { if(stream->state == SPDYLAY_STREAM_OPENING) { valid = 1; @@ -1190,9 +1215,10 @@ int spdylay_session_on_headers_received(spdylay_session *session, if(!spdylay_session_check_version(frame->headers.hd.version)) { return 0; } - stream = spdylay_session_get_stream(session, frame->headers.stream_id); - /* First we check readability from this stream. */ - if(stream && (stream->shut_flags & SPDYLAY_SHUT_RD) == 0) { + if((stream = spdylay_session_get_stream(session, + frame->headers.stream_id)) && + (stream->shut_flags & SPDYLAY_SHUT_RD) == 0 && + spdylay_session_check_nv(frame->headers.nv)) { if(spdylay_session_is_my_stream_id(session, frame->headers.stream_id)) { if(stream->state == SPDYLAY_STREAM_OPENED) { valid = 1; diff --git a/tests/spdylay_session_test.c b/tests/spdylay_session_test.c index b725ae73..331847f4 100644 --- a/tests/spdylay_session_test.c +++ b/tests/spdylay_session_test.c @@ -310,6 +310,7 @@ void test_spdylay_session_on_syn_stream_received() spdylay_session_callbacks callbacks; my_user_data user_data; const char *nv[] = { NULL }; + const char *upcase_nv[] = { "version", "http/1.1", "methoD", "get", NULL }; spdylay_frame frame; spdylay_stream *stream; int32_t stream_id = 1; @@ -341,6 +342,14 @@ void test_spdylay_session_on_syn_stream_received() CU_ASSERT(0 == spdylay_session_on_syn_stream_received(session, &frame)); CU_ASSERT(2 == user_data.invalid_ctrl_recv_cb_called); + spdylay_frame_syn_stream_free(&frame.syn_stream); + + /* Upper cased name/value pairs */ + spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_FLAG_NONE, 3, 0, 3, + dup_nv(upcase_nv)); + CU_ASSERT(0 == spdylay_session_on_syn_stream_received(session, &frame)); + CU_ASSERT(3 == user_data.invalid_ctrl_recv_cb_called); + spdylay_frame_syn_stream_free(&frame.syn_stream); spdylay_session_del(session); } @@ -409,6 +418,7 @@ void test_spdylay_session_on_syn_reply_received() }; my_user_data user_data; const char *nv[] = { NULL }; + const char *upcase_nv[] = { "version", "http/1.1", "methoD", "get", NULL }; spdylay_frame frame; spdylay_stream *stream; user_data.ctrl_recv_cb_called = 0; @@ -441,6 +451,17 @@ void test_spdylay_session_on_syn_reply_received() CU_ASSERT(2 == user_data.invalid_ctrl_recv_cb_called); spdylay_frame_syn_reply_free(&frame.syn_reply); + + /* Upper cased name/value pairs */ + spdylay_session_open_stream(session, 5, SPDYLAY_FLAG_NONE, 0, + SPDYLAY_STREAM_OPENING, NULL); + spdylay_frame_syn_reply_init(&frame.syn_reply, SPDYLAY_FLAG_NONE, 5, + dup_nv(upcase_nv)); + CU_ASSERT(0 == spdylay_session_on_syn_reply_received(session, &frame)); + CU_ASSERT(3 == user_data.invalid_ctrl_recv_cb_called); + + spdylay_frame_syn_reply_free(&frame.syn_reply); + spdylay_session_del(session); } @@ -572,6 +593,7 @@ void test_spdylay_session_on_headers_received() spdylay_session_callbacks callbacks; my_user_data user_data; const char *nv[] = { NULL }; + const char *upcase_nv[] = { "version", "http/1.1", "methoD", "get", NULL }; spdylay_frame frame; memset(&callbacks, 0, sizeof(spdylay_session_callbacks)); callbacks.on_ctrl_recv_callback = on_ctrl_recv_callback; @@ -629,6 +651,18 @@ void test_spdylay_session_on_headers_received() CU_ASSERT(2 == user_data.invalid_ctrl_recv_cb_called); spdylay_frame_headers_free(&frame.headers); + + /* Upper cased name/value pairs */ + spdylay_session_open_stream(session, 5, SPDYLAY_FLAG_NONE, 0, + SPDYLAY_STREAM_OPENED, NULL); + spdylay_frame_headers_init(&frame.headers, SPDYLAY_FLAG_NONE, 5, + dup_nv(upcase_nv)); + + CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame)); + CU_ASSERT(3 == user_data.invalid_ctrl_recv_cb_called); + + spdylay_frame_headers_free(&frame.headers); + spdylay_session_del(session); } From c1aefb3ba548f518adfca0418a2cc3b7fca77359 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 15 Feb 2012 23:02:51 +0900 Subject: [PATCH 2/5] Added flags argument to spdylay_submit_data() and spdylay_frame_data_init(). The intention is make spdylay_submit_data() more generic, allowing trailing DATA and/or HEADERS frames. --- lib/includes/spdylay/spdylay.h | 19 +++++++++++-------- lib/spdylay_frame.c | 3 ++- lib/spdylay_frame.h | 2 +- lib/spdylay_session.c | 5 +++-- lib/spdylay_submit.c | 7 ++++++- 5 files changed, 23 insertions(+), 13 deletions(-) diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index 01f2026d..756bcb4d 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -425,14 +425,6 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri, spdylay_data_provider *data_prd, void *stream_user_data); -/* - * Submits DATA frame to stream |stream_id|. - * - * This function returns 0 if it succeeds, or negative error code. - */ -int spdylay_submit_data(spdylay_session *session, int32_t stream_id, - spdylay_data_provider *data_prd); - /* * Submits SYN_REPLY frame against stream |stream_id|. |nv| must * include following name/value pairs: @@ -451,6 +443,17 @@ int spdylay_submit_response(spdylay_session *session, int32_t stream_id, const char **nv, spdylay_data_provider *data_prd); +/* + * Submits 1 or more DATA frames to the stream |stream_id|. The data + * to be sent are provided by |data_prd|. Depending on the length of + * data, 1 or more DATA frames will be sent. If |flags| contains + * SPDYLAY_FLAG_FIN, the last DATA frame has FLAG_FIN set. + * + * This function returns 0 if it succeeds, or negative error code. + */ +int spdylay_submit_data(spdylay_session *session, int32_t stream_id, + uint8_t flags, spdylay_data_provider *data_prd); + /* * Submits RST_STREAM frame to cancel/reset stream |stream_id| with * status code |status_code|. This function returns 0 if it succeeds, diff --git a/lib/spdylay_frame.c b/lib/spdylay_frame.c index ca21601a..f5972f0e 100644 --- a/lib/spdylay_frame.c +++ b/lib/spdylay_frame.c @@ -425,10 +425,11 @@ void spdylay_frame_settings_free(spdylay_settings *frame) } void spdylay_frame_data_init(spdylay_data *frame, int32_t stream_id, - spdylay_data_provider *data_prd) + uint8_t flags, spdylay_data_provider *data_prd) { memset(frame, 0, sizeof(spdylay_data)); frame->stream_id = stream_id; + frame->flags = flags; frame->data_prd = *data_prd; } diff --git a/lib/spdylay_frame.h b/lib/spdylay_frame.h index 3991ebce..a880a601 100644 --- a/lib/spdylay_frame.h +++ b/lib/spdylay_frame.h @@ -266,7 +266,7 @@ void spdylay_frame_settings_init(spdylay_settings *frame, uint8_t flags, void spdylay_frame_settings_free(spdylay_settings *frame); void spdylay_frame_data_init(spdylay_data *frame, int32_t stream_id, - spdylay_data_provider *data_prd); + uint8_t flags, spdylay_data_provider *data_prd); void spdylay_frame_data_free(spdylay_data *frame); diff --git a/lib/spdylay_session.c b/lib/spdylay_session.c index 52593381..753c9b63 100644 --- a/lib/spdylay_session.c +++ b/lib/spdylay_session.c @@ -691,7 +691,7 @@ static int spdylay_session_after_frame_sent(spdylay_session *session) int r; /* spdylay_submit_data() makes a copy of aux_data->data_prd */ r = spdylay_submit_data(session, frame->syn_stream.stream_id, - aux_data->data_prd); + SPDYLAY_FLAG_FIN, aux_data->data_prd); if(r != 0) { /* TODO If r is not FATAL, we should send RST_STREAM. */ return r; @@ -714,7 +714,8 @@ static int spdylay_session_after_frame_sent(spdylay_session *session) spdylay_data_provider *data_prd = (spdylay_data_provider*)item->aux_data; int r; - r = spdylay_submit_data(session, frame->syn_reply.stream_id, data_prd); + r = spdylay_submit_data(session, frame->syn_reply.stream_id, + SPDYLAY_FLAG_FIN, data_prd); if(r != 0) { /* TODO If r is not FATAL, we should send RST_STREAM. */ return r; diff --git a/lib/spdylay_submit.c b/lib/spdylay_submit.c index 1daaba20..d1579a28 100644 --- a/lib/spdylay_submit.c +++ b/lib/spdylay_submit.c @@ -88,15 +88,20 @@ int spdylay_submit_response(spdylay_session *session, } int spdylay_submit_data(spdylay_session *session, int32_t stream_id, + uint8_t flags, spdylay_data_provider *data_prd) { int r; spdylay_frame *frame; + uint8_t nflags = 0; frame = malloc(sizeof(spdylay_frame)); if(frame == NULL) { return SPDYLAY_ERR_NOMEM; } - spdylay_frame_data_init(&frame->data, stream_id, data_prd); + if(flags & SPDYLAY_FLAG_FIN) { + nflags |= SPDYLAY_FLAG_FIN; + } + spdylay_frame_data_init(&frame->data, stream_id, nflags, data_prd); r = spdylay_session_add_frame(session, SPDYLAY_DATA, frame, NULL); if(r != 0) { spdylay_frame_data_free(&frame->data); From e7e2c69526f631f573cbc47d87554238a4887753 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 15 Feb 2012 23:15:48 +0900 Subject: [PATCH 3/5] Renamed spdylay_submit_cancel() as spdylay_submit_rst_stream(). --- lib/includes/spdylay/spdylay.h | 6 +++--- lib/spdylay_submit.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index 756bcb4d..c3edd082 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -455,12 +455,12 @@ int spdylay_submit_data(spdylay_session *session, int32_t stream_id, uint8_t flags, spdylay_data_provider *data_prd); /* - * Submits RST_STREAM frame to cancel/reset stream |stream_id| with + * Submits RST_STREAM frame to cancel/reject stream |stream_id| with * status code |status_code|. This function returns 0 if it succeeds, * or negative error code. */ -int spdylay_submit_cancel(spdylay_session *session, int32_t stream_id, - uint32_t status_code); +int spdylay_submit_rst_stream(spdylay_session *session, int32_t stream_id, + uint32_t status_code); /* * Submits PING frame. This function returns 0 if it succeeds, or diff --git a/lib/spdylay_submit.c b/lib/spdylay_submit.c index d1579a28..c083c024 100644 --- a/lib/spdylay_submit.c +++ b/lib/spdylay_submit.c @@ -33,8 +33,8 @@ int spdylay_submit_ping(spdylay_session *session) spdylay_session_get_next_unique_id(session)); } -int spdylay_submit_cancel(spdylay_session *session, int32_t stream_id, - uint32_t status_code) +int spdylay_submit_rst_stream(spdylay_session *session, int32_t stream_id, + uint32_t status_code) { return spdylay_session_add_rst_stream(session, stream_id, status_code); } From 85ec883d11e7d06351f7de5db7eb5aacb631eb25 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Wed, 15 Feb 2012 23:54:42 +0900 Subject: [PATCH 4/5] Lower-case names in name/value pairs in spdylay_submit_{request, response} --- lib/includes/spdylay/spdylay.h | 21 +++++++++++++-------- lib/spdylay_frame.c | 12 ++++++++++++ lib/spdylay_frame.h | 5 +++++ lib/spdylay_submit.c | 2 ++ tests/main.c | 2 ++ tests/spdylay_frame_test.c | 17 +++++++++++++++++ tests/spdylay_frame_test.h | 1 + tests/spdylay_session_test.c | 10 ++++++++-- 8 files changed, 60 insertions(+), 10 deletions(-) diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index c3edd082..aa5c86fd 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -394,9 +394,10 @@ void* spdylay_session_get_stream_user_data(spdylay_session *session, int32_t stream_id); /* - * Submits SYN_STREAM frame. |pri| is priority of this request and it - * must be in the range of [0, 3]. 0 means the higest priority. |nv| - * must include following name/value pairs: + * Submits SYN_STREAM frame and optionally one or more DATA + * frames. |pri| is priority of this request and it must be in the + * range of [0, 3]. 0 means the higest priority. |nv| must include + * following name/value pairs: * * "method": HTTP method (e.g., "GET" or "POST") * "scheme": URI scheme (e.g., "https") @@ -405,7 +406,8 @@ void* spdylay_session_get_stream_user_data(spdylay_session *session, * * "host" name/value pair is also required by some hosts. * - * This function creates copies of all name/value pairs in |nv|. + * This function creates copies of all name/value pairs in |nv|. It + * also lower-cases all names in |nv|. * * If |data_prd| is not NULL, it provides data which will be sent in * subsequent DATA frames. In this case, "POST" must be specified with @@ -426,14 +428,17 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri, void *stream_user_data); /* - * Submits SYN_REPLY frame against stream |stream_id|. |nv| must - * include following name/value pairs: + * Submits SYN_REPLY frame and optionally one or more DATA frames + * against stream |stream_id|. |nv| must include following name/value + * pairs: * * "status": HTTP status code (e.g., "200" or "200 OK") * "version": HTTP response version (e.g., "HTTP/1.1") * - * This function creates copies of all name/value pairs in |nv|. If - * |data_prd| is not NULL, it provides data which will be sent in + * This function creates copies of all name/value pairs in |nv|. It + * also lower-cases all names in |nv|. + * + * If |data_prd| is not NULL, it provides data which will be sent in * subsequent DATA frames. If |data_prd| is NULL, SYN_REPLY will have * FLAG_FIN. * diff --git a/lib/spdylay_frame.c b/lib/spdylay_frame.c index f5972f0e..567e54e1 100644 --- a/lib/spdylay_frame.c +++ b/lib/spdylay_frame.c @@ -315,6 +315,18 @@ void spdylay_frame_nv_sort(char **nv) qsort(nv, n/2, 2*sizeof(char*), spdylay_string_compar); } +void spdylay_frame_nv_downcase(char **nv) +{ + int i, j; + for(i = 0; nv[i]; i += 2) { + for(j = 0; nv[i][j] != '\0'; ++j) { + if('A' <= nv[i][j] && nv[i][j] <= 'Z') { + nv[i][j] += 'a'-'A'; + } + } + } +} + void spdylay_frame_syn_stream_init(spdylay_syn_stream *frame, uint8_t flags, int32_t stream_id, int32_t assoc_stream_id, uint8_t pri, char **nv) diff --git a/lib/spdylay_frame.h b/lib/spdylay_frame.h index a880a601..fcdcbe68 100644 --- a/lib/spdylay_frame.h +++ b/lib/spdylay_frame.h @@ -293,6 +293,11 @@ char** spdylay_frame_nv_copy(const char **nv); */ void spdylay_frame_nv_sort(char **nv); +/* + * Makes names in |nv| lower cased. + */ +void spdylay_frame_nv_downcase(char **nv); + /* * Makes copy of |iv| and return the copy. The |niv| is the number of * entries in |iv|. This function returns the pointer to the copy if diff --git a/lib/spdylay_submit.c b/lib/spdylay_submit.c index c083c024..86245a09 100644 --- a/lib/spdylay_submit.c +++ b/lib/spdylay_submit.c @@ -71,6 +71,7 @@ int spdylay_submit_response(spdylay_session *session, free(data_prd_copy); return SPDYLAY_ERR_NOMEM; } + spdylay_frame_nv_downcase(nv_copy); spdylay_frame_nv_sort(nv_copy); if(data_prd == NULL) { flags |= SPDYLAY_FLAG_FIN; @@ -151,6 +152,7 @@ int spdylay_submit_request(spdylay_session *session, uint8_t pri, free(data_prd_copy); return SPDYLAY_ERR_NOMEM; } + spdylay_frame_nv_downcase(nv_copy); spdylay_frame_nv_sort(nv_copy); if(data_prd == NULL) { flags |= SPDYLAY_FLAG_FIN; diff --git a/tests/main.c b/tests/main.c index 1a1892d7..f144a84f 100644 --- a/tests/main.c +++ b/tests/main.c @@ -132,6 +132,8 @@ int main(int argc, char* argv[]) !CU_add_test(pSuite, "frame_pack_settings", test_spdylay_frame_pack_settings) || !CU_add_test(pSuite, "frame_nv_sort", test_spdylay_frame_nv_sort) || + !CU_add_test(pSuite, "frame_nv_downcase", + test_spdylay_frame_nv_downcase) || !CU_add_test(pSuite, "stream_add_pushed_stream", test_spdylay_stream_add_pushed_stream)) { CU_cleanup_registry(); diff --git a/tests/spdylay_frame_test.c b/tests/spdylay_frame_test.c index 9f32268d..73a22e95 100644 --- a/tests/spdylay_frame_test.c +++ b/tests/spdylay_frame_test.c @@ -230,3 +230,20 @@ void test_spdylay_frame_nv_sort() CU_ASSERT(strcmp("version", nv[4]) == 0); CU_ASSERT(strcmp("HTTP/1.1", nv[5]) == 0); } + +void test_spdylay_frame_nv_downcase() +{ + const char *nv_src[] = { + "VERSION", "HTTP/1.1", + "Content-Length", "1000000007", + NULL + }; + char **nv; + nv = spdylay_frame_nv_copy(nv_src); + spdylay_frame_nv_downcase(nv); + CU_ASSERT(0 == strcmp("version", nv[0])); + CU_ASSERT(0 == strcmp("HTTP/1.1", nv[1])); + CU_ASSERT(0 == strcmp("content-length", nv[2])); + CU_ASSERT(0 == strcmp("1000000007", nv[3])); + spdylay_frame_nv_del(nv); +} diff --git a/tests/spdylay_frame_test.h b/tests/spdylay_frame_test.h index 26c35daa..6484e565 100644 --- a/tests/spdylay_frame_test.h +++ b/tests/spdylay_frame_test.h @@ -33,5 +33,6 @@ void test_spdylay_frame_pack_goaway(); void test_spdylay_frame_pack_headers(); void test_spdylay_frame_pack_settings(); void test_spdylay_frame_nv_sort(); +void test_spdylay_frame_nv_downcase(); #endif /* SPDYLAY_FRAME_TEST_H */ diff --git a/tests/spdylay_session_test.c b/tests/spdylay_session_test.c index 331847f4..f7bc8fe3 100644 --- a/tests/spdylay_session_test.c +++ b/tests/spdylay_session_test.c @@ -527,10 +527,11 @@ void test_spdylay_submit_response() NULL, NULL }; - const char *nv[] = { NULL }; + const char *nv[] = { "Content-Length", "1024", NULL }; int32_t stream_id = 2; spdylay_data_provider data_prd; my_user_data ud; + spdylay_outbound_item *item; data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 64*1024; @@ -538,6 +539,8 @@ void test_spdylay_submit_response() spdylay_session_open_stream(session, stream_id, SPDYLAY_FLAG_NONE, 3, SPDYLAY_STREAM_OPENING, NULL); CU_ASSERT(0 == spdylay_submit_response(session, stream_id, nv, &data_prd)); + item = spdylay_session_get_next_ob_item(session); + CU_ASSERT(0 == strcmp("content-length", item->frame->syn_reply.nv[0])); CU_ASSERT(0 == spdylay_session_send(session)); spdylay_session_del(session); } @@ -551,14 +554,17 @@ void test_spdylay_submit_request_with_data() NULL, NULL }; - const char *nv[] = { NULL }; + const char *nv[] = { "Version", "HTTP/1.1", NULL }; spdylay_data_provider data_prd; my_user_data ud; + spdylay_outbound_item *item; data_prd.read_callback = fixed_length_data_source_read_callback; ud.data_source_length = 64*1024; CU_ASSERT(0 == spdylay_session_client_new(&session, &callbacks, &ud)); CU_ASSERT(0 == spdylay_submit_request(session, 3, nv, &data_prd, NULL)); + item = spdylay_session_get_next_ob_item(session); + CU_ASSERT(0 == strcmp("version", item->frame->syn_stream.nv[0])); CU_ASSERT(0 == spdylay_session_send(session)); CU_ASSERT(0 == ud.data_source_length); From e4ad4462610eec508b97324c48557e77ecbd7b51 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 16 Feb 2012 02:51:46 +0900 Subject: [PATCH 5/5] Fixed busy loop: remove marked handler. --- examples/SpdyServer.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/examples/SpdyServer.cc b/examples/SpdyServer.cc index 82f6ad4b..d9b82000 100644 --- a/examples/SpdyServer.cc +++ b/examples/SpdyServer.cc @@ -922,10 +922,14 @@ int SpdyServer::run() sessions.mod_poll(hd); } } + if(hd->mark_del()) { + del_list.push_back(hd); + } } for(std::vector::iterator i = del_list.begin(), eoi = del_list.end(); i != eoi; ++i) { on_close(sessions, *i); + sessions.remove_handler(*i); } del_list.clear(); }