Added spdylay_submit_headers function.
This commit is contained in:
parent
e182308cb7
commit
769150d5f7
|
@ -541,6 +541,26 @@ int spdylay_submit_syn_stream(spdylay_session *session, uint8_t flags,
|
||||||
int32_t assoc_stream_id, uint8_t pri,
|
int32_t assoc_stream_id, uint8_t pri,
|
||||||
const char **nv, void *stream_user_data);
|
const char **nv, void *stream_user_data);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Submits HEADERS frame. The |flags| is bitwise OR of the following
|
||||||
|
* values:
|
||||||
|
*
|
||||||
|
* SPDYLAY_FLAG_FIN
|
||||||
|
*
|
||||||
|
* If |flags| includes SPDYLAY_FLAG_FIN, this frame has FIN flag set.
|
||||||
|
*
|
||||||
|
* The stream this frame belongs to is given in |stream_id|. The |nv|
|
||||||
|
* is the name/value pairs in this frame.
|
||||||
|
*
|
||||||
|
* This function returns 0 if it succeeds, or one of the following
|
||||||
|
* negative error codes:
|
||||||
|
*
|
||||||
|
* SPDYLAY_ERR_NOMEM
|
||||||
|
* Out of memory.
|
||||||
|
*/
|
||||||
|
int spdylay_submit_headers(spdylay_session *session, uint8_t flags,
|
||||||
|
int32_t stream_id, const char **nv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Submits 1 or more DATA frames to the stream |stream_id|. The data
|
* Submits 1 or more DATA frames to the stream |stream_id|. The data
|
||||||
* to be sent are provided by |data_prd|. Depending on the length of
|
* to be sent are provided by |data_prd|. Depending on the length of
|
||||||
|
|
|
@ -293,10 +293,14 @@ int spdylay_session_add_frame(spdylay_session *session,
|
||||||
case SPDYLAY_GOAWAY:
|
case SPDYLAY_GOAWAY:
|
||||||
/* Should GOAWAY have higher priority? */
|
/* Should GOAWAY have higher priority? */
|
||||||
break;
|
break;
|
||||||
case SPDYLAY_HEADERS:
|
case SPDYLAY_HEADERS: {
|
||||||
/* Currently we don't have any API to send HEADERS frame, so this
|
spdylay_stream *stream = spdylay_session_get_stream
|
||||||
is unreachable. */
|
(session, frame->headers.stream_id);
|
||||||
abort();
|
if(stream) {
|
||||||
|
item->pri = stream->pri;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SPDYLAY_DATA: {
|
case SPDYLAY_DATA: {
|
||||||
spdylay_stream *stream = spdylay_session_get_stream
|
spdylay_stream *stream = spdylay_session_get_stream
|
||||||
(session, frame->data.stream_id);
|
(session, frame->data.stream_id);
|
||||||
|
@ -423,6 +427,24 @@ static int spdylay_session_is_reply_allowed(spdylay_session *session,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns nonzero value if local endpoint can send HEADERS with
|
||||||
|
* stream ID |stream_id| at the moment.
|
||||||
|
*/
|
||||||
|
static int spdylay_session_is_headers_allowed(spdylay_session *session,
|
||||||
|
int32_t stream_id)
|
||||||
|
{
|
||||||
|
spdylay_stream *stream = spdylay_session_get_stream(session, stream_id);
|
||||||
|
if(stream == NULL || (stream->shut_flags & SPDYLAY_SHUT_WR)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if(spdylay_session_is_my_stream_id(session, stream_id)) {
|
||||||
|
return stream->state != SPDYLAY_STREAM_CLOSING;
|
||||||
|
} else {
|
||||||
|
return stream->state == SPDYLAY_STREAM_OPENED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int spdylay_session_is_data_allowed(spdylay_session *session,
|
static int spdylay_session_is_data_allowed(spdylay_session *session,
|
||||||
int32_t stream_id)
|
int32_t stream_id)
|
||||||
{
|
{
|
||||||
|
@ -534,10 +556,22 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
|
||||||
return framebuflen;
|
return framebuflen;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SPDYLAY_HEADERS:
|
case SPDYLAY_HEADERS: {
|
||||||
/* Currently we don't have any API to send HEADERS frame, so this
|
if(!spdylay_session_is_headers_allowed(session,
|
||||||
is unreachable. */
|
item->frame->headers.stream_id)) {
|
||||||
abort();
|
return SPDYLAY_ERR_INVALID_FRAME;
|
||||||
|
}
|
||||||
|
framebuflen = spdylay_frame_pack_headers(&session->aob.framebuf,
|
||||||
|
&session->aob.framebufmax,
|
||||||
|
&session->nvbuf,
|
||||||
|
&session->nvbuflen,
|
||||||
|
&item->frame->headers,
|
||||||
|
&session->hd_deflater);
|
||||||
|
if(framebuflen < 0) {
|
||||||
|
return framebuflen;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SPDYLAY_GOAWAY:
|
case SPDYLAY_GOAWAY:
|
||||||
if(session->goaway_flags & SPDYLAY_GOAWAY_SEND) {
|
if(session->goaway_flags & SPDYLAY_GOAWAY_SEND) {
|
||||||
/* TODO The spec does not mandate that both endpoints have to
|
/* TODO The spec does not mandate that both endpoints have to
|
||||||
|
@ -776,10 +810,17 @@ static int spdylay_session_after_frame_sent(spdylay_session *session)
|
||||||
case SPDYLAY_GOAWAY:
|
case SPDYLAY_GOAWAY:
|
||||||
session->goaway_flags |= SPDYLAY_GOAWAY_SEND;
|
session->goaway_flags |= SPDYLAY_GOAWAY_SEND;
|
||||||
break;
|
break;
|
||||||
case SPDYLAY_HEADERS:
|
case SPDYLAY_HEADERS: {
|
||||||
/* Currently we don't have any API to send HEADERS frame, so this
|
spdylay_stream *stream =
|
||||||
is unreachable. */
|
spdylay_session_get_stream(session, frame->headers.stream_id);
|
||||||
abort();
|
if(stream) {
|
||||||
|
if(frame->headers.hd.flags & SPDYLAY_FLAG_FIN) {
|
||||||
|
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_WR);
|
||||||
|
}
|
||||||
|
spdylay_session_close_stream_if_shut_rdwr(session, stream);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case SPDYLAY_DATA:
|
case SPDYLAY_DATA:
|
||||||
if(frame->data.eof && (frame->data.flags & SPDYLAY_FLAG_FIN)) {
|
if(frame->data.eof && (frame->data.flags & SPDYLAY_FLAG_FIN)) {
|
||||||
spdylay_stream *stream =
|
spdylay_stream *stream =
|
||||||
|
|
|
@ -106,6 +106,37 @@ int spdylay_submit_syn_stream(spdylay_session *session, uint8_t flags,
|
||||||
pri, nv, NULL, stream_user_data);
|
pri, nv, NULL, stream_user_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int spdylay_submit_headers(spdylay_session *session, uint8_t flags,
|
||||||
|
int32_t stream_id, const char **nv)
|
||||||
|
{
|
||||||
|
int r;
|
||||||
|
spdylay_frame *frame;
|
||||||
|
char **nv_copy;
|
||||||
|
uint8_t flags_copy;
|
||||||
|
frame = malloc(sizeof(spdylay_frame));
|
||||||
|
if(frame == NULL) {
|
||||||
|
return SPDYLAY_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
nv_copy = spdylay_frame_nv_copy(nv);
|
||||||
|
if(nv_copy == NULL) {
|
||||||
|
free(frame);
|
||||||
|
return SPDYLAY_ERR_NOMEM;
|
||||||
|
}
|
||||||
|
spdylay_frame_nv_downcase(nv_copy);
|
||||||
|
spdylay_frame_nv_sort(nv_copy);
|
||||||
|
flags_copy = 0;
|
||||||
|
if(flags & SPDYLAY_FLAG_FIN) {
|
||||||
|
flags_copy |= SPDYLAY_FLAG_FIN;
|
||||||
|
}
|
||||||
|
spdylay_frame_headers_init(&frame->headers, flags_copy, stream_id, nv_copy);
|
||||||
|
r = spdylay_session_add_frame(session, SPDYLAY_HEADERS, frame, NULL);
|
||||||
|
if(r != 0) {
|
||||||
|
spdylay_frame_headers_free(&frame->headers);
|
||||||
|
free(frame);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
int spdylay_submit_ping(spdylay_session *session)
|
int spdylay_submit_ping(spdylay_session *session)
|
||||||
{
|
{
|
||||||
return spdylay_session_add_ping(session,
|
return spdylay_session_add_ping(session,
|
||||||
|
|
|
@ -93,6 +93,7 @@ int main(int argc, char* argv[])
|
||||||
test_spdylay_submit_request_with_null_data_read_callback) ||
|
test_spdylay_submit_request_with_null_data_read_callback) ||
|
||||||
!CU_add_test(pSuite, "submit_syn_stream",
|
!CU_add_test(pSuite, "submit_syn_stream",
|
||||||
test_spdylay_submit_syn_stream) ||
|
test_spdylay_submit_syn_stream) ||
|
||||||
|
!CU_add_test(pSuite, "submit_headers", test_spdylay_submit_headers) ||
|
||||||
!CU_add_test(pSuite, "session_reply_fail",
|
!CU_add_test(pSuite, "session_reply_fail",
|
||||||
test_spdylay_session_reply_fail) ||
|
test_spdylay_session_reply_fail) ||
|
||||||
!CU_add_test(pSuite, "session_on_headers_received",
|
!CU_add_test(pSuite, "session_on_headers_received",
|
||||||
|
|
|
@ -665,6 +665,42 @@ void test_spdylay_submit_syn_stream()
|
||||||
spdylay_session_del(session);
|
spdylay_session_del(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test_spdylay_submit_headers()
|
||||||
|
{
|
||||||
|
spdylay_session *session;
|
||||||
|
spdylay_session_callbacks callbacks;
|
||||||
|
const char *nv[] = { "version", "HTTP/1.1", NULL };
|
||||||
|
my_user_data ud;
|
||||||
|
spdylay_outbound_item *item;
|
||||||
|
spdylay_stream *stream;
|
||||||
|
|
||||||
|
memset(&callbacks, 0, sizeof(spdylay_session_callbacks));
|
||||||
|
callbacks.send_callback = null_send_callback;
|
||||||
|
callbacks.on_ctrl_send_callback = on_ctrl_send_callback;
|
||||||
|
|
||||||
|
CU_ASSERT(0 == spdylay_session_client_new(&session, &callbacks, &ud));
|
||||||
|
CU_ASSERT(0 == spdylay_submit_headers(session, SPDYLAY_FLAG_FIN, 1, nv));
|
||||||
|
item = spdylay_session_get_next_ob_item(session);
|
||||||
|
CU_ASSERT(0 == strcmp("version", item->frame->headers.nv[0]));
|
||||||
|
CU_ASSERT(SPDYLAY_FLAG_FIN == item->frame->headers.hd.flags);
|
||||||
|
|
||||||
|
ud.ctrl_send_cb_called = 0;
|
||||||
|
ud.sent_frame_type = 0;
|
||||||
|
CU_ASSERT(0 == spdylay_session_send(session));
|
||||||
|
CU_ASSERT(0 == ud.ctrl_send_cb_called);
|
||||||
|
|
||||||
|
stream = spdylay_session_open_stream(session, 1, SPDYLAY_FLAG_NONE, 3,
|
||||||
|
SPDYLAY_STREAM_OPENING, NULL);
|
||||||
|
|
||||||
|
CU_ASSERT(0 == spdylay_submit_headers(session, SPDYLAY_FLAG_FIN, 1, nv));
|
||||||
|
CU_ASSERT(0 == spdylay_session_send(session));
|
||||||
|
CU_ASSERT(1 == ud.ctrl_send_cb_called);
|
||||||
|
CU_ASSERT(SPDYLAY_HEADERS == ud.sent_frame_type);
|
||||||
|
CU_ASSERT(stream->shut_flags & SPDYLAY_SHUT_WR);
|
||||||
|
|
||||||
|
spdylay_session_del(session);
|
||||||
|
}
|
||||||
|
|
||||||
void test_spdylay_session_reply_fail()
|
void test_spdylay_session_reply_fail()
|
||||||
{
|
{
|
||||||
spdylay_session *session;
|
spdylay_session *session;
|
||||||
|
|
|
@ -38,6 +38,7 @@ void test_spdylay_submit_response_with_null_data_read_callback();
|
||||||
void test_spdylay_submit_request_with_data();
|
void test_spdylay_submit_request_with_data();
|
||||||
void test_spdylay_submit_request_with_null_data_read_callback();
|
void test_spdylay_submit_request_with_null_data_read_callback();
|
||||||
void test_spdylay_submit_syn_stream();
|
void test_spdylay_submit_syn_stream();
|
||||||
|
void test_spdylay_submit_headers();
|
||||||
void test_spdylay_session_reply_fail();
|
void test_spdylay_session_reply_fail();
|
||||||
void test_spdylay_session_on_headers_received();
|
void test_spdylay_session_on_headers_received();
|
||||||
void test_spdylay_session_on_ping_received();
|
void test_spdylay_session_on_ping_received();
|
||||||
|
|
Loading…
Reference in New Issue