spdylay_submit_syn_stream: Return SPDYLAY_ERR_INVALID_ARGUMENT if even

Associated-To-Stream-ID is specified.
Check the Associated-To-Stream is active before sending SYN_STREAM.
This commit is contained in:
Tatsuhiro Tsujikawa 2012-03-11 18:52:42 +09:00
parent bee873712a
commit 8284746163
4 changed files with 73 additions and 16 deletions

View File

@ -663,7 +663,8 @@ void* spdylay_session_get_stream_user_data(spdylay_session *session,
* negative error codes: * negative error codes:
* *
* SPDYLAY_ERR_INVALID_ARGUMENT * SPDYLAY_ERR_INVALID_ARGUMENT
* |pri| is invalid. * The |pri| is invalid; or the Associated-To-Stream-ID is
* invalid.
* SPDYLAY_ERR_NOMEM * SPDYLAY_ERR_NOMEM
* Out of memory. * Out of memory.
*/ */
@ -722,14 +723,15 @@ int spdylay_submit_response(spdylay_session *session,
* data which is associated to the stream this frame will open. * data which is associated to the stream this frame will open.
* *
* This function is low-level in a sense that the application code can * This function is low-level in a sense that the application code can
* specify flags and assoc-stream-ID directly. For usual HTTP request, * specify flags and the Associated-To-Stream-ID directly. For usual
* spdylay_submit_request() is useful. * HTTP request, spdylay_submit_request() is useful.
* *
* 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:
* *
* SPDYLAY_ERR_INVALID_ARGUMENT * SPDYLAY_ERR_INVALID_ARGUMENT
* |pri| is invalid. * The |pri| is invalid; or the Associated-To-Stream-ID is
* invalid.
* SPDYLAY_ERR_NOMEM * SPDYLAY_ERR_NOMEM
* Out of memory. * Out of memory.
*/ */

View File

@ -478,6 +478,45 @@ static int spdylay_predicate_stream_for_send(spdylay_stream *stream)
} }
} }
/*
* This function checks SYN_STREAM frame |frame| can be sent at this
* time.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* SPDYLAY_ERR_STREAM_CLOSED
* The Associated-To-Stream is already closed or does not exist.
* SPDYLAY_ERR_STREAM_ID_NOT_AVAILABLE
* Stream ID has reached maximum value. Therefore no stream ID is
* available.
*/
static int spdylay_session_predicate_syn_stream_send
(spdylay_session *session,
spdylay_syn_stream *frame)
{
if(session->goaway_flags) {
/* When GOAWAY is sent or received, peer must not send new
SYN_STREAM. */
return SPDYLAY_ERR_SYN_STREAM_NOT_ALLOWED;
}
/* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) {
return SPDYLAY_ERR_STREAM_ID_NOT_AVAILABLE;
}
if(frame->assoc_stream_id != 0) {
/* Check associated stream is active. */
/* We assume here that if frame->assoc_stream_id != 0,
session->server is always 1 and frame->assoc_stream_id is
odd. */
if(spdylay_session_get_stream(session, frame->assoc_stream_id) ==
NULL) {
return SPDYLAY_ERR_STREAM_CLOSED;
}
}
return 0;
}
/* /*
* This function checks SYN_REPLY with the stream ID |stream_id| can * This function checks SYN_REPLY with the stream ID |stream_id| can
* be sent at this time. * be sent at this time.
@ -673,21 +712,16 @@ static int spdylay_session_predicate_data_send(spdylay_session *session,
static ssize_t spdylay_session_prep_frame(spdylay_session *session, static ssize_t spdylay_session_prep_frame(spdylay_session *session,
spdylay_outbound_item *item) spdylay_outbound_item *item)
{ {
/* TODO Get or validate stream ID here */
/* TODO Validate assoc_stream_id here */
ssize_t framebuflen; ssize_t framebuflen;
switch(item->frame_type) { switch(item->frame_type) {
case SPDYLAY_SYN_STREAM: { case SPDYLAY_SYN_STREAM: {
int32_t stream_id; int32_t stream_id;
spdylay_syn_stream_aux_data *aux_data; spdylay_syn_stream_aux_data *aux_data;
if(session->goaway_flags) { int r;
/* When GOAWAY is sent or received, peer must not send new r = spdylay_session_predicate_syn_stream_send(session,
SYN_STREAM. */ &item->frame->syn_stream);
return SPDYLAY_ERR_SYN_STREAM_NOT_ALLOWED; if(r != 0) {
} return r;
/* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) {
return SPDYLAY_ERR_STREAM_ID_NOT_AVAILABLE;
} }
stream_id = session->next_stream_id; stream_id = session->next_stream_id;

View File

@ -47,8 +47,12 @@ static int spdylay_submit_syn_stream_shared
if(pri > spdylay_session_get_pri_lowest(session)) { if(pri > spdylay_session_get_pri_lowest(session)) {
return SPDYLAY_ERR_INVALID_ARGUMENT; return SPDYLAY_ERR_INVALID_ARGUMENT;
} }
if(assoc_stream_id != 0) {
if(session->server == 0) { if(session->server == 0) {
assoc_stream_id = 0; assoc_stream_id = 0;
} else if(spdylay_session_is_my_stream_id(session, assoc_stream_id)) {
return SPDYLAY_ERR_INVALID_ARGUMENT;
}
} }
if(data_prd != NULL && data_prd->read_callback != NULL) { if(data_prd != NULL && data_prd->read_callback != NULL) {
data_prd_copy = malloc(sizeof(spdylay_data_provider)); data_prd_copy = malloc(sizeof(spdylay_data_provider));

View File

@ -730,6 +730,11 @@ void test_spdylay_submit_syn_stream()
CU_ASSERT(1 == item->frame->syn_stream.assoc_stream_id); CU_ASSERT(1 == item->frame->syn_stream.assoc_stream_id);
CU_ASSERT(3 == item->frame->syn_stream.pri); CU_ASSERT(3 == item->frame->syn_stream.pri);
/* Invalid assoc-stream-ID */
CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT ==
spdylay_submit_syn_stream(session, SPDYLAY_CTRL_FLAG_FIN, 2, 3,
nv, NULL));
spdylay_session_del(session); spdylay_session_del(session);
} }
@ -1738,9 +1743,21 @@ void test_spdylay_session_on_ctrl_not_send()
stream = spdylay_session_open_stream(session, 1, stream = spdylay_session_open_stream(session, 1,
SPDYLAY_CTRL_FLAG_NONE, SPDYLAY_CTRL_FLAG_NONE,
3, SPDYLAY_STREAM_OPENED, &user_data); 3, SPDYLAY_STREAM_OPENED, &user_data);
/* Check SYN_STREAM */
CU_ASSERT(0 == spdylay_submit_syn_stream(session, SPDYLAY_CTRL_FLAG_FIN, 3, 3,
nv, NULL));
user_data.ctrl_not_send_cb_called = 0;
/* Associated stream closed */
CU_ASSERT(0 == spdylay_session_send(session));
CU_ASSERT(1 == user_data.ctrl_not_send_cb_called);
CU_ASSERT(SPDYLAY_SYN_STREAM == user_data.not_sent_frame_type);
CU_ASSERT(SPDYLAY_ERR_STREAM_CLOSED == user_data.not_sent_error);
/* Check SYN_REPLY */ /* Check SYN_REPLY */
CU_ASSERT(0 == CU_ASSERT(0 ==
spdylay_submit_syn_reply(session, SPDYLAY_CTRL_FLAG_FIN, 1, nv)); spdylay_submit_syn_reply(session, SPDYLAY_CTRL_FLAG_FIN, 1, nv));
user_data.ctrl_not_send_cb_called = 0;
CU_ASSERT(0 == spdylay_session_send(session)); CU_ASSERT(0 == spdylay_session_send(session));
CU_ASSERT(1 == user_data.ctrl_not_send_cb_called); CU_ASSERT(1 == user_data.ctrl_not_send_cb_called);
CU_ASSERT(SPDYLAY_SYN_REPLY == user_data.not_sent_frame_type); CU_ASSERT(SPDYLAY_SYN_REPLY == user_data.not_sent_frame_type);