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.
This commit is contained in:
Tatsuhiro Tsujikawa 2012-05-20 16:03:01 +09:00
parent 80ab232060
commit b95e9a8c4c
3 changed files with 27 additions and 15 deletions

View File

@ -1894,15 +1894,16 @@ int spdylay_submit_settings(spdylay_session *session, uint8_t flags,
/** /**
* @function * @function
* *
* Submits WINDOW_UPDATE frame. The library keeps track of the * Submits WINDOW_UPDATE frame. The effective range of the
* received bytes from the remote endpoint. If the |delta_window_size| * |delta_window_size| is [1, (1 << 31)-1], inclusive. But the
* is larger than the received bytes, then it is reduced to the * application must be responsible to keep the resulting window size
* received bytes. If the received bytes is 0, the library will not * <= (1 << 31)-1.
* send this frame.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns 0 if it succeeds, or one of the following
* negative error codes: * negative error codes:
* *
* :enum:`SPDYLAY_ERR_INVALID_ARGUMENT`
* The |delta_window_size| is 0 or negative.
* :enum:`SPDYLAY_ERR_STREAM_CLOSED` * :enum:`SPDYLAY_ERR_STREAM_CLOSED`
* The stream is already closed or does not exist. * The stream is already closed or does not exist.
* :enum:`SPDYLAY_ERR_NOMEM` * :enum:`SPDYLAY_ERR_NOMEM`

View File

@ -233,16 +233,15 @@ int spdylay_submit_window_update(spdylay_session *session, int32_t stream_id,
int32_t delta_window_size) int32_t delta_window_size)
{ {
spdylay_stream *stream; spdylay_stream *stream;
if(delta_window_size <= 0) {
return SPDYLAY_ERR_INVALID_ARGUMENT;
}
stream = spdylay_session_get_stream(session, stream_id); stream = spdylay_session_get_stream(session, stream_id);
if(stream) { if(stream) {
delta_window_size = spdylay_min(delta_window_size, stream->recv_window_size -= spdylay_min(delta_window_size,
stream->recv_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, return spdylay_session_add_window_update(session, stream_id,
delta_window_size); delta_window_size);
}
return 0;
} else { } else {
return SPDYLAY_ERR_STREAM_CLOSED; return SPDYLAY_ERR_STREAM_CLOSED;
} }

View File

@ -2339,15 +2339,27 @@ void test_spdylay_submit_window_update(void)
CU_ASSERT(SPDYLAY_WINDOW_UPDATE == OB_CTRL_TYPE(item)); CU_ASSERT(SPDYLAY_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(1024 == OB_CTRL(item)->window_update.delta_window_size); CU_ASSERT(1024 == OB_CTRL(item)->window_update.delta_window_size);
CU_ASSERT(0 == spdylay_session_send(session)); 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)); CU_ASSERT(0 == spdylay_submit_window_update(session, stream_id, 4096));
item = spdylay_session_get_next_ob_item(session); item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(SPDYLAY_WINDOW_UPDATE == OB_CTRL_TYPE(item)); 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 == spdylay_session_send(session));
CU_ASSERT(0 == stream->recv_window_size);
CU_ASSERT(0 == spdylay_submit_window_update(session, stream_id, 4096)); 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); spdylay_session_del(session);
} }