Added function to pack and unpack WINDOW_UPDATE frame.

This commit is contained in:
Tatsuhiro Tsujikawa 2012-02-25 01:47:37 +09:00
parent 895562a15b
commit 4e62c75b02
6 changed files with 131 additions and 3 deletions

View File

@ -73,6 +73,8 @@ typedef enum {
SPDYLAY_PING = 6,
SPDYLAY_GOAWAY = 7,
SPDYLAY_HEADERS = 8,
/* Since SPDY/3 */
SPDYLAY_WINDOW_UPDATE = 9,
SPDYLAY_DATA = 100,
} spdylay_frame_type;
@ -143,7 +145,7 @@ typedef struct {
SPDYLAY_SPDY3_LOWEST_PRI (loweset), depending on the protocol
version. */
uint8_t pri;
/* Use in spdy/3 only */
/* Since SPDY/3 */
uint8_t slot;
char **nv;
} spdylay_syn_stream;
@ -187,10 +189,17 @@ typedef struct {
typedef struct {
spdylay_ctrl_hd hd;
int32_t last_good_stream_id;
/* spdy/3 only */
/* Since SPDY/3 */
uint32_t status_code;
} spdylay_goaway;
/* WINDOW_UPDATE is introduced since SPDY/3 */
typedef struct {
spdylay_ctrl_hd hd;
int32_t stream_id;
int32_t delta_window_size;
} spdylay_window_update;
typedef union {
int fd;
void *ptr;
@ -237,6 +246,8 @@ typedef union {
spdylay_ping ping;
spdylay_goaway goaway;
spdylay_headers headers;
/* Since SPDY/3 */
spdylay_window_update window_update;
spdylay_data data;
} spdylay_frame;

View File

@ -495,6 +495,23 @@ void spdylay_frame_rst_stream_init(spdylay_rst_stream *frame,
void spdylay_frame_rst_stream_free(spdylay_rst_stream *frame)
{}
void spdylay_frame_window_update_init(spdylay_window_update *frame,
uint16_t version,
int32_t stream_id,
int32_t delta_window_size)
{
memset(frame, 0, sizeof(spdylay_window_update));
frame->hd.version = version;
frame->hd.type = SPDYLAY_WINDOW_UPDATE;
frame->hd.flags = 0;
frame->hd.length = 8;
frame->stream_id = stream_id;
frame->delta_window_size = delta_window_size;
}
void spdylay_frame_window_update_free(spdylay_window_update *frame)
{}
void spdylay_frame_settings_init(spdylay_settings *frame,
uint16_t version, uint8_t flags,
spdylay_settings_entry *iv, size_t niv)
@ -823,6 +840,37 @@ int spdylay_frame_unpack_rst_stream(spdylay_rst_stream *frame,
return 0;
}
ssize_t spdylay_frame_pack_window_update(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_window_update *frame)
{
ssize_t framelen = 16;
int r;
r = spdylay_reserve_buffer(buf_ptr, buflen_ptr, framelen);
if(r != 0) {
return r;
}
memset(*buf_ptr, 0, framelen);
spdylay_frame_pack_ctrl_hd(*buf_ptr, &frame->hd);
spdylay_put_uint32be(&(*buf_ptr)[8], frame->stream_id);
spdylay_put_uint32be(&(*buf_ptr)[12], frame->delta_window_size);
return framelen;
}
int spdylay_frame_unpack_window_update(spdylay_window_update *frame,
const uint8_t *head, size_t headlen,
const uint8_t *payload,
size_t payloadlen)
{
if(payloadlen != 8) {
return SPDYLAY_ERR_INVALID_FRAME;
}
spdylay_frame_unpack_ctrl_hd(&frame->hd, head);
frame->stream_id = spdylay_get_uint32(payload) & SPDYLAY_STREAM_ID_MASK;
frame->delta_window_size = spdylay_get_uint32(&payload[4]) &
SPDYLAY_DELTA_WINDOW_SIZE_MASK;
return 0;
}
ssize_t spdylay_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_settings *frame)
{

View File

@ -36,6 +36,7 @@
#define SPDYLAY_STREAM_ID_MASK 0x7fffffff
#define SPDYLAY_LENGTH_MASK 0xffffff
#define SPDYLAY_VERSION_MASK 0x7fff
#define SPDYLAY_DELTA_WINDOW_SIZE_MASK 0x7fffffff
/* The length of DATA frame payload. */
#define SPDYLAY_DATA_PAYLOAD_LENGTH 4096
@ -287,7 +288,7 @@ int spdylay_frame_unpack_headers(spdylay_headers *frame,
* Packs RST_STREAM frame |frame| in wire frame format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|. In spdy/2 spc, RST_STREAM wire format is always 16
* given |frame|. In spdy/2 spec, RST_STREAM wire format is always 16
* bytes long.
*
* This function returns the size of packed frame if it succeeds, or
@ -312,6 +313,37 @@ int spdylay_frame_unpack_rst_stream(spdylay_rst_stream *frame,
const uint8_t *head, size_t headlen,
const uint8_t *payload, size_t payloadlen);
/*
* Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
* in |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|. In SPDY/3 spec, WINDOW_UPDATE wire format is always 16
* bytes long.
*
* This function returns the size of packed frame if it succeeds, or
* returns one of the following negative error codes:
*
* SPDYLAY_ERR_NOMEM
* Out of memory.
*/
ssize_t spdylay_frame_pack_window_update(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_window_update *frame);
/*
* Unpacks WINDOW_UPDATE frame byte sequence into |frame|.
*
* This function returns 0 if it succeeds or one of the following
* negative error codes:
*
* SPDYLAY_ERR_INVALID_FRAME
* The input data are invalid.
*/
int spdylay_frame_unpack_window_update(spdylay_window_update *frame,
const uint8_t *head, size_t headlen,
const uint8_t *payload,
size_t payloadlen);
/*
* Packs SETTINGS frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
@ -448,6 +480,13 @@ void spdylay_frame_rst_stream_init(spdylay_rst_stream *frame,
void spdylay_frame_rst_stream_free(spdylay_rst_stream *frame);
void spdylay_frame_window_update_init(spdylay_window_update *frame,
uint16_t version,
int32_t stream_id,
int32_t delta_window_size);
void spdylay_frame_window_update_free(spdylay_window_update *frame);
/*
* Initializes SETTINGS frame |frame| with given values. |frame| takes
* ownership of |iv|, so caller must not free it.

View File

@ -145,6 +145,8 @@ int main(int argc, char* argv[])
test_spdylay_frame_pack_syn_reply) ||
!CU_add_test(pSuite, "frame_pack_headers",
test_spdylay_frame_pack_headers) ||
!CU_add_test(pSuite, "frame_pack_window_update",
test_spdylay_frame_pack_window_update) ||
!CU_add_test(pSuite, "frame_pack_settings",
test_spdylay_frame_pack_settings) ||
!CU_add_test(pSuite, "frame_nv_sort", test_spdylay_frame_nv_sort) ||

View File

@ -384,6 +384,33 @@ void test_spdylay_frame_pack_headers()
test_spdylay_frame_pack_headers_with(SPDYLAY_PROTO_SPDY3);
}
void test_spdylay_frame_pack_window_update()
{
spdylay_frame frame, oframe;
uint8_t *buf = NULL;
size_t buflen = 0;
ssize_t framelen;
spdylay_frame_window_update_init(&frame.window_update, SPDYLAY_PROTO_SPDY3,
1000000007, 4096);
framelen = spdylay_frame_pack_window_update(&buf, &buflen,
&frame.window_update);
CU_ASSERT(0 == spdylay_frame_unpack_window_update
(&oframe.window_update,
&buf[0], SPDYLAY_FRAME_HEAD_LENGTH,
&buf[SPDYLAY_FRAME_HEAD_LENGTH],
framelen-SPDYLAY_FRAME_HEAD_LENGTH));
CU_ASSERT(1000000007 == oframe.window_update.stream_id);
CU_ASSERT(4096 == oframe.window_update.delta_window_size);
CU_ASSERT(SPDYLAY_PROTO_SPDY3 == oframe.headers.hd.version);
CU_ASSERT(SPDYLAY_WINDOW_UPDATE == oframe.headers.hd.type);
CU_ASSERT(SPDYLAY_CTRL_FLAG_NONE == oframe.headers.hd.flags);
CU_ASSERT(framelen-SPDYLAY_FRAME_HEAD_LENGTH == oframe.ping.hd.length);
free(buf);
spdylay_frame_window_update_free(&oframe.window_update);
spdylay_frame_window_update_free(&frame.window_update);
}
void test_spdylay_frame_pack_settings()
{
spdylay_frame frame, oframe;

View File

@ -34,6 +34,7 @@ void test_spdylay_frame_pack_goaway();
void test_spdylay_frame_pack_syn_stream();
void test_spdylay_frame_pack_syn_reply();
void test_spdylay_frame_pack_headers();
void test_spdylay_frame_pack_window_update();
void test_spdylay_frame_pack_settings();
void test_spdylay_frame_nv_sort();
void test_spdylay_frame_nv_downcase();