Added status_code handling to GOAWAY
This commit is contained in:
parent
88cd97843f
commit
d5cc71c636
|
@ -121,7 +121,7 @@ void on_stream_close_callback
|
|||
if(itr != stream2req.end()) {
|
||||
++complete;
|
||||
if(complete == numreq) {
|
||||
spdylay_submit_goaway(session);
|
||||
spdylay_submit_goaway(session, SPDYLAY_GOAWAY_OK);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -116,7 +116,10 @@ typedef enum {
|
|||
/* Default maximum concurrent streams */
|
||||
#define SPDYLAY_CONCURRENT_STREAMS_MAX 100
|
||||
|
||||
/* Status code for RST_STREAM */
|
||||
typedef enum {
|
||||
/* SPDYLAY_OK is not valid status code for RST_STREAM. It is defined
|
||||
just for spdylay library use. */
|
||||
SPDYLAY_OK = 0,
|
||||
SPDYLAY_PROTOCOL_ERROR = 1,
|
||||
SPDYLAY_INVALID_STREAM = 2,
|
||||
|
@ -124,9 +127,21 @@ typedef enum {
|
|||
SPDYLAY_UNSUPPORTED_VERSION = 4,
|
||||
SPDYLAY_CANCEL = 5,
|
||||
SPDYLAY_INTERNAL_ERROR = 6,
|
||||
SPDYLAY_FLOW_CONTROL_ERROR = 7
|
||||
SPDYLAY_FLOW_CONTROL_ERROR = 7,
|
||||
/* Following status codes were introduced in SPDY/3 */
|
||||
SPDYLAY_STREAM_IN_USE = 8,
|
||||
SPDYLAY_STREAM_ALREADY_CLOSED = 9,
|
||||
SPDYLAY_INVALID_CREDENTIALS = 10,
|
||||
FRAME_TOO_LARGE = 11
|
||||
} spdylay_status_code;
|
||||
|
||||
/* Status code for GOAWAY, introduced in SPDY/3 */
|
||||
typedef enum {
|
||||
SPDYLAY_GOAWAY_OK = 0,
|
||||
SPDYLAY_GOAWAY_PROTOCOL_ERROR = 1,
|
||||
SPDYLAY_GOAWAY_INTERNAL_ERROR = 11
|
||||
} spdylay_goaway_status_code;
|
||||
|
||||
#define SPDYLAY_SPDY2_PRI_LOWEST 3
|
||||
#define SPDYLAY_SPDY3_PRI_LOWEST 7
|
||||
|
||||
|
@ -643,7 +658,8 @@ int spdylay_submit_rst_stream(spdylay_session *session, int32_t stream_id,
|
|||
int spdylay_submit_ping(spdylay_session *session);
|
||||
|
||||
/*
|
||||
* Submits GOAWAY frame.
|
||||
* Submits GOAWAY frame. The status code |status_code| is ignored if
|
||||
* the protocol version is SPDYLAY_PROTO_SPDY2.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
|
@ -651,7 +667,7 @@ int spdylay_submit_ping(spdylay_session *session);
|
|||
* SPDYLAY_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int spdylay_submit_goaway(spdylay_session *session);
|
||||
int spdylay_submit_goaway(spdylay_session *session, uint32_t status_code);
|
||||
|
||||
/*
|
||||
* A helper function for dealing with NPN in client side.
|
||||
|
|
|
@ -449,7 +449,8 @@ void spdylay_frame_ping_free(spdylay_ping *frame)
|
|||
{}
|
||||
|
||||
void spdylay_frame_goaway_init(spdylay_goaway *frame,
|
||||
uint16_t version, int32_t last_good_stream_id)
|
||||
uint16_t version, int32_t last_good_stream_id,
|
||||
uint32_t status_code)
|
||||
{
|
||||
memset(frame, 0, sizeof(spdylay_goaway));
|
||||
frame->hd.version = version;
|
||||
|
@ -458,11 +459,11 @@ void spdylay_frame_goaway_init(spdylay_goaway *frame,
|
|||
frame->hd.length = 4;
|
||||
} else if(version == SPDYLAY_PROTO_SPDY3) {
|
||||
frame->hd.length = 8;
|
||||
frame->status_code = status_code;
|
||||
} else {
|
||||
frame->hd.length = 0;
|
||||
}
|
||||
frame->last_good_stream_id = last_good_stream_id;
|
||||
frame->status_code = 0; /* TODO Add status_code arg for spdy/3 */
|
||||
}
|
||||
|
||||
void spdylay_frame_goaway_free(spdylay_goaway *frame)
|
||||
|
|
|
@ -463,8 +463,13 @@ void spdylay_frame_ping_init(spdylay_ping *frame, uint16_t version,
|
|||
|
||||
void spdylay_frame_ping_free(spdylay_ping *frame);
|
||||
|
||||
/*
|
||||
* Initializes GOAWAY frame |frame| with given values. The
|
||||
* |status_code| is ignored if |version| == SPDYLAY_PROTO_SPDY2.
|
||||
*/
|
||||
void spdylay_frame_goaway_init(spdylay_goaway *frame, uint16_t version,
|
||||
int32_t last_good_stream_id);
|
||||
int32_t last_good_stream_id,
|
||||
uint32_t status_code);
|
||||
|
||||
void spdylay_frame_goaway_free(spdylay_goaway *frame);
|
||||
|
||||
|
|
|
@ -1489,13 +1489,14 @@ int spdylay_session_on_headers_received(spdylay_session *session,
|
|||
|
||||
/*
|
||||
* This function should be called when the session wants to drop
|
||||
* connection after sending GOAWAY. For example, when it receives bad
|
||||
* zlib data.
|
||||
* connection after sending GOAWAY. These cases are called as the
|
||||
* session error. For example, when it receives bad zlib data.
|
||||
*/
|
||||
static int spdylay_session_fail_session(spdylay_session *session)
|
||||
static int spdylay_session_fail_session(spdylay_session *session,
|
||||
uint32_t status_code)
|
||||
{
|
||||
session->goaway_flags |= SPDYLAY_GOAWAY_FAIL_ON_SEND;
|
||||
return spdylay_submit_goaway(session);
|
||||
return spdylay_submit_goaway(session, status_code);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1533,7 +1534,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
|||
invalid frame, send RST_STREAM with PROTOCOL_ERROR. Same for
|
||||
other control frames. */
|
||||
} else if(spdylay_is_non_fatal(r)) {
|
||||
r = spdylay_session_fail_session(session);
|
||||
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
}
|
||||
break;
|
||||
case SPDYLAY_SYN_REPLY:
|
||||
|
@ -1551,7 +1552,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
|||
r = spdylay_session_on_syn_reply_received(session, &frame);
|
||||
spdylay_frame_syn_reply_free(&frame.syn_reply);
|
||||
} else if(spdylay_is_non_fatal(r)) {
|
||||
r = spdylay_session_fail_session(session);
|
||||
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
}
|
||||
break;
|
||||
case SPDYLAY_RST_STREAM:
|
||||
|
@ -1564,7 +1565,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
|||
r = spdylay_session_on_rst_stream_received(session, &frame);
|
||||
spdylay_frame_rst_stream_free(&frame.rst_stream);
|
||||
} else if(spdylay_is_non_fatal(r)) {
|
||||
r = spdylay_session_fail_session(session);
|
||||
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
}
|
||||
break;
|
||||
case SPDYLAY_SETTINGS:
|
||||
|
@ -1577,7 +1578,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
|||
r = spdylay_session_on_settings_received(session, &frame);
|
||||
spdylay_frame_settings_free(&frame.settings);
|
||||
} else if(spdylay_is_non_fatal(r)) {
|
||||
r = spdylay_session_fail_session(session);
|
||||
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
}
|
||||
break;
|
||||
case SPDYLAY_NOOP:
|
||||
|
@ -1592,7 +1593,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
|||
r = spdylay_session_on_ping_received(session, &frame);
|
||||
spdylay_frame_ping_free(&frame.ping);
|
||||
} else if(spdylay_is_non_fatal(r)) {
|
||||
r = spdylay_session_fail_session(session);
|
||||
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
}
|
||||
break;
|
||||
case SPDYLAY_GOAWAY:
|
||||
|
@ -1605,7 +1606,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
|||
r = spdylay_session_on_goaway_received(session, &frame);
|
||||
spdylay_frame_goaway_free(&frame.goaway);
|
||||
} else if(spdylay_is_non_fatal(r)) {
|
||||
r = spdylay_session_fail_session(session);
|
||||
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
}
|
||||
break;
|
||||
case SPDYLAY_HEADERS:
|
||||
|
@ -1623,7 +1624,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
|||
r = spdylay_session_on_headers_received(session, &frame);
|
||||
spdylay_frame_headers_free(&frame.headers);
|
||||
} else if(spdylay_is_non_fatal(r)) {
|
||||
r = spdylay_session_fail_session(session);
|
||||
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
}
|
||||
break;
|
||||
case SPDYLAY_WINDOW_UPDATE:
|
||||
|
@ -1636,7 +1637,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
|
|||
r = spdylay_session_on_window_update_received(session, &frame);
|
||||
spdylay_frame_window_update_free(&frame.window_update);
|
||||
} else if(spdylay_is_non_fatal(r)) {
|
||||
r = spdylay_session_fail_session(session);
|
||||
r = spdylay_session_fail_session(session, SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -1923,7 +1924,8 @@ int spdylay_session_add_ping(spdylay_session *session, uint32_t unique_id)
|
|||
}
|
||||
|
||||
int spdylay_session_add_goaway(spdylay_session *session,
|
||||
int32_t last_good_stream_id)
|
||||
int32_t last_good_stream_id,
|
||||
uint32_t status_code)
|
||||
{
|
||||
int r;
|
||||
spdylay_frame *frame;
|
||||
|
@ -1932,7 +1934,7 @@ int spdylay_session_add_goaway(spdylay_session *session,
|
|||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
spdylay_frame_goaway_init(&frame->goaway, session->version,
|
||||
last_good_stream_id);
|
||||
last_good_stream_id, status_code);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_GOAWAY, frame, NULL);
|
||||
if(r != 0) {
|
||||
spdylay_frame_goaway_free(&frame->goaway);
|
||||
|
|
|
@ -218,9 +218,11 @@ int spdylay_session_add_rst_stream(spdylay_session *session,
|
|||
int spdylay_session_add_ping(spdylay_session *session, uint32_t unique_id);
|
||||
|
||||
/*
|
||||
* Adds GOAWAY frame with last-good-stream-ID
|
||||
* |last_good_stream_id|. This is a convenient function built on top
|
||||
* of spdylay_session_add_frame() to add GOAWAY easily.
|
||||
* Adds GOAWAY frame with last-good-stream-ID |last_good_stream_id|
|
||||
* and the status code |status_code|. The |status_code| is ignored if
|
||||
* the protocol version is SPDYLAY_PROTO_SPDY2. This is a convenient
|
||||
* function built on top of spdylay_session_add_frame() to add GOAWAY
|
||||
* easily.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
|
@ -229,7 +231,8 @@ int spdylay_session_add_ping(spdylay_session *session, uint32_t unique_id);
|
|||
* Out of memory.
|
||||
*/
|
||||
int spdylay_session_add_goaway(spdylay_session *session,
|
||||
int32_t last_good_stream_id);
|
||||
int32_t last_good_stream_id,
|
||||
uint32_t status_code);
|
||||
|
||||
/*
|
||||
* Adds WINDOW_UPDATE frame with stream ID |stream_id| and
|
||||
|
|
|
@ -151,9 +151,10 @@ int spdylay_submit_rst_stream(spdylay_session *session, int32_t stream_id,
|
|||
return spdylay_session_add_rst_stream(session, stream_id, status_code);
|
||||
}
|
||||
|
||||
int spdylay_submit_goaway(spdylay_session *session)
|
||||
int spdylay_submit_goaway(spdylay_session *session, uint32_t status_code)
|
||||
{
|
||||
return spdylay_session_add_goaway(session, session->last_recv_stream_id);
|
||||
return spdylay_session_add_goaway(session, session->last_recv_stream_id,
|
||||
status_code);
|
||||
}
|
||||
|
||||
int spdylay_submit_request(spdylay_session *session, uint8_t pri,
|
||||
|
|
|
@ -141,8 +141,10 @@ int main(int argc, char* argv[])
|
|||
!CU_add_test(pSuite, "frame_count_unpack_nv_space",
|
||||
test_spdylay_frame_count_unpack_nv_space) ||
|
||||
!CU_add_test(pSuite, "frame_pack_ping", test_spdylay_frame_pack_ping) ||
|
||||
!CU_add_test(pSuite, "frame_pack_goaway",
|
||||
test_spdylay_frame_pack_goaway) ||
|
||||
!CU_add_test(pSuite, "frame_pack_goaway_spdy2",
|
||||
test_spdylay_frame_pack_goaway_spdy2) ||
|
||||
!CU_add_test(pSuite, "frame_pack_goaway_spdy3",
|
||||
test_spdylay_frame_pack_goaway_spdy3) ||
|
||||
!CU_add_test(pSuite, "frame_pack_syn_stream",
|
||||
test_spdylay_frame_pack_syn_stream) ||
|
||||
!CU_add_test(pSuite, "frame_pack_syn_reply",
|
||||
|
|
|
@ -216,13 +216,14 @@ void test_spdylay_frame_pack_ping()
|
|||
spdylay_frame_ping_free(&frame.ping);
|
||||
}
|
||||
|
||||
void test_spdylay_frame_pack_goaway()
|
||||
void test_spdylay_frame_pack_goaway_version(uint16_t version)
|
||||
{
|
||||
spdylay_frame frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
ssize_t framelen;
|
||||
spdylay_frame_goaway_init(&frame.goaway, SPDYLAY_PROTO_SPDY2, 1000000007);
|
||||
spdylay_frame_goaway_init(&frame.goaway, version, 1000000007,
|
||||
SPDYLAY_GOAWAY_PROTOCOL_ERROR);
|
||||
framelen = spdylay_frame_pack_goaway(&buf, &buflen, &frame.goaway);
|
||||
CU_ASSERT(0 == spdylay_frame_unpack_goaway
|
||||
(&oframe.goaway,
|
||||
|
@ -230,7 +231,13 @@ void test_spdylay_frame_pack_goaway()
|
|||
&buf[SPDYLAY_FRAME_HEAD_LENGTH],
|
||||
framelen-SPDYLAY_FRAME_HEAD_LENGTH));
|
||||
CU_ASSERT(1000000007 == oframe.goaway.last_good_stream_id);
|
||||
CU_ASSERT(SPDYLAY_PROTO_SPDY2 == oframe.headers.hd.version);
|
||||
if(version == SPDYLAY_PROTO_SPDY2) {
|
||||
/* The status code is ignored in SPDY/2 */
|
||||
CU_ASSERT(0 == oframe.goaway.status_code);
|
||||
} else if(version == SPDYLAY_PROTO_SPDY3) {
|
||||
CU_ASSERT(SPDYLAY_GOAWAY_PROTOCOL_ERROR == oframe.goaway.status_code);
|
||||
}
|
||||
CU_ASSERT(version == oframe.headers.hd.version);
|
||||
CU_ASSERT(SPDYLAY_GOAWAY == oframe.headers.hd.type);
|
||||
CU_ASSERT(SPDYLAY_CTRL_FLAG_NONE == oframe.headers.hd.flags);
|
||||
CU_ASSERT(framelen-SPDYLAY_FRAME_HEAD_LENGTH == oframe.ping.hd.length);
|
||||
|
@ -239,6 +246,16 @@ void test_spdylay_frame_pack_goaway()
|
|||
spdylay_frame_goaway_free(&frame.goaway);
|
||||
}
|
||||
|
||||
void test_spdylay_frame_pack_goaway_spdy2()
|
||||
{
|
||||
test_spdylay_frame_pack_goaway_version(SPDYLAY_PROTO_SPDY2);
|
||||
}
|
||||
|
||||
void test_spdylay_frame_pack_goaway_spdy3()
|
||||
{
|
||||
test_spdylay_frame_pack_goaway_version(SPDYLAY_PROTO_SPDY3);
|
||||
}
|
||||
|
||||
void test_spdylay_frame_pack_syn_stream_with(uint16_t version)
|
||||
{
|
||||
spdylay_zlib deflater, inflater;
|
||||
|
|
|
@ -30,7 +30,8 @@ void test_spdylay_frame_pack_nv_duplicate_keys();
|
|||
void test_spdylay_frame_count_nv_space();
|
||||
void test_spdylay_frame_count_unpack_nv_space();
|
||||
void test_spdylay_frame_pack_ping();
|
||||
void test_spdylay_frame_pack_goaway();
|
||||
void test_spdylay_frame_pack_goaway_spdy2();
|
||||
void test_spdylay_frame_pack_goaway_spdy3();
|
||||
void test_spdylay_frame_pack_syn_stream();
|
||||
void test_spdylay_frame_pack_syn_reply();
|
||||
void test_spdylay_frame_pack_headers();
|
||||
|
|
|
@ -913,7 +913,8 @@ void test_spdylay_session_on_goaway_received()
|
|||
|
||||
spdylay_session_client_new(&session, SPDYLAY_PROTO_SPDY2, &callbacks,
|
||||
&user_data);
|
||||
spdylay_frame_goaway_init(&frame.goaway, SPDYLAY_PROTO_SPDY2, stream_id);
|
||||
spdylay_frame_goaway_init(&frame.goaway, SPDYLAY_PROTO_SPDY2, stream_id,
|
||||
SPDYLAY_GOAWAY_OK);
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_on_goaway_received(session, &frame));
|
||||
CU_ASSERT(1 == user_data.ctrl_recv_cb_called);
|
||||
|
|
Loading…
Reference in New Issue