diff --git a/lib/includes/spdylay/spdylay.h b/lib/includes/spdylay/spdylay.h index b29b4980..5be8b81b 100644 --- a/lib/includes/spdylay/spdylay.h +++ b/lib/includes/spdylay/spdylay.h @@ -63,6 +63,7 @@ typedef enum { SPDYLAY_NOOP = 5, SPDYLAY_PING = 6, SPDYLAY_GOAWAY = 7, + SPDYLAY_HEADERS = 8, SPDYLAY_DATA = 100, } spdylay_frame_type; @@ -104,6 +105,12 @@ typedef struct { char **nv; } spdylay_syn_reply; +typedef struct { + spdylay_ctrl_hd hd; + int32_t stream_id; + char **nv; +} spdylay_headers; + typedef struct { spdylay_ctrl_hd hd; int32_t stream_id; @@ -134,6 +141,7 @@ typedef union { spdylay_syn_stream syn_stream; spdylay_syn_reply syn_reply; spdylay_rst_stream rst_stream; + spdylay_headers headers; spdylay_data data; } spdylay_frame; diff --git a/lib/spdylay_frame.c b/lib/spdylay_frame.c index 2fb56c14..4b9d04fd 100644 --- a/lib/spdylay_frame.c +++ b/lib/spdylay_frame.c @@ -374,6 +374,23 @@ void spdylay_frame_syn_reply_free(spdylay_syn_reply *frame) free(frame->nv); } +void spdylay_frame_headers_init(spdylay_headers *frame, uint8_t flags, + int32_t stream_id, char **nv) +{ + memset(frame, 0, sizeof(spdylay_headers)); + frame->hd.version = 2; + frame->hd.type = SPDYLAY_HEADERS; + frame->hd.flags = flags; + frame->stream_id = stream_id; + frame->nv = nv; +} + +void spdylay_frame_headers_free(spdylay_headers *frame) +{ + spdylay_frame_nv_free(frame->nv); + free(frame->nv); +} + void spdylay_frame_rst_stream_init(spdylay_rst_stream *frame, int32_t stream_id, uint32_t status_code) { @@ -472,6 +489,39 @@ int spdylay_frame_unpack_syn_reply(spdylay_syn_reply *frame, return r; } +#define SPDYLAY_HEADERS_NV_OFFSET 14 + +ssize_t spdylay_frame_pack_headers(uint8_t **buf_ptr, + spdylay_headers *frame, + spdylay_zlib *deflater) +{ + uint8_t *framebuf = NULL; + ssize_t framelen; + framelen = spdylay_frame_alloc_pack_nv(&framebuf, frame->nv, + SPDYLAY_HEADERS_NV_OFFSET, deflater); + if(framelen < 0) { + return framelen; + } + frame->hd.length = framelen-SPDYLAY_FRAME_HEAD_LENGTH; + memset(framebuf, 0, SPDYLAY_HEADERS_NV_OFFSET); + spdylay_frame_pack_ctrl_hd(framebuf, &frame->hd); + spdylay_put_uint32be(&framebuf[8], frame->stream_id); + *buf_ptr = framebuf; + return framelen; +} + +int spdylay_frame_unpack_headers(spdylay_headers *frame, + const uint8_t *head, size_t headlen, + const uint8_t *payload, size_t payloadlen, + spdylay_zlib *inflater) +{ + int r; + spdylay_frame_unpack_ctrl_hd(&frame->hd, head); + frame->stream_id = spdylay_get_uint32(payload) & SPDYLAY_STREAM_ID_MASK; + r = spdylay_frame_alloc_unpack_nv(&frame->nv, payload+6, payloadlen-6, + inflater); +} + ssize_t spdylay_frame_pack_rst_stream(uint8_t **buf_ptr, spdylay_rst_stream *frame) { diff --git a/lib/spdylay_frame.h b/lib/spdylay_frame.h index e56a0f2c..fef58790 100644 --- a/lib/spdylay_frame.h +++ b/lib/spdylay_frame.h @@ -39,6 +39,9 @@ #define SPDYLAY_DATA_FRAME_LENGTH 4096 +/* The number of bytes of frame header. */ +#define SPDYLAY_FRAME_HEAD_LENGTH 8 + /* * Packs SYN_STREAM frame |frame| in wire frame format and store it in * |*buf_ptr|. This function allocates enough memory to store given @@ -82,6 +85,25 @@ int spdylay_frame_unpack_syn_reply(spdylay_syn_reply *frame, const uint8_t *payload, size_t payloadlen, spdylay_zlib *inflater); +/* + * Packs HEADERS frame |frame| in wire format and store it in + * |*buf_ptr|. This function allocates enough memory in |*buf_ptr| to + * store given |frame|. This function returns the size of packed frame + * it it succeeds, or returns negative error code. frame->hd.length is + * assigned after length is determined during packing process. + */ +ssize_t spdylay_frame_pack_headers(uint8_t **buf_ptr, + spdylay_headers *frame, + spdylay_zlib *deflater); + +/* + * Unpacks HEADERS wire format into |frame|. This function returns 0 + * if it succeeds or negative error code. + */ +int spdylay_frame_unpack_headers(spdylay_headers *frame, + const uint8_t *head, size_t headlen, + const uint8_t *payload, size_t payloadlen, + spdylay_zlib *inflater); /* * Packs RST_STREAM frame |frame| in wire frame format and store it in * |*buf_ptr|. This function allocates enough memory to store given @@ -138,6 +160,11 @@ void spdylay_frame_syn_reply_init(spdylay_syn_reply *frame, uint8_t flags, void spdylay_frame_syn_reply_free(spdylay_syn_reply *frame); +void spdylay_frame_headers_init(spdylay_headers *frame, uint8_t flags, + int32_t stream_id, char **nv); + +void spdylay_frame_headers_free(spdylay_headers *frame); + void spdylay_frame_rst_stream_init(spdylay_rst_stream *frame, int32_t stream_id, uint32_t status_code); diff --git a/tests/main.c b/tests/main.c index 86f93d32..5afa6687 100644 --- a/tests/main.c +++ b/tests/main.c @@ -84,7 +84,9 @@ int main() test_spdylay_session_reply_fail) || !CU_add_test(pSuite, "frame_unpack_nv", test_spdylay_frame_unpack_nv) || !CU_add_test(pSuite, "frame_count_nv_space", - test_spdylay_frame_count_nv_space)) { + test_spdylay_frame_count_nv_space) || + !CU_add_test(pSuite, "frame_pack_headers", + test_spdylay_frame_pack_headers)) { CU_cleanup_registry(); return CU_get_error(); } diff --git a/tests/spdylay_frame_test.c b/tests/spdylay_frame_test.c index 9a7174c3..f24c42e8 100644 --- a/tests/spdylay_frame_test.c +++ b/tests/spdylay_frame_test.c @@ -53,3 +53,26 @@ void test_spdylay_frame_count_nv_space() CU_ASSERT(83 == spdylay_frame_count_nv_space((char**)headers)); } +void test_spdylay_frame_pack_headers() +{ + spdylay_zlib deflater, inflater; + spdylay_frame frame, oframe; + uint8_t *buf; + ssize_t buflen; + spdylay_zlib_deflate_hd_init(&deflater); + spdylay_zlib_inflate_hd_init(&inflater); + spdylay_frame_headers_init(&frame.headers, SPDYLAY_FLAG_FIN, 3, + spdylay_frame_nv_copy(headers)); + buflen = spdylay_frame_pack_headers(&buf, &frame.headers, &deflater); + CU_ASSERT(0 == spdylay_frame_unpack_headers + (&oframe.headers, + &buf[0], SPDYLAY_FRAME_HEAD_LENGTH, + &buf[SPDYLAY_FRAME_HEAD_LENGTH], + buflen-SPDYLAY_FRAME_HEAD_LENGTH, + &inflater)); + free(buf); + spdylay_frame_headers_free(&oframe.headers); + spdylay_frame_headers_free(&frame.headers); + spdylay_zlib_inflate_free(&inflater); + spdylay_zlib_deflate_free(&deflater); +} diff --git a/tests/spdylay_frame_test.h b/tests/spdylay_frame_test.h index f5397457..51097891 100644 --- a/tests/spdylay_frame_test.h +++ b/tests/spdylay_frame_test.h @@ -27,5 +27,6 @@ void test_spdylay_frame_unpack_nv(); void test_spdylay_frame_count_nv_space(); +void test_spdylay_frame_pack_headers(); #endif /* SPDYLAY_FRAME_TEST_H */