From ba56ed6c480f0b6a83a85131fc3ec0594ec11240 Mon Sep 17 00:00:00 2001 From: Tatsuhiro Tsujikawa Date: Thu, 29 Mar 2012 23:59:51 +0900 Subject: [PATCH] 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. --- lib/includes/spdylay/spdylay.h | 55 +-- lib/spdylay_frame.h | 32 ++ lib/spdylay_outbound_item.c | 78 ++-- lib/spdylay_outbound_item.h | 12 +- lib/spdylay_session.c | 749 +++++++++++++++++---------------- lib/spdylay_session.h | 18 +- lib/spdylay_submit.c | 24 +- tests/spdylay_session_test.c | 101 ++--- 8 files changed, 572 insertions(+), 497 deletions(-) diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index 29cf85f2..aee40381 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -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; /** diff --git a/lib/spdylay_frame.h b/lib/spdylay_frame.h index b03467a5..da8dce0e 100644 --- a/lib/spdylay_frame.h +++ b/lib/spdylay_frame.h @@ -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, diff --git a/lib/spdylay_outbound_item.c b/lib/spdylay_outbound_item.c index 3ff7c4b5..41154581 100644 --- a/lib/spdylay_outbound_item.c +++ b/lib/spdylay_outbound_item.c @@ -24,44 +24,56 @@ */ #include "spdylay_outbound_item.h" +#include + 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); diff --git a/lib/spdylay_outbound_item.h b/lib/spdylay_outbound_item.h index ad4475d3..5b85010c 100644 --- a/lib/spdylay_outbound_item.h +++ b/lib/spdylay_outbound_item.h @@ -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 */ diff --git a/lib/spdylay_session.c b/lib/spdylay_session.c index 6c2c207c..e5aa05d5 100644 --- a/lib/spdylay_session.c +++ b/lib/spdylay_session.c @@ -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); diff --git a/lib/spdylay_session.h b/lib/spdylay_session.h index 589e6893..f3f280c7 100644 --- a/lib/spdylay_session.h +++ b/lib/spdylay_session.h @@ -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 diff --git a/lib/spdylay_submit.c b/lib/spdylay_submit.c index d58e985d..0a5fcc37 100644 --- a/lib/spdylay_submit.c +++ b/lib/spdylay_submit.c @@ -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; } diff --git a/tests/spdylay_session_test.c b/tests/spdylay_session_test.c index 88c1898f..228b9150 100644 --- a/tests/spdylay_session_test.c +++ b/tests/spdylay_session_test.c @@ -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);