From b95e9a8c4c2450795047feffc5ffe3dc02425252 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Sun, 20 May 2012 16:03:01 +0900 Subject: [PATCH] Made spdylay_submit_window_update() not be bounded by recv_window_size Current SPDY/3 spec does not clearly prohibit to send delta_window_size which makes resulting window size more than initial window size. For this reason, spdylay_submit_window_update() can send delta_window_size in [1, (1 << 31)-1], inclusive, without bounded by stream's recv_window_size. Of course, the application is now responsible to keep the resulting window size <= (1 << 31)-1. spdylay_submit_window_update() now returns SPDYLAY_ERR_INVALID_ARGUMENT if delta_window_size is 0 or negative. --- lib/includes/spdylay/spdylay.h | 11 ++++++----- lib/spdylay_submit.c | 15 +++++++-------- tests/spdylay_session_test.c | 16 ++++++++++++++-- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index d1c54443..0329775b 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -1894,15 +1894,16 @@ int spdylay_submit_settings(spdylay_session *session, uint8_t flags, /** * @function * - * Submits WINDOW_UPDATE frame. The library keeps track of the - * received bytes from the remote endpoint. If the |delta_window_size| - * is larger than the received bytes, then it is reduced to the - * received bytes. If the received bytes is 0, the library will not - * send this frame. + * Submits WINDOW_UPDATE frame. The effective range of the + * |delta_window_size| is [1, (1 << 31)-1], inclusive. But the + * application must be responsible to keep the resulting window size + * <= (1 << 31)-1. * * This function returns 0 if it succeeds, or one of the following * negative error codes: * + * :enum:`SPDYLAY_ERR_INVALID_ARGUMENT` + * The |delta_window_size| is 0 or negative. * :enum:`SPDYLAY_ERR_STREAM_CLOSED` * The stream is already closed or does not exist. * :enum:`SPDYLAY_ERR_NOMEM` diff --git a/lib/spdylay_submit.c b/lib/spdylay_submit.c index 730d48ca..488205ac 100644 --- a/lib/spdylay_submit.c +++ b/lib/spdylay_submit.c @@ -233,16 +233,15 @@ int spdylay_submit_window_update(spdylay_session *session, int32_t stream_id, int32_t delta_window_size) { spdylay_stream *stream; + if(delta_window_size <= 0) { + return SPDYLAY_ERR_INVALID_ARGUMENT; + } stream = spdylay_session_get_stream(session, stream_id); if(stream) { - delta_window_size = spdylay_min(delta_window_size, - stream->recv_window_size); - if(delta_window_size > 0) { - stream->recv_window_size -= delta_window_size; - return spdylay_session_add_window_update(session, stream_id, - delta_window_size); - } - return 0; + stream->recv_window_size -= spdylay_min(delta_window_size, + stream->recv_window_size); + return spdylay_session_add_window_update(session, stream_id, + delta_window_size); } else { return SPDYLAY_ERR_STREAM_CLOSED; } diff --git a/tests/spdylay_session_test.c b/tests/spdylay_session_test.c index 0fcbf231..5b7588bb 100644 --- a/tests/spdylay_session_test.c +++ b/tests/spdylay_session_test.c @@ -2339,15 +2339,27 @@ void test_spdylay_submit_window_update(void) CU_ASSERT(SPDYLAY_WINDOW_UPDATE == OB_CTRL_TYPE(item)); CU_ASSERT(1024 == OB_CTRL(item)->window_update.delta_window_size); CU_ASSERT(0 == spdylay_session_send(session)); + CU_ASSERT(3072 == stream->recv_window_size); CU_ASSERT(0 == spdylay_submit_window_update(session, stream_id, 4096)); item = spdylay_session_get_next_ob_item(session); CU_ASSERT(SPDYLAY_WINDOW_UPDATE == OB_CTRL_TYPE(item)); - CU_ASSERT(3072 == OB_CTRL(item)->window_update.delta_window_size); + CU_ASSERT(4096 == OB_CTRL(item)->window_update.delta_window_size); CU_ASSERT(0 == spdylay_session_send(session)); + CU_ASSERT(0 == stream->recv_window_size); CU_ASSERT(0 == spdylay_submit_window_update(session, stream_id, 4096)); - CU_ASSERT(NULL == spdylay_session_get_next_ob_item(session)); + CU_ASSERT(SPDYLAY_WINDOW_UPDATE == OB_CTRL_TYPE(item)); + CU_ASSERT(4096 == OB_CTRL(item)->window_update.delta_window_size); + CU_ASSERT(0 == spdylay_session_send(session)); + CU_ASSERT(0 == stream->recv_window_size); + + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_window_update(session, stream_id, 0)); + CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT == + spdylay_submit_window_update(session, stream_id, -1)); + CU_ASSERT(SPDYLAY_ERR_STREAM_CLOSED == + spdylay_submit_window_update(session, 4, 4096)); spdylay_session_del(session); }