Added spdylay_on_request_recv_callback function.

This function invoked when request from remote peer is
received.  In other words, frame with FIN flag set is received.  In
HTTP, this means HTTP request, including request body, is fully
received.
This commit is contained in:
Tatsuhiro Tsujikawa 2012-02-08 00:10:23 +09:00
parent e8a9268985
commit 4630dfb4fe
5 changed files with 110 additions and 13 deletions

View File

@ -304,6 +304,15 @@ typedef void (*spdylay_on_stream_close_callback)
(spdylay_session *session, int32_t stream_id, spdylay_status_code status_code,
void *user_data);
/*
* Callback function invoked when request from remote peer is
* received. In other words, frame with FIN flag set is received. In
* HTTP, this means HTTP request, including request body, is fully
* received.
*/
typedef void (*spdylay_on_request_recv_callback)
(spdylay_session *session, int32_t stream_id, void *user_data);
typedef struct {
spdylay_send_callback send_callback;
spdylay_recv_callback recv_callback;
@ -315,6 +324,7 @@ typedef struct {
spdylay_on_ctrl_send_callback on_ctrl_send_callback;
spdylay_on_data_send_callback on_data_send_callback;
spdylay_on_stream_close_callback on_stream_close_callback;
spdylay_on_request_recv_callback on_request_recv_callback;
} spdylay_session_callbacks;
/*

View File

@ -903,6 +903,15 @@ static void spdylay_debug_print_nv(char **nv)
}
}
static void spdylay_session_call_on_request_recv
(spdylay_session *session, int32_t stream_id)
{
if(session->callbacks.on_request_recv_callback) {
session->callbacks.on_request_recv_callback(session, stream_id,
session->user_data);
}
}
static void spdylay_session_call_on_ctrl_frame_received
(spdylay_session *session, spdylay_frame_type type, spdylay_frame *frame)
{
@ -1022,6 +1031,10 @@ int spdylay_session_on_syn_stream_received(spdylay_session *session,
session->last_recv_stream_id = frame->syn_stream.stream_id;
spdylay_session_call_on_ctrl_frame_received(session, SPDYLAY_SYN_STREAM,
frame);
if(flags & SPDYLAY_FLAG_FIN) {
spdylay_session_call_on_request_recv(session,
frame->syn_stream.stream_id);
}
}
} else {
r = spdylay_session_handle_invalid_stream
@ -1152,6 +1165,8 @@ int spdylay_session_on_headers_received(spdylay_session *session,
spdylay_session_call_on_ctrl_frame_received(session, SPDYLAY_HEADERS,
frame);
if(frame->headers.hd.flags & SPDYLAY_FLAG_FIN) {
spdylay_session_call_on_request_recv(session,
frame->headers.stream_id);
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_RD);
spdylay_session_close_stream_if_shut_rdwr(session, stream);
}
@ -1272,16 +1287,20 @@ int spdylay_session_on_data_received(spdylay_session *session,
uint8_t flags, int32_t length,
int32_t stream_id)
{
int valid = 0;
int r = 0;
spdylay_status_code status_code = 0;
spdylay_stream *stream;
stream = spdylay_session_get_stream(session, stream_id);
if(stream) {
if((stream->shut_flags & SPDYLAY_SHUT_RD) == 0) {
int valid = 0;
if(spdylay_session_is_my_stream_id(session, stream_id)) {
if(stream->state == SPDYLAY_STREAM_OPENED) {
valid = 1;
if(session->callbacks.on_data_recv_callback) {
session->callbacks.on_data_recv_callback
(session, flags, stream_id, length, session->user_data);
}
} else if(stream->state != SPDYLAY_STREAM_CLOSING) {
status_code = SPDYLAY_PROTOCOL_ERROR;
}
@ -1290,6 +1309,13 @@ int spdylay_session_on_data_received(spdylay_session *session,
not receive FIN unless stream is in SPDYLAY_STREAM_CLOSING
state. This is a race condition. */
valid = 1;
if(session->callbacks.on_data_recv_callback) {
session->callbacks.on_data_recv_callback
(session, flags, stream_id, length, session->user_data);
}
if(flags & SPDYLAY_FLAG_FIN) {
spdylay_session_call_on_request_recv(session, stream_id);
}
}
if(valid) {
if(flags & SPDYLAY_FLAG_FIN) {
@ -1303,12 +1329,7 @@ int spdylay_session_on_data_received(spdylay_session *session,
} else {
status_code = SPDYLAY_INVALID_STREAM;
}
if(valid) {
if(session->callbacks.on_data_recv_callback) {
session->callbacks.on_data_recv_callback
(session, flags, stream_id, length, session->user_data);
}
} else if(status_code != 0) {
if(status_code != 0) {
r = spdylay_session_add_rst_stream(session, stream_id, status_code);
}
return r;

View File

@ -107,6 +107,8 @@ int main(int argc, char* argv[])
test_spdylay_session_get_next_ob_item) ||
!CU_add_test(pSuite, "session_pop_next_ob_item",
test_spdylay_session_pop_next_ob_item) ||
!CU_add_test(pSuite, "session_on_request_recv_callback",
test_spdylay_session_on_request_recv_callback) ||
!CU_add_test(pSuite, "frame_unpack_nv", test_spdylay_frame_unpack_nv) ||
!CU_add_test(pSuite, "frame_count_nv_space",
test_spdylay_frame_count_nv_space) ||

View File

@ -51,6 +51,7 @@ typedef struct {
scripted_data_feed *df;
int valid, invalid;
size_t data_source_length;
int32_t stream_id;
} my_user_data;
static void scripted_data_feed_init(scripted_data_feed *df,
@ -140,6 +141,14 @@ static ssize_t fixed_length_data_source_read_callback
return wlen;
}
static void on_request_recv_callback(spdylay_session *session,
int32_t stream_id,
void *user_data)
{
my_user_data *ud = (my_user_data*)user_data;
ud->stream_id = stream_id;
}
static char** dup_nv(const char **src)
{
return spdylay_frame_nv_copy(src);
@ -536,15 +545,13 @@ void test_spdylay_session_reply_fail()
void test_spdylay_session_on_headers_received()
{
spdylay_session *session;
spdylay_session_callbacks callbacks = {
NULL,
NULL,
on_ctrl_recv_callback,
on_invalid_ctrl_recv_callback
};
spdylay_session_callbacks callbacks;
my_user_data user_data;
const char *nv[] = { NULL };
spdylay_frame frame;
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
callbacks.on_ctrl_recv_callback = on_ctrl_recv_callback;
callbacks.on_invalid_ctrl_recv_callback = on_invalid_ctrl_recv_callback;
user_data.valid = 0;
user_data.invalid = 0;
@ -883,3 +890,59 @@ void test_spdylay_session_pop_next_ob_item()
spdylay_session_del(session);
}
void test_spdylay_session_on_request_recv_callback()
{
spdylay_session *session;
spdylay_session_callbacks callbacks;
my_user_data user_data;
const char *nv[] = { NULL };
spdylay_frame frame;
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
callbacks.on_request_recv_callback = on_request_recv_callback;
user_data.stream_id = 0;
spdylay_session_server_new(&session, &callbacks, &user_data);
spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_FLAG_NONE, 1, 0, 3,
dup_nv(nv));
CU_ASSERT(0 == spdylay_session_on_syn_stream_received(session, &frame));
CU_ASSERT(0 == user_data.stream_id);
frame.syn_stream.stream_id = 3;
frame.syn_stream.hd.flags |= SPDYLAY_FLAG_FIN;
CU_ASSERT(0 == spdylay_session_on_syn_stream_received(session, &frame));
CU_ASSERT(3 == user_data.stream_id);
user_data.stream_id = 0;
frame.syn_stream.stream_id = 0;
CU_ASSERT(0 == spdylay_session_on_syn_stream_received(session, &frame));
CU_ASSERT(0 == user_data.stream_id);
spdylay_frame_syn_stream_free(&frame.syn_stream);
user_data.stream_id = 0;
spdylay_session_open_stream(session, 5, SPDYLAY_FLAG_NONE, 0,
SPDYLAY_STREAM_OPENING, NULL);
spdylay_frame_headers_init(&frame.headers, SPDYLAY_FLAG_NONE, 5, dup_nv(nv));
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
CU_ASSERT(0 == user_data.stream_id);
frame.headers.hd.flags |= SPDYLAY_FLAG_FIN;
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
CU_ASSERT(5 == user_data.stream_id);
user_data.stream_id = 0;
CU_ASSERT(0 == spdylay_session_on_headers_received(session, &frame));
CU_ASSERT(0 == user_data.stream_id);
spdylay_frame_headers_free(&frame.headers);
spdylay_session_del(session);
}

View File

@ -45,5 +45,6 @@ void test_spdylay_session_is_my_stream_id();
void test_spdylay_session_send_rst_stream();
void test_spdylay_session_get_next_ob_item();
void test_spdylay_session_pop_next_ob_item();
void test_spdylay_session_on_request_recv_callback();
#endif // SPDYLAY_SESSION_TEST_H