Added spdylay_submit_headers function.

This commit is contained in:
Tatsuhiro Tsujikawa
2012-02-24 00:02:29 +09:00
parent e182308cb7
commit 769150d5f7
6 changed files with 142 additions and 12 deletions

View File

@@ -541,6 +541,26 @@ int spdylay_submit_syn_stream(spdylay_session *session, uint8_t flags,
int32_t assoc_stream_id, uint8_t pri,
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
* to be sent are provided by |data_prd|. Depending on the length of

View File

@@ -293,10 +293,14 @@ int spdylay_session_add_frame(spdylay_session *session,
case SPDYLAY_GOAWAY:
/* Should GOAWAY have higher priority? */
break;
case SPDYLAY_HEADERS:
/* Currently we don't have any API to send HEADERS frame, so this
is unreachable. */
abort();
case SPDYLAY_HEADERS: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->headers.stream_id);
if(stream) {
item->pri = stream->pri;
}
break;
}
case SPDYLAY_DATA: {
spdylay_stream *stream = spdylay_session_get_stream
(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,
int32_t stream_id)
{
@@ -534,10 +556,22 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
return framebuflen;
}
break;
case SPDYLAY_HEADERS:
/* Currently we don't have any API to send HEADERS frame, so this
is unreachable. */
abort();
case SPDYLAY_HEADERS: {
if(!spdylay_session_is_headers_allowed(session,
item->frame->headers.stream_id)) {
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:
if(session->goaway_flags & SPDYLAY_GOAWAY_SEND) {
/* 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:
session->goaway_flags |= SPDYLAY_GOAWAY_SEND;
break;
case SPDYLAY_HEADERS:
/* Currently we don't have any API to send HEADERS frame, so this
is unreachable. */
abort();
case SPDYLAY_HEADERS: {
spdylay_stream *stream =
spdylay_session_get_stream(session, frame->headers.stream_id);
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:
if(frame->data.eof && (frame->data.flags & SPDYLAY_FLAG_FIN)) {
spdylay_stream *stream =

View File

@@ -106,6 +106,37 @@ int spdylay_submit_syn_stream(spdylay_session *session, uint8_t flags,
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)
{
return spdylay_session_add_ping(session,