Hide spdylay_data from public API.

The spdylay_data contains full of implementation details and is not
used in public API. It should be hidden.
The spdylay_frame union now only contains the control frame.
This commit is contained in:
Tatsuhiro Tsujikawa 2012-03-29 23:59:51 +09:00
parent 67e83e09a6
commit ba56ed6c48
8 changed files with 572 additions and 497 deletions

View File

@ -176,7 +176,7 @@ typedef enum {
/**
* @enum
* The frame types in SPDY protocol.
* The control frame types in SPDY protocol.
*/
typedef enum {
/**
@ -214,11 +214,7 @@ typedef enum {
/**
* The WINDOW_UPDATE control frame. This first appeared in SPDY/3.
*/
SPDYLAY_WINDOW_UPDATE = 9,
/**
* The DATA frame.
*/
SPDYLAY_DATA = 100
SPDYLAY_WINDOW_UPDATE = 9
} spdylay_frame_type;
/**
@ -639,6 +635,19 @@ typedef struct {
int32_t delta_window_size;
} spdylay_window_update;
/**
* @struct
*
* Convenient structure to inspect control frame header. It is useful
* to get the frame type.
*/
typedef struct {
/**
* The control frame header.
*/
spdylay_ctrl_hd hd;
} spdylay_ctrl_frame;
/**
* @union
*
@ -695,37 +704,17 @@ typedef struct {
spdylay_data_source_read_callback read_callback;
} spdylay_data_provider;
/**
* @struct
* The DATA frame. It has the following members:
*/
typedef struct {
/**
* The stream ID.
*/
int32_t stream_id;
/**
* The DATA frame flags. See :type:`spdylay_data_flag`.
*/
uint8_t flags;
/**
* The flag to indicate whether EOF was reached or not. Initially
* |eof| is 0. It becomes 1 after all data were read.
*/
uint8_t eof;
/**
* The data to be sent for this DATA frame.
*/
spdylay_data_provider data_prd;
} spdylay_data;
/**
* @union
*
* This union includes all control frames and DATA frame to pass them
* This union includes all control frames to pass them
* to various function calls as spdylay_frame type.
*/
typedef union {
/**
* Convenient structure to inspect control frame header.
*/
spdylay_ctrl_frame common;
/**
* The SYN_STREAM control frame.
*/
@ -758,10 +747,6 @@ typedef union {
* The WINDOW_UPDATE control frame.
*/
spdylay_window_update window_update;
/**
* The DATA frame.
*/
spdylay_data data;
} spdylay_frame;
/**

View File

@ -52,6 +52,38 @@
(LEN_SIZE == 2 ? \
spdylay_put_uint16be(OUT, VAL) : spdylay_put_uint32be(OUT, VAL))
/* Category of SPDY frames. */
typedef enum {
/* Control frame */
SPDYLAY_CTRL,
/* DATA frame */
SPDYLAY_DATA
} spdylay_frame_category;
/**
* @struct
* The DATA frame. It has the following members:
*/
typedef struct {
/**
* The stream ID.
*/
int32_t stream_id;
/**
* The DATA frame flags. See :type:`spdylay_data_flag`.
*/
uint8_t flags;
/**
* The flag to indicate whether EOF was reached or not. Initially
* |eof| is 0. It becomes 1 after all data were read.
*/
uint8_t eof;
/**
* The data to be sent for this DATA frame.
*/
spdylay_data_provider data_prd;
} spdylay_data;
/*
* Returns the number of bytes in length of name/value pair for the
* given protocol version |version|. If |version| is not supported,

View File

@ -24,44 +24,56 @@
*/
#include "spdylay_outbound_item.h"
#include <assert.h>
void spdylay_outbound_item_free(spdylay_outbound_item *item)
{
if(item == NULL) {
return;
}
switch(item->frame_type) {
case SPDYLAY_SYN_STREAM:
spdylay_frame_syn_stream_free(&item->frame->syn_stream);
free(((spdylay_syn_stream_aux_data*)item->aux_data)->data_prd);
break;
case SPDYLAY_SYN_REPLY:
spdylay_frame_syn_reply_free(&item->frame->syn_reply);
break;
case SPDYLAY_RST_STREAM:
spdylay_frame_rst_stream_free(&item->frame->rst_stream);
break;
case SPDYLAY_SETTINGS:
spdylay_frame_settings_free(&item->frame->settings);
break;
case SPDYLAY_NOOP:
/* We don't have any public API to add NOOP, so here is
unreachable. */
abort();
case SPDYLAY_PING:
spdylay_frame_ping_free(&item->frame->ping);
break;
case SPDYLAY_GOAWAY:
spdylay_frame_goaway_free(&item->frame->goaway);
break;
case SPDYLAY_HEADERS:
spdylay_frame_headers_free(&item->frame->headers);
break;
case SPDYLAY_WINDOW_UPDATE:
spdylay_frame_window_update_free(&item->frame->window_update);
break;
case SPDYLAY_DATA:
spdylay_frame_data_free(&item->frame->data);
break;
if(item->frame_cat == SPDYLAY_CTRL) {
spdylay_frame_type frame_type;
spdylay_frame *frame;
frame_type = spdylay_outbound_item_get_ctrl_frame_type(item);
frame = spdylay_outbound_item_get_ctrl_frame(item);
switch(frame_type) {
case SPDYLAY_SYN_STREAM:
spdylay_frame_syn_stream_free(&frame->syn_stream);
free(((spdylay_syn_stream_aux_data*)item->aux_data)->data_prd);
break;
case SPDYLAY_SYN_REPLY:
spdylay_frame_syn_reply_free(&frame->syn_reply);
break;
case SPDYLAY_RST_STREAM:
spdylay_frame_rst_stream_free(&frame->rst_stream);
break;
case SPDYLAY_SETTINGS:
spdylay_frame_settings_free(&frame->settings);
break;
case SPDYLAY_NOOP:
/* We don't have any public API to add NOOP, so here is
unreachable. */
abort();
case SPDYLAY_PING:
spdylay_frame_ping_free(&frame->ping);
break;
case SPDYLAY_GOAWAY:
spdylay_frame_goaway_free(&frame->goaway);
break;
case SPDYLAY_HEADERS:
spdylay_frame_headers_free(&frame->headers);
break;
case SPDYLAY_WINDOW_UPDATE:
spdylay_frame_window_update_free(&frame->window_update);
break;
}
} else if(item->frame_cat == SPDYLAY_DATA) {
spdylay_data *data_frame;
data_frame = spdylay_outbound_item_get_data_frame(item);
spdylay_frame_data_free(data_frame);
} else {
/* Unreachable */
assert(0);
}
free(item->frame);
free(item->aux_data);

View File

@ -38,8 +38,10 @@ typedef struct {
} spdylay_syn_stream_aux_data;
typedef struct {
spdylay_frame_type frame_type;
spdylay_frame *frame;
/* Type of |frame|. SPDYLAY_CTRL: spdylay_frame*, SPDYLAY_DATA:
spdylay_data* */
spdylay_frame_category frame_cat;
void *frame;
void *aux_data;
int pri;
int64_t seq;
@ -51,4 +53,10 @@ typedef struct {
*/
void spdylay_outbound_item_free(spdylay_outbound_item *item);
/* Macros to cast spdylay_outbound_item.frame to the proper type. */
#define spdylay_outbound_item_get_ctrl_frame(ITEM) ((spdylay_frame*)ITEM->frame)
#define spdylay_outbound_item_get_ctrl_frame_type(ITEM) \
(((spdylay_frame*)ITEM->frame)->common.hd.type)
#define spdylay_outbound_item_get_data_frame(ITEM) ((spdylay_data*)ITEM->frame)
#endif /* SPDYLAY_OUTBOUND_ITEM_H */

View File

@ -305,8 +305,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_category frame_cat,
void *abs_frame,
void *aux_data)
{
int r;
@ -315,77 +315,84 @@ int spdylay_session_add_frame(spdylay_session *session,
if(item == NULL) {
return SPDYLAY_ERR_NOMEM;
}
item->frame_type = frame_type;
item->frame = frame;
item->frame_cat = frame_cat;
item->frame = abs_frame;
item->aux_data = aux_data;
item->seq = session->next_seq++;
/* Set priority lowest at the moment. */
item->pri = spdylay_session_get_pri_lowest(session);
switch(frame_type) {
case SPDYLAY_SYN_STREAM:
item->pri = frame->syn_stream.pri;
break;
case SPDYLAY_SYN_REPLY: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->syn_reply.stream_id);
if(frame_cat == SPDYLAY_CTRL) {
spdylay_frame *frame = (spdylay_frame*)abs_frame;
spdylay_frame_type frame_type = frame->common.hd.type;
switch(frame_type) {
case SPDYLAY_SYN_STREAM:
item->pri = frame->syn_stream.pri;
break;
case SPDYLAY_SYN_REPLY: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->syn_reply.stream_id);
if(stream) {
item->pri = stream->pri;
}
break;
}
case SPDYLAY_RST_STREAM: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->rst_stream.stream_id);
if(stream) {
stream->state = SPDYLAY_STREAM_CLOSING;
item->pri = stream->pri;
}
break;
}
case SPDYLAY_SETTINGS:
/* Should SPDYLAY_SETTINGS have higher priority? */
item->pri = -1;
break;
case SPDYLAY_NOOP:
/* We don't have any public API to add NOOP, so here is
unreachable. */
assert(0);
case SPDYLAY_PING:
/* Ping has "height" priority. Give it -1. */
item->pri = -1;
break;
case SPDYLAY_GOAWAY:
/* Should GOAWAY have higher priority? */
break;
case SPDYLAY_HEADERS: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->headers.stream_id);
if(stream) {
item->pri = stream->pri;
}
break;
}
case SPDYLAY_WINDOW_UPDATE: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->window_update.stream_id);
if(stream) {
item->pri = stream->pri;
}
break;
}
}
if(frame_type == SPDYLAY_SYN_STREAM) {
r = spdylay_pq_push(&session->ob_ss_pq, item);
} else {
r = spdylay_pq_push(&session->ob_pq, item);
}
} else if(frame_cat == SPDYLAY_DATA) {
spdylay_data *data_frame = (spdylay_data*)abs_frame;
spdylay_stream *stream = spdylay_session_get_stream(session,
data_frame->stream_id);
if(stream) {
item->pri = stream->pri;
}
break;
}
case SPDYLAY_RST_STREAM: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->rst_stream.stream_id);
if(stream) {
stream->state = SPDYLAY_STREAM_CLOSING;
item->pri = stream->pri;
}
break;
}
case SPDYLAY_SETTINGS:
/* Should SPDYLAY_SETTINGS have higher priority? */
item->pri = -1;
break;
case SPDYLAY_NOOP:
/* We don't have any public API to add NOOP, so here is
unreachable. */
abort();
case SPDYLAY_PING:
/* Ping has "height" priority. Give it -1. */
item->pri = -1;
break;
case SPDYLAY_GOAWAY:
/* Should GOAWAY have higher priority? */
break;
case SPDYLAY_HEADERS: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->headers.stream_id);
if(stream) {
item->pri = stream->pri;
}
break;
}
case SPDYLAY_WINDOW_UPDATE: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->window_update.stream_id);
if(stream) {
item->pri = stream->pri;
}
break;
}
case SPDYLAY_DATA: {
spdylay_stream *stream = spdylay_session_get_stream
(session, frame->data.stream_id);
if(stream) {
item->pri = stream->pri;
}
break;
}
};
if(frame_type == SPDYLAY_SYN_STREAM) {
r = spdylay_pq_push(&session->ob_ss_pq, item);
} else {
r = spdylay_pq_push(&session->ob_pq, item);
} else {
/* Unreachable */
assert(0);
}
if(r != 0) {
free(item);
@ -405,7 +412,7 @@ int spdylay_session_add_rst_stream(spdylay_session *session,
}
spdylay_frame_rst_stream_init(&frame->rst_stream, session->version,
stream_id, status_code);
r = spdylay_session_add_frame(session, SPDYLAY_RST_STREAM, frame, NULL);
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
if(r != 0) {
spdylay_frame_rst_stream_free(&frame->rst_stream);
free(frame);
@ -729,167 +736,176 @@ static ssize_t spdylay_session_prep_frame(spdylay_session *session,
spdylay_outbound_item *item)
{
ssize_t framebuflen;
switch(item->frame_type) {
case SPDYLAY_SYN_STREAM: {
int32_t stream_id;
spdylay_syn_stream_aux_data *aux_data;
int r;
r = spdylay_session_predicate_syn_stream_send(session,
&item->frame->syn_stream);
if(r != 0) {
return r;
}
stream_id = session->next_stream_id;
if(item->frame_cat == SPDYLAY_CTRL) {
spdylay_frame *frame;
spdylay_frame_type frame_type;
frame = spdylay_outbound_item_get_ctrl_frame(item);
frame_type = spdylay_outbound_item_get_ctrl_frame_type(item);
switch(frame_type) {
case SPDYLAY_SYN_STREAM: {
int32_t stream_id;
spdylay_syn_stream_aux_data *aux_data;
int r;
r = spdylay_session_predicate_syn_stream_send(session,
&frame->syn_stream);
if(r != 0) {
return r;
}
stream_id = session->next_stream_id;
item->frame->syn_stream.stream_id = stream_id;
session->next_stream_id += 2;
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_3to2(item->frame->syn_stream.nv);
spdylay_frame_nv_sort(item->frame->syn_stream.nv);
frame->syn_stream.stream_id = stream_id;
session->next_stream_id += 2;
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_3to2(frame->syn_stream.nv);
spdylay_frame_nv_sort(frame->syn_stream.nv);
}
framebuflen = spdylay_frame_pack_syn_stream(&session->aob.framebuf,
&session->aob.framebufmax,
&session->nvbuf,
&session->nvbuflen,
&frame->syn_stream,
&session->hd_deflater);
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_2to3(frame->syn_stream.nv);
spdylay_frame_nv_sort(frame->syn_stream.nv);
}
if(framebuflen < 0) {
return framebuflen;
}
aux_data = (spdylay_syn_stream_aux_data*)item->aux_data;
if(spdylay_session_open_stream(session, stream_id,
frame->syn_stream.hd.flags,
frame->syn_stream.pri,
SPDYLAY_STREAM_INITIAL,
aux_data->stream_user_data) == NULL) {
return SPDYLAY_ERR_NOMEM;
}
break;
}
framebuflen = spdylay_frame_pack_syn_stream(&session->aob.framebuf,
case SPDYLAY_SYN_REPLY: {
int r;
r = spdylay_session_predicate_syn_reply_send(session,
frame->syn_reply.stream_id);
if(r != 0) {
return r;
}
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_3to2(frame->syn_reply.nv);
spdylay_frame_nv_sort(frame->syn_reply.nv);
}
framebuflen = spdylay_frame_pack_syn_reply(&session->aob.framebuf,
&session->aob.framebufmax,
&session->nvbuf,
&session->nvbuflen,
&frame->syn_reply,
&session->hd_deflater);
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_2to3(frame->syn_reply.nv);
spdylay_frame_nv_sort(frame->syn_reply.nv);
}
if(framebuflen < 0) {
return framebuflen;
}
break;
}
case SPDYLAY_RST_STREAM:
framebuflen = spdylay_frame_pack_rst_stream(&session->aob.framebuf,
&session->aob.framebufmax,
&frame->rst_stream);
if(framebuflen < 0) {
return framebuflen;
}
break;
case SPDYLAY_SETTINGS:
framebuflen = spdylay_frame_pack_settings(&session->aob.framebuf,
&session->aob.framebufmax,
&session->nvbuf,
&session->nvbuflen,
&item->frame->syn_stream,
&session->hd_deflater);
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_2to3(item->frame->syn_stream.nv);
spdylay_frame_nv_sort(item->frame->syn_stream.nv);
}
if(framebuflen < 0) {
return framebuflen;
}
aux_data = (spdylay_syn_stream_aux_data*)item->aux_data;
if(spdylay_session_open_stream(session, stream_id,
item->frame->syn_stream.hd.flags,
item->frame->syn_stream.pri,
SPDYLAY_STREAM_INITIAL,
aux_data->stream_user_data) == NULL) {
return SPDYLAY_ERR_NOMEM;
}
break;
}
case SPDYLAY_SYN_REPLY: {
int r;
r = spdylay_session_predicate_syn_reply_send
(session, item->frame->syn_reply.stream_id);
if(r != 0) {
return r;
}
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_3to2(item->frame->syn_reply.nv);
spdylay_frame_nv_sort(item->frame->syn_reply.nv);
}
framebuflen = spdylay_frame_pack_syn_reply(&session->aob.framebuf,
&frame->settings);
if(framebuflen < 0) {
return framebuflen;
}
break;
case SPDYLAY_NOOP:
/* We don't have any public API to add NOOP, so here is
unreachable. */
assert(0);
case SPDYLAY_PING:
framebuflen = spdylay_frame_pack_ping(&session->aob.framebuf,
&session->aob.framebufmax,
&frame->ping);
if(framebuflen < 0) {
return framebuflen;
}
break;
case SPDYLAY_HEADERS: {
int r;
r = spdylay_session_predicate_headers_send(session,
frame->headers.stream_id);
if(r != 0) {
return r;
}
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_3to2(frame->headers.nv);
spdylay_frame_nv_sort(frame->headers.nv);
}
framebuflen = spdylay_frame_pack_headers(&session->aob.framebuf,
&session->aob.framebufmax,
&session->nvbuf,
&session->nvbuflen,
&item->frame->syn_reply,
&frame->headers,
&session->hd_deflater);
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_2to3(item->frame->syn_reply.nv);
spdylay_frame_nv_sort(item->frame->syn_reply.nv);
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_2to3(frame->headers.nv);
spdylay_frame_nv_sort(frame->headers.nv);
}
if(framebuflen < 0) {
return framebuflen;
}
break;
}
if(framebuflen < 0) {
return framebuflen;
case SPDYLAY_WINDOW_UPDATE: {
int r;
r = spdylay_session_predicate_window_update_send
(session, frame->window_update.stream_id);
if(r != 0) {
return r;
}
framebuflen = spdylay_frame_pack_window_update(&session->aob.framebuf,
&session->aob.framebufmax,
&frame->window_update);
if(framebuflen < 0) {
return framebuflen;
}
break;
}
break;
}
case SPDYLAY_RST_STREAM:
framebuflen = spdylay_frame_pack_rst_stream(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->rst_stream);
if(framebuflen < 0) {
return framebuflen;
}
break;
case SPDYLAY_SETTINGS:
framebuflen = spdylay_frame_pack_settings(&session->aob.framebuf,
case SPDYLAY_GOAWAY:
if(session->goaway_flags & SPDYLAY_GOAWAY_SEND) {
/* TODO The spec does not mandate that both endpoints have to
exchange GOAWAY. This implementation allows receiver of first
GOAWAY can sent its own GOAWAY to tell the remote peer that
last-good-stream-id. */
return SPDYLAY_ERR_GOAWAY_ALREADY_SENT;
}
framebuflen = spdylay_frame_pack_goaway(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->settings);
if(framebuflen < 0) {
return framebuflen;
&frame->goaway);
if(framebuflen < 0) {
return framebuflen;
}
break;
default:
framebuflen = SPDYLAY_ERR_INVALID_ARGUMENT;
}
break;
case SPDYLAY_NOOP:
/* We don't have any public API to add NOOP, so here is
unreachable. */
abort();
case SPDYLAY_PING:
framebuflen = spdylay_frame_pack_ping(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->ping);
if(framebuflen < 0) {
return framebuflen;
}
break;
case SPDYLAY_HEADERS: {
int r;
r = spdylay_session_predicate_headers_send(session,
item->frame->headers.stream_id);
if(r != 0) {
return r;
}
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_3to2(item->frame->headers.nv);
spdylay_frame_nv_sort(item->frame->headers.nv);
}
framebuflen = spdylay_frame_pack_headers(&session->aob.framebuf,
&session->aob.framebufmax,
&session->nvbuf,
&session->nvbuflen,
&item->frame->headers,
&session->hd_deflater);
if(session->version == SPDYLAY_PROTO_SPDY2) {
spdylay_frame_nv_2to3(item->frame->headers.nv);
spdylay_frame_nv_sort(item->frame->headers.nv);
}
if(framebuflen < 0) {
return framebuflen;
}
break;
}
case SPDYLAY_WINDOW_UPDATE: {
int r;
r = spdylay_session_predicate_window_update_send
(session, item->frame->window_update.stream_id);
if(r != 0) {
return r;
}
framebuflen = spdylay_frame_pack_window_update(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->window_update);
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
exchange GOAWAY. This implementation allows receiver of first
GOAWAY can sent its own GOAWAY to tell the remote peer that
last-good-stream-id. */
return SPDYLAY_ERR_GOAWAY_ALREADY_SENT;
}
framebuflen = spdylay_frame_pack_goaway(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->goaway);
if(framebuflen < 0) {
return framebuflen;
}
break;
case SPDYLAY_DATA: {
} else if(item->frame_cat == SPDYLAY_DATA) {
size_t next_readmax;
spdylay_stream *stream;
spdylay_data *data_frame;
int r;
r = spdylay_session_predicate_data_send(session,
item->frame->data.stream_id);
data_frame = spdylay_outbound_item_get_data_frame(item);
r = spdylay_session_predicate_data_send(session, data_frame->stream_id);
if(r != 0) {
return r;
}
stream = spdylay_session_get_stream(session, item->frame->data.stream_id);
stream = spdylay_session_get_stream(session, data_frame->stream_id);
/* Assuming stream is not NULL */
assert(stream);
next_readmax = spdylay_session_next_data_read(session, stream);
@ -901,17 +917,16 @@ static ssize_t spdylay_session_prep_frame(spdylay_session *session,
&session->aob.framebuf,
&session->aob.framebufmax,
next_readmax,
&item->frame->data);
data_frame);
if(framebuflen == SPDYLAY_ERR_DEFERRED) {
spdylay_stream_defer_data(stream, item, SPDYLAY_DEFERRED_NONE);
return SPDYLAY_ERR_DEFERRED;
} else if(framebuflen < 0) {
return framebuflen;
}
break;
}
default:
framebuflen = SPDYLAY_ERR_INVALID_ARGUMENT;
} else {
/* Unreachable */
assert(0);
}
return framebuflen;
}
@ -1013,136 +1028,140 @@ static int spdylay_session_after_frame_sent(spdylay_session *session)
{
/* TODO handle FIN flag. */
spdylay_outbound_item *item = session->aob.item;
spdylay_frame *frame = session->aob.item->frame;
spdylay_frame_type type = session->aob.item->frame_type;
if(type == SPDYLAY_DATA) {
if(session->callbacks.on_data_send_callback) {
session->callbacks.on_data_send_callback
(session,
frame->data.eof ? frame->data.flags :
(frame->data.flags & (~SPDYLAY_DATA_FLAG_FIN)),
frame->data.stream_id,
session->aob.framebuflen-SPDYLAY_HEAD_LEN, session->user_data);
}
} else {
if(session->callbacks.on_ctrl_send_callback) {
if(item->frame_cat == SPDYLAY_CTRL) {
spdylay_frame *frame;
spdylay_frame_type type;
frame = spdylay_outbound_item_get_ctrl_frame(session->aob.item);
type = spdylay_outbound_item_get_ctrl_frame_type(session->aob.item);
if(session->callbacks.on_ctrl_send_callback &&
type != SPDYLAY_WINDOW_UPDATE) {
session->callbacks.on_ctrl_send_callback
(session, type, frame, session->user_data);
}
}
switch(type) {
case SPDYLAY_SYN_STREAM: {
spdylay_stream *stream =
spdylay_session_get_stream(session, frame->syn_stream.stream_id);
if(stream) {
spdylay_syn_stream_aux_data *aux_data;
stream->state = SPDYLAY_STREAM_OPENING;
if(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_WR);
}
if(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_RD);
}
spdylay_session_close_stream_if_shut_rdwr(session, stream);
/* We assume aux_data is a pointer to spdylay_syn_stream_aux_data */
aux_data = (spdylay_syn_stream_aux_data*)item->aux_data;
if(aux_data->data_prd) {
int r;
/* spdylay_submit_data() makes a copy of aux_data->data_prd */
r = spdylay_submit_data(session, frame->syn_stream.stream_id,
SPDYLAY_DATA_FLAG_FIN, aux_data->data_prd);
if(r != 0) {
/* FATAL error */
assert(r < SPDYLAY_ERR_FATAL);
/* TODO If r is not FATAL, we should send RST_STREAM. */
return r;
}
}
}
break;
}
case SPDYLAY_SYN_REPLY: {
spdylay_stream *stream =
spdylay_session_get_stream(session, frame->syn_reply.stream_id);
if(stream) {
stream->state = SPDYLAY_STREAM_OPENED;
if(frame->syn_reply.hd.flags & SPDYLAY_CTRL_FLAG_FIN) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_WR);
}
spdylay_session_close_stream_if_shut_rdwr(session, stream);
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, frame->syn_reply.stream_id,
SPDYLAY_DATA_FLAG_FIN, data_prd);
if(r != 0) {
/* FATAL error */
assert(r < SPDYLAY_ERR_FATAL);
/* TODO If r is not FATAL, we should send RST_STREAM. */
return r;
}
}
}
break;
}
case SPDYLAY_RST_STREAM:
if(!session->server &&
spdylay_session_is_my_stream_id(session, frame->rst_stream.stream_id) &&
frame->rst_stream.status_code == SPDYLAY_CANCEL) {
spdylay_session_close_pushed_streams(session, frame->rst_stream.stream_id,
frame->rst_stream.status_code);
}
spdylay_session_close_stream(session, frame->rst_stream.stream_id,
frame->rst_stream.status_code);
break;
case SPDYLAY_SETTINGS:
/* nothing to do */
break;
case SPDYLAY_NOOP:
/* We don't have any public API to add NOOP, so here is
unreachable. */
abort();
case SPDYLAY_PING:
/* We record the time now and show application code RTT when
reply PING is received. */
session->last_ping_unique_id = frame->ping.unique_id;
break;
case SPDYLAY_GOAWAY:
session->goaway_flags |= SPDYLAY_GOAWAY_SEND;
break;
case SPDYLAY_HEADERS: {
spdylay_stream *stream =
spdylay_session_get_stream(session, frame->headers.stream_id);
if(stream) {
if(frame->headers.hd.flags & SPDYLAY_CTRL_FLAG_FIN) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_WR);
}
spdylay_session_close_stream_if_shut_rdwr(session, stream);
}
break;
}
case SPDYLAY_WINDOW_UPDATE:
break;
case SPDYLAY_DATA:
if(frame->data.eof && (frame->data.flags & SPDYLAY_DATA_FLAG_FIN)) {
switch(type) {
case SPDYLAY_SYN_STREAM: {
spdylay_stream *stream =
spdylay_session_get_stream(session, frame->data.stream_id);
spdylay_session_get_stream(session, frame->syn_stream.stream_id);
if(stream) {
spdylay_syn_stream_aux_data *aux_data;
stream->state = SPDYLAY_STREAM_OPENING;
if(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_WR);
}
if(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_UNIDIRECTIONAL) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_RD);
}
spdylay_session_close_stream_if_shut_rdwr(session, stream);
/* We assume aux_data is a pointer to spdylay_syn_stream_aux_data */
aux_data = (spdylay_syn_stream_aux_data*)item->aux_data;
if(aux_data->data_prd) {
int r;
/* spdylay_submit_data() makes a copy of aux_data->data_prd */
r = spdylay_submit_data(session, frame->syn_stream.stream_id,
SPDYLAY_DATA_FLAG_FIN, aux_data->data_prd);
if(r != 0) {
/* FATAL error */
assert(r < SPDYLAY_ERR_FATAL);
/* TODO If r is not FATAL, we should send RST_STREAM. */
return r;
}
}
}
break;
}
case SPDYLAY_SYN_REPLY: {
spdylay_stream *stream =
spdylay_session_get_stream(session, frame->syn_reply.stream_id);
if(stream) {
stream->state = SPDYLAY_STREAM_OPENED;
if(frame->syn_reply.hd.flags & SPDYLAY_CTRL_FLAG_FIN) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_WR);
}
spdylay_session_close_stream_if_shut_rdwr(session, stream);
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, frame->syn_reply.stream_id,
SPDYLAY_DATA_FLAG_FIN, data_prd);
if(r != 0) {
/* FATAL error */
assert(r < SPDYLAY_ERR_FATAL);
/* TODO If r is not FATAL, we should send RST_STREAM. */
return r;
}
}
}
break;
}
case SPDYLAY_RST_STREAM:
if(!session->server &&
spdylay_session_is_my_stream_id(session,
frame->rst_stream.stream_id) &&
frame->rst_stream.status_code == SPDYLAY_CANCEL) {
spdylay_session_close_pushed_streams(session,
frame->rst_stream.stream_id,
frame->rst_stream.status_code);
}
spdylay_session_close_stream(session, frame->rst_stream.stream_id,
frame->rst_stream.status_code);
break;
case SPDYLAY_SETTINGS:
/* nothing to do */
break;
case SPDYLAY_NOOP:
/* We don't have any public API to add NOOP, so here is
unreachable. */
assert(0);
case SPDYLAY_PING:
/* We record the time now and show application code RTT when
reply PING is received. */
session->last_ping_unique_id = frame->ping.unique_id;
break;
case SPDYLAY_GOAWAY:
session->goaway_flags |= SPDYLAY_GOAWAY_SEND;
break;
case SPDYLAY_HEADERS: {
spdylay_stream *stream =
spdylay_session_get_stream(session, frame->headers.stream_id);
if(stream) {
if(frame->headers.hd.flags & SPDYLAY_CTRL_FLAG_FIN) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_WR);
}
spdylay_session_close_stream_if_shut_rdwr(session, stream);
}
break;
}
case SPDYLAY_WINDOW_UPDATE:
break;
}
spdylay_active_outbound_item_reset(&session->aob);
} else if(item->frame_cat == SPDYLAY_DATA) {
int r;
spdylay_data *data_frame;
data_frame = spdylay_outbound_item_get_data_frame(session->aob.item);
if(session->callbacks.on_data_send_callback) {
session->callbacks.on_data_send_callback
(session,
data_frame->eof ? data_frame->flags :
(data_frame->flags & (~SPDYLAY_DATA_FLAG_FIN)),
data_frame->stream_id,
session->aob.framebuflen-SPDYLAY_HEAD_LEN, session->user_data);
}
if(data_frame->eof && (data_frame->flags & SPDYLAY_DATA_FLAG_FIN)) {
spdylay_stream *stream =
spdylay_session_get_stream(session, data_frame->stream_id);
if(stream) {
spdylay_stream_shutdown(stream, SPDYLAY_SHUT_WR);
spdylay_session_close_stream_if_shut_rdwr(session, stream);
}
}
break;
};
if(type == SPDYLAY_DATA) {
int r;
/* If session is closed or RST_STREAM was queued, we won't send
further data. */
if(frame->data.eof ||
if(data_frame->eof ||
spdylay_session_predicate_data_send(session,
frame->data.stream_id) != 0) {
data_frame->stream_id) != 0) {
spdylay_active_outbound_item_reset(&session->aob);
} else {
spdylay_outbound_item* item = spdylay_session_get_next_ob_item(session);
@ -1152,7 +1171,7 @@ static int spdylay_session_after_frame_sent(spdylay_session *session)
if(item == NULL || session->aob.item->pri <= item->pri) {
size_t next_readmax;
spdylay_stream *stream;
stream = spdylay_session_get_stream(session, frame->data.stream_id);
stream = spdylay_session_get_stream(session, data_frame->stream_id);
/* Assuming stream is not NULL */
assert(stream);
next_readmax = spdylay_session_next_data_read(session, stream);
@ -1167,7 +1186,7 @@ static int spdylay_session_after_frame_sent(spdylay_session *session)
&session->aob.framebuf,
&session->aob.framebufmax,
next_readmax,
&frame->data);
data_frame);
if(r == SPDYLAY_ERR_DEFERRED) {
spdylay_stream_defer_data(stream, session->aob.item,
SPDYLAY_DEFERRED_NONE);
@ -1196,7 +1215,8 @@ static int spdylay_session_after_frame_sent(spdylay_session *session)
}
}
} else {
spdylay_active_outbound_item_reset(&session->aob);
/* Unreachable */
assert(0);
}
return 0;
}
@ -1219,17 +1239,22 @@ int spdylay_session_send(spdylay_session *session)
if(framebuflen == SPDYLAY_ERR_DEFERRED) {
continue;
} else if(framebuflen < 0) {
/* The library is responsible for the transmission of
WINDOW_UPDATE frame, so we don't call error callback for
it. */
if(session->callbacks.on_ctrl_not_send_callback &&
spdylay_is_non_fatal(framebuflen) &&
item->frame_type != SPDYLAY_WINDOW_UPDATE) {
session->callbacks.on_ctrl_not_send_callback(session,
item->frame_type,
item->frame,
framebuflen,
session->user_data);
if(item->frame_cat == SPDYLAY_CTRL &&
session->callbacks.on_ctrl_not_send_callback &&
spdylay_is_non_fatal(framebuflen)) {
/* The library is responsible for the transmission of
WINDOW_UPDATE frame, so we don't call error callback for
it. */
spdylay_frame_type frame_type;
frame_type = spdylay_outbound_item_get_ctrl_frame_type(item);
if(frame_type != SPDYLAY_WINDOW_UPDATE) {
session->callbacks.on_ctrl_not_send_callback
(session,
frame_type,
spdylay_outbound_item_get_ctrl_frame(item),
framebuflen,
session->user_data);
}
}
spdylay_outbound_item_free(item);
free(item);
@ -1242,10 +1267,17 @@ int spdylay_session_send(spdylay_session *session)
session->aob.item = item;
session->aob.framebuflen = framebuflen;
/* Call before_send callback */
if(item->frame_type != SPDYLAY_DATA &&
if(item->frame_cat == SPDYLAY_CTRL &&
session->callbacks.before_ctrl_send_callback) {
session->callbacks.before_ctrl_send_callback
(session, item->frame_type, item->frame, session->user_data);
spdylay_frame_type frame_type;
frame_type = spdylay_outbound_item_get_ctrl_frame_type(item);
if(frame_type != SPDYLAY_WINDOW_UPDATE) {
session->callbacks.before_ctrl_send_callback
(session,
frame_type,
spdylay_outbound_item_get_ctrl_frame(item),
session->user_data);
}
}
}
data = session->aob.framebuf + session->aob.framebufoff;
@ -1261,11 +1293,11 @@ int spdylay_session_send(spdylay_session *session)
} else {
session->aob.framebufoff += sentlen;
if(session->flow_control &&
session->aob.item->frame_type == SPDYLAY_DATA) {
spdylay_frame *frame;
session->aob.item->frame_cat == SPDYLAY_DATA) {
spdylay_data *frame;
spdylay_stream *stream;
frame = session->aob.item->frame;
stream = spdylay_session_get_stream(session, frame->data.stream_id);
frame = spdylay_outbound_item_get_data_frame(session->aob.item);
stream = spdylay_session_get_stream(session, frame->stream_id);
if(stream) {
stream->window_size -= spdylay_get_uint32(&session->aob.framebuf[4]);
}
@ -1753,8 +1785,7 @@ static int spdylay_session_process_ctrl_frame(spdylay_session *session)
int r = 0;
uint16_t type;
spdylay_frame frame;
memcpy(&type, &session->iframe.headbuf[2], sizeof(uint16_t));
type = ntohs(type);
type = spdylay_get_uint16(&session->iframe.headbuf[2]);
switch(type) {
case SPDYLAY_SYN_STREAM:
spdylay_buffer_reset(&session->inflatebuf);
@ -2193,7 +2224,7 @@ int spdylay_session_add_ping(spdylay_session *session, uint32_t unique_id)
return SPDYLAY_ERR_NOMEM;
}
spdylay_frame_ping_init(&frame->ping, session->version, unique_id);
r = spdylay_session_add_frame(session, SPDYLAY_PING, frame, NULL);
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
if(r != 0) {
spdylay_frame_ping_free(&frame->ping);
free(frame);
@ -2213,7 +2244,7 @@ int spdylay_session_add_goaway(spdylay_session *session,
}
spdylay_frame_goaway_init(&frame->goaway, session->version,
last_good_stream_id, status_code);
r = spdylay_session_add_frame(session, SPDYLAY_GOAWAY, frame, NULL);
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
if(r != 0) {
spdylay_frame_goaway_free(&frame->goaway);
free(frame);
@ -2233,7 +2264,7 @@ int spdylay_session_add_window_update(spdylay_session *session,
}
spdylay_frame_window_update_init(&frame->window_update, session->version,
stream_id, delta_window_size);
r = spdylay_session_add_frame(session, SPDYLAY_WINDOW_UPDATE, frame, NULL);
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
if(r != 0) {
spdylay_frame_window_update_free(&frame->window_update);
free(frame);

View File

@ -181,11 +181,14 @@ int spdylay_session_is_my_stream_id(spdylay_session *session,
int32_t stream_id);
/*
* Adds frame |frame| of type |frame_type| to the outbound queue in
* |session|. |aux_data| is a pointer to the 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 on success.
* Adds frame |frame| to the outbound queue in |session|. The
* |frame_cat| must be either SPDYLAY_CTRL or SPDYLAY_DATA. If the
* |frame_cat| is SPDYLAY_CTRL, the |frame| must be a pointer to
* spdylay_frame. If the |frame_cat| is SPDYLAY_DATA, it must be a
* pointer to spdylay_data. |aux_data| is a pointer to the arbitrary
* data. Its interpretation is defined per the type of the frame. When
* this function succeeds, it takes ownership of |frame| and
* |aux_data|, so caller must not free them on success.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@ -194,9 +197,8 @@ int spdylay_session_is_my_stream_id(spdylay_session *session,
* Out of memory.
*/
int spdylay_session_add_frame(spdylay_session *session,
spdylay_frame_type frame_type,
spdylay_frame *frame,
void *aux_data);
spdylay_frame_category frame_cat,
void *abs_frame, void *aux_data);
/*
* Adds RST_STREAM frame for the stream |stream_id| with status code

View File

@ -92,7 +92,7 @@ static int spdylay_submit_syn_stream_shared
spdylay_frame_syn_stream_init(&frame->syn_stream,
session->version, flags_copy,
0, assoc_stream_id, pri, nv_copy);
r = spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame,
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame,
aux_data);
if(r != 0) {
spdylay_frame_syn_stream_free(&frame->syn_stream);
@ -133,7 +133,7 @@ int spdylay_submit_syn_reply(spdylay_session *session, uint8_t flags,
}
spdylay_frame_syn_reply_init(&frame->syn_reply, session->version, flags_copy,
stream_id, nv_copy);
r = spdylay_session_add_frame(session, SPDYLAY_SYN_REPLY, frame, NULL);
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
if(r != 0) {
spdylay_frame_syn_reply_free(&frame->syn_reply);
free(frame);
@ -163,7 +163,7 @@ int spdylay_submit_headers(spdylay_session *session, uint8_t flags,
}
spdylay_frame_headers_init(&frame->headers, session->version, flags_copy,
stream_id, nv_copy);
r = spdylay_session_add_frame(session, SPDYLAY_HEADERS, frame, NULL);
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
if(r != 0) {
spdylay_frame_headers_free(&frame->headers);
free(frame);
@ -218,7 +218,7 @@ int spdylay_submit_settings(spdylay_session *session, uint8_t flags,
spdylay_frame_iv_sort(iv_copy, niv);
spdylay_frame_settings_init(&frame->settings, session->version,
flags, iv_copy, niv);
r = spdylay_session_add_frame(session, SPDYLAY_SETTINGS, frame, NULL);
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
if(r == 0) {
spdylay_session_update_local_settings(session, iv_copy, niv);
} else {
@ -274,7 +274,7 @@ int spdylay_submit_response(spdylay_session *session,
}
spdylay_frame_syn_reply_init(&frame->syn_reply, session->version, flags,
stream_id, nv_copy);
r = spdylay_session_add_frame(session, SPDYLAY_SYN_REPLY, frame,
r = spdylay_session_add_frame(session, SPDYLAY_CTRL, frame,
data_prd_copy);
if(r != 0) {
spdylay_frame_syn_reply_free(&frame->syn_reply);
@ -289,20 +289,20 @@ int spdylay_submit_data(spdylay_session *session, int32_t stream_id,
const spdylay_data_provider *data_prd)
{
int r;
spdylay_frame *frame;
spdylay_data *data_frame;
uint8_t nflags = 0;
frame = malloc(sizeof(spdylay_frame));
if(frame == NULL) {
data_frame = malloc(sizeof(spdylay_frame));
if(data_frame == NULL) {
return SPDYLAY_ERR_NOMEM;
}
if(flags & SPDYLAY_DATA_FLAG_FIN) {
nflags |= SPDYLAY_DATA_FLAG_FIN;
}
spdylay_frame_data_init(&frame->data, stream_id, nflags, data_prd);
r = spdylay_session_add_frame(session, SPDYLAY_DATA, frame, NULL);
spdylay_frame_data_init(data_frame, stream_id, nflags, data_prd);
r = spdylay_session_add_frame(session, SPDYLAY_DATA, data_frame, NULL);
if(r != 0) {
spdylay_frame_data_free(&frame->data);
free(frame);
spdylay_frame_data_free(data_frame);
free(data_frame);
}
return r;
}

View File

@ -33,6 +33,10 @@
#include "spdylay_session.h"
#include "spdylay_stream.h"
#define OB_CTRL(ITEM) spdylay_outbound_item_get_ctrl_frame(ITEM)
#define OB_CTRL_TYPE(ITEM) spdylay_outbound_item_get_ctrl_frame_type(ITEM)
#define OB_DATA(ITEM) spdylay_outbound_item_get_data_frame(ITEM)
typedef struct {
uint8_t buf[4096];
size_t length;
@ -260,8 +264,8 @@ void test_spdylay_session_recv(void)
CU_ASSERT(0 == spdylay_session_recv(session));
CU_ASSERT(0 == user_data.ctrl_recv_cb_called);
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(SPDYLAY_RST_STREAM == item->frame_type);
CU_ASSERT(SPDYLAY_PROTOCOL_ERROR == item->frame->rst_stream.status_code);
CU_ASSERT(SPDYLAY_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(SPDYLAY_PROTOCOL_ERROR == OB_CTRL(item)->rst_stream.status_code);
spdylay_session_del(session);
@ -282,8 +286,8 @@ void test_spdylay_session_recv(void)
CU_ASSERT(0 == spdylay_session_recv(session));
CU_ASSERT(0 == user_data.ctrl_recv_cb_called);
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(SPDYLAY_RST_STREAM == item->frame_type);
CU_ASSERT(SPDYLAY_PROTOCOL_ERROR == item->frame->rst_stream.status_code);
CU_ASSERT(SPDYLAY_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(SPDYLAY_PROTOCOL_ERROR == OB_CTRL(item)->rst_stream.status_code);
CU_ASSERT(0 == spdylay_session_send(session));
@ -302,8 +306,8 @@ void test_spdylay_session_recv(void)
CU_ASSERT(0 == spdylay_session_recv(session));
CU_ASSERT(0 == user_data.ctrl_recv_cb_called);
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(SPDYLAY_RST_STREAM == item->frame_type);
CU_ASSERT(SPDYLAY_PROTOCOL_ERROR == item->frame->rst_stream.status_code);
CU_ASSERT(SPDYLAY_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(SPDYLAY_PROTOCOL_ERROR == OB_CTRL(item)->rst_stream.status_code);
free(framedata);
free(nvbuf);
@ -342,7 +346,7 @@ void test_spdylay_session_add_frame(void)
spdylay_frame_syn_stream_init(&frame->syn_stream, SPDYLAY_PROTO_SPDY2,
SPDYLAY_CTRL_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_CTRL, frame,
aux_data));
CU_ASSERT(0 == spdylay_pq_empty(&session->ob_ss_pq));
CU_ASSERT(0 == spdylay_session_send(session));
@ -579,8 +583,8 @@ void test_spdylay_session_on_syn_reply_received(void)
CU_ASSERT(0 == spdylay_session_on_syn_reply_received(session, &frame));
CU_ASSERT(1 == user_data.invalid_ctrl_recv_cb_called);
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(SPDYLAY_RST_STREAM == item->frame_type);
CU_ASSERT(SPDYLAY_STREAM_IN_USE == item->frame->rst_stream.status_code);
CU_ASSERT(SPDYLAY_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(SPDYLAY_STREAM_IN_USE == OB_CTRL(item)->rst_stream.status_code);
spdylay_frame_syn_reply_free(&frame.syn_reply);
@ -603,7 +607,7 @@ void test_spdylay_session_send_syn_stream(void)
spdylay_session_client_new(&session, SPDYLAY_PROTO_SPDY2, &callbacks, NULL);
spdylay_frame_syn_stream_init(&frame->syn_stream, SPDYLAY_PROTO_SPDY2,
SPDYLAY_CTRL_FLAG_NONE, 0, 0, 3, dup_nv(nv));
spdylay_session_add_frame(session, SPDYLAY_SYN_STREAM, frame, aux_data);
spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, aux_data);
CU_ASSERT(0 == spdylay_session_send(session));
stream = spdylay_session_get_stream(session, 1);
CU_ASSERT(SPDYLAY_STREAM_OPENING == stream->state);
@ -628,7 +632,7 @@ void test_spdylay_session_send_syn_reply(void)
SPDYLAY_STREAM_OPENING, NULL);
spdylay_frame_syn_reply_init(&frame->syn_reply, SPDYLAY_PROTO_SPDY2,
SPDYLAY_CTRL_FLAG_NONE, 2, dup_nv(nv));
spdylay_session_add_frame(session, SPDYLAY_SYN_REPLY, frame, NULL);
spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
CU_ASSERT(0 == spdylay_session_send(session));
stream = spdylay_session_get_stream(session, 2);
CU_ASSERT(SPDYLAY_STREAM_OPENED == stream->state);
@ -657,7 +661,7 @@ void test_spdylay_submit_response(void)
SPDYLAY_STREAM_OPENING, NULL);
CU_ASSERT(0 == spdylay_submit_response(session, stream_id, nv, &data_prd));
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(0 == strcmp("content-length", item->frame->syn_reply.nv[0]));
CU_ASSERT(0 == strcmp("content-length", OB_CTRL(item)->syn_reply.nv[0]));
CU_ASSERT(0 == spdylay_session_send(session));
spdylay_session_del(session);
}
@ -683,8 +687,8 @@ void test_spdylay_submit_response_with_null_data_read_callback(void)
SPDYLAY_STREAM_OPENING, NULL);
CU_ASSERT(0 == spdylay_submit_response(session, 1, nv, &data_prd));
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(0 == strcmp(":version", item->frame->syn_reply.nv[0]));
CU_ASSERT(item->frame->syn_reply.hd.flags & SPDYLAY_CTRL_FLAG_FIN);
CU_ASSERT(0 == strcmp(":version", OB_CTRL(item)->syn_reply.nv[0]));
CU_ASSERT(OB_CTRL(item)->syn_reply.hd.flags & SPDYLAY_CTRL_FLAG_FIN);
CU_ASSERT(0 == spdylay_session_send(session));
CU_ASSERT(0 == spdylay_frame_unpack_syn_reply(&frame.syn_reply,
@ -719,7 +723,7 @@ void test_spdylay_submit_request_with_data(void)
&callbacks, &ud));
CU_ASSERT(0 == spdylay_submit_request(session, 3, nv, &data_prd, NULL));
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(0 == strcmp("version", item->frame->syn_stream.nv[0]));
CU_ASSERT(0 == strcmp("version", OB_CTRL(item)->syn_stream.nv[0]));
CU_ASSERT(0 == spdylay_session_send(session));
CU_ASSERT(0 == ud.data_source_length);
@ -745,8 +749,8 @@ void test_spdylay_submit_request_with_null_data_read_callback(void)
&callbacks, &ud));
CU_ASSERT(0 == spdylay_submit_request(session, 3, nv, &data_prd, NULL));
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(0 == strcmp(":version", item->frame->syn_stream.nv[0]));
CU_ASSERT(item->frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN);
CU_ASSERT(0 == strcmp(":version", OB_CTRL(item)->syn_stream.nv[0]));
CU_ASSERT(OB_CTRL(item)->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN);
CU_ASSERT(0 == spdylay_session_send(session));
CU_ASSERT(0 == spdylay_frame_unpack_syn_stream(&frame.syn_stream,
@ -776,11 +780,11 @@ void test_spdylay_submit_syn_stream(void)
CU_ASSERT(0 == spdylay_submit_syn_stream(session, SPDYLAY_CTRL_FLAG_FIN, 1, 3,
nv, NULL));
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(0 == strcmp("version", item->frame->syn_stream.nv[0]));
CU_ASSERT(SPDYLAY_CTRL_FLAG_FIN == item->frame->syn_stream.hd.flags);
CU_ASSERT(0 == strcmp("version", OB_CTRL(item)->syn_stream.nv[0]));
CU_ASSERT(SPDYLAY_CTRL_FLAG_FIN == OB_CTRL(item)->syn_stream.hd.flags);
/* See assoc-stream-ID is ignored */
CU_ASSERT(0 == item->frame->syn_stream.assoc_stream_id);
CU_ASSERT(3 == item->frame->syn_stream.pri);
CU_ASSERT(0 == OB_CTRL(item)->syn_stream.assoc_stream_id);
CU_ASSERT(3 == OB_CTRL(item)->syn_stream.pri);
spdylay_session_del(session);
@ -789,10 +793,10 @@ void test_spdylay_submit_syn_stream(void)
CU_ASSERT(0 == spdylay_submit_syn_stream(session, SPDYLAY_CTRL_FLAG_FIN, 1, 3,
nv, NULL));
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(0 == strcmp("version", item->frame->syn_stream.nv[0]));
CU_ASSERT(SPDYLAY_CTRL_FLAG_FIN == item->frame->syn_stream.hd.flags);
CU_ASSERT(1 == item->frame->syn_stream.assoc_stream_id);
CU_ASSERT(3 == item->frame->syn_stream.pri);
CU_ASSERT(0 == strcmp("version", OB_CTRL(item)->syn_stream.nv[0]));
CU_ASSERT(SPDYLAY_CTRL_FLAG_FIN == OB_CTRL(item)->syn_stream.hd.flags);
CU_ASSERT(1 == OB_CTRL(item)->syn_stream.assoc_stream_id);
CU_ASSERT(3 == OB_CTRL(item)->syn_stream.pri);
/* Invalid assoc-stream-ID */
CU_ASSERT(SPDYLAY_ERR_INVALID_ARGUMENT ==
@ -820,8 +824,8 @@ void test_spdylay_submit_syn_reply(void)
CU_ASSERT(0 == spdylay_submit_syn_reply(session, SPDYLAY_CTRL_FLAG_FIN, 1,
nv));
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(0 == strcmp("version", item->frame->syn_reply.nv[0]));
CU_ASSERT(SPDYLAY_CTRL_FLAG_FIN == item->frame->syn_reply.hd.flags);
CU_ASSERT(0 == strcmp("version", OB_CTRL(item)->syn_reply.nv[0]));
CU_ASSERT(SPDYLAY_CTRL_FLAG_FIN == OB_CTRL(item)->syn_reply.hd.flags);
ud.ctrl_send_cb_called = 0;
ud.sent_frame_type = 0;
@ -862,8 +866,8 @@ void test_spdylay_submit_headers(void)
&callbacks, &ud));
CU_ASSERT(0 == spdylay_submit_headers(session, SPDYLAY_CTRL_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_CTRL_FLAG_FIN == item->frame->headers.hd.flags);
CU_ASSERT(0 == strcmp(":version", OB_CTRL(item)->headers.nv[0]));
CU_ASSERT(SPDYLAY_CTRL_FLAG_FIN == OB_CTRL(item)->headers.hd.flags);
ud.ctrl_send_cb_called = 0;
ud.sent_frame_type = 0;
@ -1009,6 +1013,7 @@ void test_spdylay_session_on_window_update_received(void)
data_item = malloc(sizeof(spdylay_outbound_item));
memset(data_item, 0, sizeof(spdylay_outbound_item));
data_item->frame_cat = SPDYLAY_DATA;
spdylay_stream_defer_data(stream, data_item, SPDYLAY_DEFERRED_FLOW_CONTROL);
CU_ASSERT(0 == spdylay_session_on_window_update_received(session, &frame));
@ -1043,8 +1048,8 @@ void test_spdylay_session_on_ping_received(void)
CU_ASSERT(0 == spdylay_session_on_ping_received(session, &frame));
CU_ASSERT(1 == user_data.ctrl_recv_cb_called);
top = spdylay_session_get_ob_pq_top(session);
CU_ASSERT(SPDYLAY_PING == top->frame_type);
CU_ASSERT(unique_id == top->frame->ping.unique_id);
CU_ASSERT(SPDYLAY_PING == OB_CTRL_TYPE(top));
CU_ASSERT(unique_id == OB_CTRL(top)->ping.unique_id);
session->last_ping_unique_id = 1;
frame.ping.unique_id = 1;
@ -1127,8 +1132,8 @@ void test_spdylay_session_on_data_received(void)
SPDYLAY_DATA_FLAG_NONE,
4096, stream_id));
top = spdylay_session_get_ob_pq_top(session);
CU_ASSERT(SPDYLAY_RST_STREAM == top->frame_type);
CU_ASSERT(SPDYLAY_INVALID_STREAM == top->frame->rst_stream.status_code);
CU_ASSERT(SPDYLAY_RST_STREAM == OB_CTRL_TYPE(top));
CU_ASSERT(SPDYLAY_INVALID_STREAM == OB_CTRL(top)->rst_stream.status_code);
spdylay_session_del(session);
}
@ -1212,7 +1217,7 @@ void test_spdylay_session_send_rst_stream(void)
frame = malloc(sizeof(spdylay_frame));
spdylay_frame_rst_stream_init(&frame->rst_stream, SPDYLAY_PROTO_SPDY2, 1,
SPDYLAY_CANCEL);
spdylay_session_add_frame(session, SPDYLAY_RST_STREAM, frame, NULL);
spdylay_session_add_frame(session, SPDYLAY_CTRL, frame, NULL);
CU_ASSERT(0 == spdylay_session_send(session));
CU_ASSERT(NULL == spdylay_session_get_stream(session, 1));
@ -1236,11 +1241,11 @@ void test_spdylay_session_get_next_ob_item(void)
CU_ASSERT(NULL == spdylay_session_get_next_ob_item(session));
spdylay_submit_ping(session);
CU_ASSERT(SPDYLAY_PING ==
spdylay_session_get_next_ob_item(session)->frame_type);
OB_CTRL_TYPE(spdylay_session_get_next_ob_item(session)));
spdylay_submit_request(session, 0, nv, NULL, NULL);
CU_ASSERT(SPDYLAY_PING ==
spdylay_session_get_next_ob_item(session)->frame_type);
OB_CTRL_TYPE(spdylay_session_get_next_ob_item(session)));
CU_ASSERT(0 == spdylay_session_send(session));
CU_ASSERT(NULL == spdylay_session_get_next_ob_item(session));
@ -1253,12 +1258,12 @@ void test_spdylay_session_get_next_ob_item(void)
spdylay_submit_response(session, 1, nv, NULL);
CU_ASSERT(SPDYLAY_SYN_REPLY ==
spdylay_session_get_next_ob_item(session)->frame_type);
OB_CTRL_TYPE(spdylay_session_get_next_ob_item(session)));
session->local_settings[SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS] = 3;
CU_ASSERT(SPDYLAY_SYN_STREAM ==
spdylay_session_get_next_ob_item(session)->frame_type);
OB_CTRL_TYPE(spdylay_session_get_next_ob_item(session)));
spdylay_session_del(session);
}
@ -1280,12 +1285,12 @@ void test_spdylay_session_pop_next_ob_item(void)
spdylay_submit_request(session, 0, nv, NULL, NULL);
item = spdylay_session_pop_next_ob_item(session);
CU_ASSERT(SPDYLAY_PING == item->frame_type);
CU_ASSERT(SPDYLAY_PING == OB_CTRL_TYPE(item));
spdylay_outbound_item_free(item);
free(item);
item = spdylay_session_pop_next_ob_item(session);
CU_ASSERT(SPDYLAY_SYN_STREAM == item->frame_type);
CU_ASSERT(SPDYLAY_SYN_STREAM == OB_CTRL_TYPE(item));
spdylay_outbound_item_free(item);
free(item);
@ -1298,7 +1303,7 @@ void test_spdylay_session_pop_next_ob_item(void)
spdylay_submit_response(session, 1, nv, NULL);
item = spdylay_session_pop_next_ob_item(session);
CU_ASSERT(SPDYLAY_SYN_REPLY == item->frame_type);
CU_ASSERT(SPDYLAY_SYN_REPLY == OB_CTRL_TYPE(item));
spdylay_outbound_item_free(item);
free(item);
@ -1308,7 +1313,7 @@ void test_spdylay_session_pop_next_ob_item(void)
session->local_settings[SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS] = 2;
item = spdylay_session_pop_next_ob_item(session);
CU_ASSERT(SPDYLAY_SYN_STREAM == item->frame_type);
CU_ASSERT(SPDYLAY_SYN_STREAM == OB_CTRL_TYPE(item));
spdylay_outbound_item_free(item);
free(item);
@ -1425,8 +1430,8 @@ void test_spdylay_session_max_concurrent_streams(void)
CU_ASSERT(0 == spdylay_session_on_syn_stream_received(session, &frame));
item = spdylay_session_get_ob_pq_top(session);
CU_ASSERT(SPDYLAY_RST_STREAM == item->frame_type);
CU_ASSERT(SPDYLAY_REFUSED_STREAM == item->frame->rst_stream.status_code)
CU_ASSERT(SPDYLAY_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(SPDYLAY_REFUSED_STREAM == OB_CTRL(item)->rst_stream.status_code)
spdylay_frame_syn_stream_free(&frame.syn_stream);
@ -1668,7 +1673,7 @@ void test_spdylay_session_defer_data(void)
/* Resume deferred DATA */
CU_ASSERT(0 == spdylay_session_resume_data(session, 1));
item = spdylay_session_get_ob_pq_top(session);
item->frame->data.data_prd.read_callback =
OB_DATA(item)->data_prd.read_callback =
fixed_length_data_source_read_callback;
ud.block_count = 1;
/* Reads 2 4KiB blocks */
@ -1676,7 +1681,7 @@ void test_spdylay_session_defer_data(void)
CU_ASSERT(ud.data_source_length == 8*1024);
/* Deferred again */
item->frame->data.data_prd.read_callback = defer_data_source_read_callback;
OB_DATA(item)->data_prd.read_callback = defer_data_source_read_callback;
/* This is needed since 4KiB block is already read and waiting to be
sent. No read_callback invocation. */
ud.block_count = 1;
@ -1687,7 +1692,7 @@ void test_spdylay_session_defer_data(void)
CU_ASSERT(0 == spdylay_session_resume_data(session, 1));
item = spdylay_session_get_ob_pq_top(session);
item->frame->data.data_prd.read_callback =
OB_DATA(item)->data_prd.read_callback =
fixed_length_data_source_read_callback;
ud.block_count = 1;
/* Reads 2 4KiB blocks */
@ -2014,7 +2019,7 @@ void test_spdylay_submit_settings(void)
item = spdylay_session_get_next_ob_item(session);
CU_ASSERT(SPDYLAY_SETTINGS == item->frame_type);
CU_ASSERT(SPDYLAY_SETTINGS == OB_CTRL_TYPE(item));
frame = item->frame;
CU_ASSERT(2 == frame->settings.niv);