mirror of
https://github.com/moparisthebest/spdylay
synced 2024-11-15 14:05:03 -05:00
Added data_prd arugment to spdylay_submit_request() and supported POST request.
This commit is contained in:
parent
c6a0fd06c1
commit
3d4cf8aec3
@ -318,10 +318,24 @@ int spdylay_session_want_write(spdylay_session *session);
|
||||
*
|
||||
* This function creates copies of all name/value pairs in |nv|.
|
||||
*
|
||||
* If |data_prd| is not NULL, it provides data which will be sent in
|
||||
* subsequent DATA frames. In this case, "POST" must be specified with
|
||||
* "method" key in |nv|. If |data_prd| is NULL, SYN_STREAM have
|
||||
* FLAG_FIN.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or negative error code.
|
||||
*/
|
||||
int spdylay_submit_request(spdylay_session *session, uint8_t pri,
|
||||
const char **nv);
|
||||
const char **nv,
|
||||
spdylay_data_provider *data_prd);
|
||||
|
||||
/*
|
||||
* Submits DATA frame to stream |stream_id|.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or negative error code.
|
||||
*/
|
||||
int spdylay_submit_data(spdylay_session *session, int32_t stream_id,
|
||||
spdylay_data_provider *data_prd);
|
||||
|
||||
/*
|
||||
* Submits SYN_REPLY frame against stream |stream_id|. |nv| must
|
||||
|
@ -158,6 +158,7 @@ static void spdylay_outbound_item_free(spdylay_outbound_item *item)
|
||||
break;
|
||||
}
|
||||
free(item->frame);
|
||||
free(item->aux_data);
|
||||
}
|
||||
|
||||
void spdylay_session_del(spdylay_session *session)
|
||||
@ -180,7 +181,8 @@ void spdylay_session_del(spdylay_session *session)
|
||||
|
||||
int spdylay_session_add_frame(spdylay_session *session,
|
||||
spdylay_frame_type frame_type,
|
||||
spdylay_frame *frame)
|
||||
spdylay_frame *frame,
|
||||
void *aux_data)
|
||||
{
|
||||
int r;
|
||||
spdylay_outbound_item *item;
|
||||
@ -190,6 +192,7 @@ int spdylay_session_add_frame(spdylay_session *session,
|
||||
}
|
||||
item->frame_type = frame_type;
|
||||
item->frame = frame;
|
||||
item->aux_data = aux_data;
|
||||
/* Set priority lowest at the moment. */
|
||||
item->pri = 3;
|
||||
switch(frame_type) {
|
||||
@ -255,7 +258,7 @@ int spdylay_session_add_rst_stream(spdylay_session *session,
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
spdylay_frame_rst_stream_init(&frame->rst_stream, stream_id, status_code);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_RST_STREAM, frame);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_RST_STREAM, frame, NULL);
|
||||
if(r != 0) {
|
||||
spdylay_frame_rst_stream_free(&frame->rst_stream);
|
||||
free(frame);
|
||||
@ -349,12 +352,14 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
|
||||
ssize_t framebuflen;
|
||||
switch(item->frame_type) {
|
||||
case SPDYLAY_SYN_STREAM: {
|
||||
uint32_t stream_id;
|
||||
if(session->goaway_flags) {
|
||||
/* When GOAWAY is sent or received, peer must not send new
|
||||
SYN_STREAM. */
|
||||
return SPDYLAY_ERR_INVALID_FRAME;
|
||||
}
|
||||
item->frame->syn_stream.stream_id = session->next_stream_id;
|
||||
stream_id = session->next_stream_id;
|
||||
item->frame->syn_stream.stream_id = stream_id;
|
||||
session->next_stream_id += 2;
|
||||
framebuflen = spdylay_frame_pack_syn_stream(&framebuf,
|
||||
&item->frame->syn_stream,
|
||||
@ -362,13 +367,24 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
}
|
||||
if(spdylay_session_open_stream(session, item->frame->syn_stream.stream_id,
|
||||
if(spdylay_session_open_stream(session, stream_id,
|
||||
item->frame->syn_stream.hd.flags,
|
||||
item->frame->syn_stream.pri,
|
||||
SPDYLAY_STREAM_INITIAL) == NULL) {
|
||||
free(framebuf);
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
if(item->aux_data) {
|
||||
/* We assume aux_data is a pointer to spdylay_data_provider */
|
||||
spdylay_data_provider *data_prd = (spdylay_data_provider*)item->aux_data;
|
||||
int r;
|
||||
r = spdylay_submit_data(session, stream_id, data_prd);
|
||||
if(r != 0) {
|
||||
free(framebuf);
|
||||
spdylay_session_close_stream(session, stream_id);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SPDYLAY_SYN_REPLY: {
|
||||
@ -1188,7 +1204,7 @@ int spdylay_session_add_ping(spdylay_session *session, uint32_t unique_id)
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
spdylay_frame_ping_init(&frame->ping, unique_id);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_PING, frame);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_PING, frame, NULL);
|
||||
if(r != 0) {
|
||||
spdylay_frame_ping_free(&frame->ping);
|
||||
free(frame);
|
||||
@ -1206,7 +1222,7 @@ int spdylay_session_add_goaway(spdylay_session *session,
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
spdylay_frame_goaway_init(&frame->goaway, last_good_stream_id);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_GOAWAY, frame);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_GOAWAY, frame, NULL);
|
||||
if(r != 0) {
|
||||
spdylay_frame_goaway_free(&frame->goaway);
|
||||
free(frame);
|
||||
@ -1248,60 +1264,76 @@ int spdylay_submit_response(spdylay_session *session,
|
||||
}
|
||||
spdylay_frame_syn_reply_init(&frame->syn_reply, flags, stream_id,
|
||||
nv_copy);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_SYN_REPLY, frame);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_SYN_REPLY, frame, NULL);
|
||||
if(r != 0) {
|
||||
spdylay_frame_syn_reply_free(&frame->syn_reply);
|
||||
free(frame);
|
||||
return r;
|
||||
}
|
||||
if(data_prd != NULL) {
|
||||
spdylay_frame *data_frame;
|
||||
r = spdylay_submit_data(session, stream_id, data_prd);
|
||||
/* TODO If error is not FATAL, we should add RST_STREAM frame to
|
||||
cancel this stream. */
|
||||
data_frame = malloc(sizeof(spdylay_frame));
|
||||
if(data_frame == NULL) {
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
spdylay_frame_data_init(&data_frame->data, stream_id, data_prd);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_DATA, data_frame);
|
||||
if(r != 0) {
|
||||
spdylay_frame_data_free(&data_frame->data);
|
||||
free(data_frame);
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
int spdylay_submit_data(spdylay_session *session, int32_t stream_id,
|
||||
spdylay_data_provider *data_prd)
|
||||
{
|
||||
int r;
|
||||
spdylay_frame *frame;
|
||||
frame = malloc(sizeof(spdylay_frame));
|
||||
if(frame == NULL) {
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
spdylay_frame_data_init(&frame->data, stream_id, data_prd);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_DATA, frame, NULL);
|
||||
if(r != 0) {
|
||||
spdylay_frame_data_free(&frame->data);
|
||||
free(frame);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
int spdylay_submit_request(spdylay_session *session, uint8_t pri,
|
||||
const char **nv)
|
||||
const char **nv, spdylay_data_provider *data_prd)
|
||||
{
|
||||
int r;
|
||||
spdylay_frame *frame;
|
||||
char **nv_copy;
|
||||
uint8_t flags = 0;
|
||||
spdylay_data_provider *data_prd_copy;
|
||||
if(pri > 3) {
|
||||
return SPDYLAY_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
data_prd_copy = malloc(sizeof(spdylay_data_provider));
|
||||
if(data_prd_copy == NULL) {
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
*data_prd_copy = *data_prd;
|
||||
frame = malloc(sizeof(spdylay_frame));
|
||||
if(frame == NULL) {
|
||||
free(data_prd_copy);
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
nv_copy = spdylay_frame_nv_copy(nv);
|
||||
if(nv_copy == NULL) {
|
||||
free(frame);
|
||||
free(data_prd_copy);
|
||||
return SPDYLAY_ERR_NOMEM;
|
||||
}
|
||||
spdylay_frame_nv_sort(nv_copy);
|
||||
/* When we support POST using spdylay_data_provider, flags should be
|
||||
0 if data_prd is set. */
|
||||
flags |= SPDYLAY_FLAG_FIN;
|
||||
spdylay_frame_syn_stream_init(&frame->syn_stream,
|
||||
SPDYLAY_FLAG_FIN, 0, 0, pri, nv_copy);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame);
|
||||
if(data_prd == NULL) {
|
||||
flags |= SPDYLAY_FLAG_FIN;
|
||||
}
|
||||
spdylay_frame_syn_stream_init(&frame->syn_stream, flags, 0, 0, pri, nv_copy);
|
||||
r = spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame,
|
||||
data_prd_copy);
|
||||
if(r != 0) {
|
||||
spdylay_frame_syn_stream_free(&frame->syn_stream);
|
||||
free(frame);
|
||||
free(data_prd_copy);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
typedef struct {
|
||||
spdylay_frame_type frame_type;
|
||||
spdylay_frame *frame;
|
||||
void *aux_data;
|
||||
int pri;
|
||||
} spdylay_outbound_item;
|
||||
|
||||
@ -123,9 +124,17 @@ typedef struct spdylay_session {
|
||||
|
||||
/* TODO stream timeout etc */
|
||||
|
||||
/*
|
||||
* Adds frame |frame| of type |frame_type| to tx queue in |session|.
|
||||
* |aux_data| is a pointer to arbitrary data. Its interpretation is
|
||||
* defined per |frame_type|. When this function succeeds, it takes
|
||||
* ownership of |frame| and |aux_data|, so caller must not free them.
|
||||
* This function returns 0 if it succeeds, or negative error code.
|
||||
*/
|
||||
int spdylay_session_add_frame(spdylay_session *session,
|
||||
spdylay_frame_type frame_type,
|
||||
spdylay_frame *frame);
|
||||
spdylay_frame *frame,
|
||||
void *aux_data);
|
||||
|
||||
int spdylay_session_add_rst_stream(spdylay_session *session,
|
||||
int32_t stream_id, uint32_t status_code);
|
||||
|
@ -80,6 +80,8 @@ int main()
|
||||
!CU_add_test(pSuite, "session_send_syn_reply",
|
||||
test_spdylay_session_send_syn_reply) ||
|
||||
!CU_add_test(pSuite, "submit_response", test_spdylay_submit_response) ||
|
||||
!CU_add_test(pSuite, "submit_request_with_data",
|
||||
test_spdylay_submit_request_with_data) ||
|
||||
!CU_add_test(pSuite, "session_reply_fail",
|
||||
test_spdylay_session_reply_fail) ||
|
||||
!CU_add_test(pSuite, "session_on_headers_received",
|
||||
|
@ -220,7 +220,8 @@ void test_spdylay_session_add_frame()
|
||||
spdylay_frame_syn_stream_init(&frame->syn_stream, SPDYLAY_FLAG_NONE, 0, 0, 3,
|
||||
dup_nv(nv));
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame));
|
||||
CU_ASSERT(0 == spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame,
|
||||
NULL));
|
||||
CU_ASSERT(0 == spdylay_pq_empty(&session->ob_pq));
|
||||
CU_ASSERT(0 == spdylay_session_send(session));
|
||||
CU_ASSERT(memcmp(hd_ans1, acc.buf, 4) == 0);
|
||||
@ -380,7 +381,7 @@ void test_spdylay_session_send_syn_stream()
|
||||
spdylay_session_client_new(&session, &callbacks, NULL);
|
||||
spdylay_frame_syn_stream_init(&frame->syn_stream, SPDYLAY_FLAG_NONE,
|
||||
0, 0, 3, dup_nv(nv));
|
||||
spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame);
|
||||
spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame, NULL);
|
||||
CU_ASSERT(0 == spdylay_session_send(session));
|
||||
stream = spdylay_session_get_stream(session, 1);
|
||||
CU_ASSERT(SPDYLAY_STREAM_OPENING == stream->state);
|
||||
@ -406,7 +407,7 @@ void test_spdylay_session_send_syn_reply()
|
||||
SPDYLAY_STREAM_OPENING);
|
||||
spdylay_frame_syn_reply_init(&frame->syn_reply, SPDYLAY_FLAG_NONE,
|
||||
2, dup_nv(nv));
|
||||
spdylay_session_add_frame(session, SPDYLAY_SYN_REPLY, frame);
|
||||
spdylay_session_add_frame(session, SPDYLAY_SYN_REPLY, frame, NULL);
|
||||
CU_ASSERT(0 == spdylay_session_send(session));
|
||||
stream = spdylay_session_get_stream(session, 2);
|
||||
CU_ASSERT(SPDYLAY_STREAM_OPENED == stream->state);
|
||||
@ -442,6 +443,33 @@ void test_spdylay_submit_response()
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
void test_spdylay_submit_request_with_data()
|
||||
{
|
||||
spdylay_session *session;
|
||||
spdylay_session_callbacks callbacks = {
|
||||
null_send_callback,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
const char *nv[] = { NULL };
|
||||
spdylay_data_source source;
|
||||
spdylay_data_provider data_prd = {
|
||||
source,
|
||||
fixed_length_data_source_read_callback
|
||||
};
|
||||
my_user_data ud;
|
||||
|
||||
ud.data_source_length = 64*1024;
|
||||
|
||||
CU_ASSERT(0 == spdylay_session_client_new(&session, &callbacks, &ud));
|
||||
CU_ASSERT(0 == spdylay_submit_request(session, 3, nv, &data_prd));
|
||||
CU_ASSERT(0 == spdylay_session_send(session));
|
||||
CU_ASSERT(0 == ud.data_source_length);
|
||||
|
||||
spdylay_session_del(session);
|
||||
}
|
||||
|
||||
void test_spdylay_session_reply_fail()
|
||||
{
|
||||
spdylay_session *session;
|
||||
|
@ -33,6 +33,7 @@ void test_spdylay_session_on_syn_reply_received();
|
||||
void test_spdylay_session_send_syn_stream();
|
||||
void test_spdylay_session_send_syn_reply();
|
||||
void test_spdylay_submit_response();
|
||||
void test_spdylay_submit_request_with_data();
|
||||
void test_spdylay_session_reply_fail();
|
||||
void test_spdylay_session_on_headers_received();
|
||||
void test_spdylay_session_on_ping_received();
|
||||
|
Loading…
Reference in New Issue
Block a user