Reuse buffers when packing frames.

Temporal name/value buffer will be shared by unpacking frame.
This commit is contained in:
Tatsuhiro Tsujikawa 2012-02-16 20:54:30 +09:00
parent e4ad446261
commit 050f33e8f9
8 changed files with 313 additions and 170 deletions

View File

@ -63,27 +63,35 @@ static void spdylay_frame_unpack_ctrl_hd(spdylay_ctrl_hd *hd,
} }
static ssize_t spdylay_frame_alloc_pack_nv(uint8_t **buf_ptr, static ssize_t spdylay_frame_alloc_pack_nv(uint8_t **buf_ptr,
size_t *buflen_ptr,
uint8_t **nvbuf_ptr,
size_t *nvbuflen_ptr,
char **nv, size_t nv_offset, char **nv, size_t nv_offset,
spdylay_zlib *deflater) spdylay_zlib *deflater)
{ {
size_t nvbuflen = spdylay_frame_count_nv_space(nv); size_t nvspace;
uint8_t *nvbuf = malloc(nvbuflen); size_t maxframelen;
size_t maxframelen = nv_offset+
spdylay_zlib_deflate_hd_bound(deflater, nvbuflen);
uint8_t *framebuf = malloc(maxframelen);
ssize_t framelen; ssize_t framelen;
spdylay_frame_pack_nv(nvbuf, nv); int r;
nvspace = spdylay_frame_count_nv_space(nv);
r = spdylay_reserve_buffer(nvbuf_ptr, nvbuflen_ptr, nvspace);
if(r != 0) {
return SPDYLAY_ERR_NOMEM;
}
maxframelen = nv_offset+spdylay_zlib_deflate_hd_bound(deflater, nvspace);
r = spdylay_reserve_buffer(buf_ptr, buflen_ptr, maxframelen);
if(r != 0) {
return SPDYLAY_ERR_NOMEM;
}
spdylay_frame_pack_nv(*nvbuf_ptr, nv);
framelen = spdylay_zlib_deflate_hd(deflater, framelen = spdylay_zlib_deflate_hd(deflater,
framebuf+nv_offset, (*buf_ptr)+nv_offset,
maxframelen-nv_offset, maxframelen-nv_offset,
nvbuf, nvbuflen); *nvbuf_ptr, nvspace);
free(nvbuf);
if(framelen < 0) { if(framelen < 0) {
free(framebuf);
return framelen; return framelen;
} }
framelen += nv_offset; framelen += nv_offset;
*buf_ptr = framebuf;
return framelen; return framelen;
} }
@ -451,26 +459,28 @@ void spdylay_frame_data_free(spdylay_data *frame)
#define SPDYLAY_SYN_STREAM_NV_OFFSET 18 #define SPDYLAY_SYN_STREAM_NV_OFFSET 18
ssize_t spdylay_frame_pack_syn_stream(uint8_t **buf_ptr, ssize_t spdylay_frame_pack_syn_stream(uint8_t **buf_ptr,
size_t *buflen_ptr,
uint8_t **nvbuf_ptr,
size_t *nvbuflen_ptr,
spdylay_syn_stream *frame, spdylay_syn_stream *frame,
spdylay_zlib *deflater) spdylay_zlib *deflater)
{ {
uint8_t *framebuf = NULL;
ssize_t framelen; ssize_t framelen;
framelen = spdylay_frame_alloc_pack_nv(&framebuf, frame->nv, framelen = spdylay_frame_alloc_pack_nv(buf_ptr, buflen_ptr,
nvbuf_ptr, nvbuflen_ptr,
frame->nv,
SPDYLAY_SYN_STREAM_NV_OFFSET, SPDYLAY_SYN_STREAM_NV_OFFSET,
deflater); deflater);
if(framelen < 0) { if(framelen < 0) {
return framelen; return framelen;
} }
frame->hd.length = framelen-SPDYLAY_FRAME_HEAD_LENGTH; frame->hd.length = framelen-SPDYLAY_FRAME_HEAD_LENGTH;
memset(framebuf, 0, SPDYLAY_SYN_STREAM_NV_OFFSET); memset(*buf_ptr, 0, SPDYLAY_SYN_STREAM_NV_OFFSET);
/* pack ctrl header after length is determined */ /* pack ctrl header after length is determined */
spdylay_frame_pack_ctrl_hd(framebuf, &frame->hd); spdylay_frame_pack_ctrl_hd(*buf_ptr, &frame->hd);
spdylay_put_uint32be(&framebuf[8], frame->stream_id); spdylay_put_uint32be(&(*buf_ptr)[8], frame->stream_id);
spdylay_put_uint32be(&framebuf[12], frame->assoc_stream_id); spdylay_put_uint32be(&(*buf_ptr)[12], frame->assoc_stream_id);
framebuf[16] = (frame->pri << 6); (*buf_ptr)[16] = (frame->pri << 6);
*buf_ptr = framebuf;
return framelen; return framelen;
} }
@ -496,21 +506,24 @@ int spdylay_frame_unpack_syn_stream(spdylay_syn_stream *frame,
#define SPDYLAY_SYN_REPLY_NV_OFFSET 14 #define SPDYLAY_SYN_REPLY_NV_OFFSET 14
ssize_t spdylay_frame_pack_syn_reply(uint8_t **buf_ptr, ssize_t spdylay_frame_pack_syn_reply(uint8_t **buf_ptr,
size_t *buflen_ptr,
uint8_t **nvbuf_ptr,
size_t *nvbuflen_ptr,
spdylay_syn_reply *frame, spdylay_syn_reply *frame,
spdylay_zlib *deflater) spdylay_zlib *deflater)
{ {
uint8_t *framebuf = NULL;
ssize_t framelen; ssize_t framelen;
framelen = spdylay_frame_alloc_pack_nv(&framebuf, frame->nv, framelen = spdylay_frame_alloc_pack_nv(buf_ptr, buflen_ptr,
nvbuf_ptr, nvbuflen_ptr,
frame->nv,
SPDYLAY_SYN_REPLY_NV_OFFSET, deflater); SPDYLAY_SYN_REPLY_NV_OFFSET, deflater);
if(framelen < 0) { if(framelen < 0) {
return framelen; return framelen;
} }
frame->hd.length = framelen-SPDYLAY_FRAME_HEAD_LENGTH; frame->hd.length = framelen-SPDYLAY_FRAME_HEAD_LENGTH;
memset(framebuf, 0, SPDYLAY_SYN_REPLY_NV_OFFSET); memset(*buf_ptr, 0, SPDYLAY_SYN_REPLY_NV_OFFSET);
spdylay_frame_pack_ctrl_hd(framebuf, &frame->hd); spdylay_frame_pack_ctrl_hd(*buf_ptr, &frame->hd);
spdylay_put_uint32be(&framebuf[8], frame->stream_id); spdylay_put_uint32be(&(*buf_ptr)[8], frame->stream_id);
*buf_ptr = framebuf;
return framelen; return framelen;
} }
@ -530,18 +543,18 @@ int spdylay_frame_unpack_syn_reply(spdylay_syn_reply *frame,
return r; return r;
} }
ssize_t spdylay_frame_pack_ping(uint8_t **buf_ptr, spdylay_ping *frame) ssize_t spdylay_frame_pack_ping(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_ping *frame)
{ {
uint8_t *framebuf = NULL;
ssize_t framelen = 12; ssize_t framelen = 12;
framebuf = malloc(framelen); int r;
if(framebuf == NULL) { r = spdylay_reserve_buffer(buf_ptr, buflen_ptr, framelen);
return SPDYLAY_ERR_NOMEM; if(r != 0) {
return r;
} }
memset(framebuf, 0, framelen); memset(*buf_ptr, 0, framelen);
spdylay_frame_pack_ctrl_hd(framebuf, &frame->hd); spdylay_frame_pack_ctrl_hd(*buf_ptr, &frame->hd);
spdylay_put_uint32be(&framebuf[8], frame->unique_id); spdylay_put_uint32be(&(*buf_ptr)[8], frame->unique_id);
*buf_ptr = framebuf;
return framelen; return framelen;
} }
@ -557,18 +570,18 @@ int spdylay_frame_unpack_ping(spdylay_ping *frame,
return 0; return 0;
} }
ssize_t spdylay_frame_pack_goaway(uint8_t **buf_ptr, spdylay_goaway *frame) ssize_t spdylay_frame_pack_goaway(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_goaway *frame)
{ {
uint8_t *framebuf = NULL;
ssize_t framelen = 12; ssize_t framelen = 12;
framebuf = malloc(framelen); int r;
if(framebuf == NULL) { r = spdylay_reserve_buffer(buf_ptr, buflen_ptr, framelen);
return SPDYLAY_ERR_NOMEM; if(r != 0) {
return r;
} }
memset(framebuf, 0, framelen); memset(*buf_ptr, 0, framelen);
spdylay_frame_pack_ctrl_hd(framebuf, &frame->hd); spdylay_frame_pack_ctrl_hd(*buf_ptr, &frame->hd);
spdylay_put_uint32be(&framebuf[8], frame->last_good_stream_id); spdylay_put_uint32be(&(*buf_ptr)[8], frame->last_good_stream_id);
*buf_ptr = framebuf;
return framelen; return framelen;
} }
@ -587,22 +600,23 @@ int spdylay_frame_unpack_goaway(spdylay_goaway *frame,
#define SPDYLAY_HEADERS_NV_OFFSET 14 #define SPDYLAY_HEADERS_NV_OFFSET 14
ssize_t spdylay_frame_pack_headers(uint8_t **buf_ptr, ssize_t spdylay_frame_pack_headers(uint8_t **buf_ptr, size_t *buflen_ptr,
uint8_t **nvbuf_ptr, size_t *nvbuflen_ptr,
spdylay_headers *frame, spdylay_headers *frame,
spdylay_zlib *deflater) spdylay_zlib *deflater)
{ {
uint8_t *framebuf = NULL;
ssize_t framelen; ssize_t framelen;
framelen = spdylay_frame_alloc_pack_nv(&framebuf, frame->nv, framelen = spdylay_frame_alloc_pack_nv(buf_ptr, buflen_ptr,
nvbuf_ptr, nvbuflen_ptr,
frame->nv,
SPDYLAY_HEADERS_NV_OFFSET, deflater); SPDYLAY_HEADERS_NV_OFFSET, deflater);
if(framelen < 0) { if(framelen < 0) {
return framelen; return framelen;
} }
frame->hd.length = framelen-SPDYLAY_FRAME_HEAD_LENGTH; frame->hd.length = framelen-SPDYLAY_FRAME_HEAD_LENGTH;
memset(framebuf, 0, SPDYLAY_HEADERS_NV_OFFSET); memset(*buf_ptr, 0, SPDYLAY_HEADERS_NV_OFFSET);
spdylay_frame_pack_ctrl_hd(framebuf, &frame->hd); spdylay_frame_pack_ctrl_hd(*buf_ptr, &frame->hd);
spdylay_put_uint32be(&framebuf[8], frame->stream_id); spdylay_put_uint32be(&(*buf_ptr)[8], frame->stream_id);
*buf_ptr = framebuf;
return framelen; return framelen;
} }
@ -622,20 +636,19 @@ int spdylay_frame_unpack_headers(spdylay_headers *frame,
return r; return r;
} }
ssize_t spdylay_frame_pack_rst_stream(uint8_t **buf_ptr, ssize_t spdylay_frame_pack_rst_stream(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_rst_stream *frame) spdylay_rst_stream *frame)
{ {
uint8_t *framebuf;
ssize_t framelen = 16; ssize_t framelen = 16;
framebuf = malloc(framelen); int r;
if(framebuf == NULL) { r = spdylay_reserve_buffer(buf_ptr, buflen_ptr, framelen);
return SPDYLAY_ERR_NOMEM; if(r != 0) {
return r;
} }
memset(framebuf, 0, framelen); memset(*buf_ptr, 0, framelen);
spdylay_frame_pack_ctrl_hd(framebuf, &frame->hd); spdylay_frame_pack_ctrl_hd(*buf_ptr, &frame->hd);
spdylay_put_uint32be(&framebuf[8], frame->stream_id); spdylay_put_uint32be(&(*buf_ptr)[8], frame->stream_id);
spdylay_put_uint32be(&framebuf[12], frame->status_code); spdylay_put_uint32be(&(*buf_ptr)[12], frame->status_code);
*buf_ptr = framebuf;
return framelen; return framelen;
} }
@ -652,34 +665,33 @@ int spdylay_frame_unpack_rst_stream(spdylay_rst_stream *frame,
return 0; return 0;
} }
ssize_t spdylay_frame_pack_settings(uint8_t **buf_ptr, spdylay_settings *frame) ssize_t spdylay_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_settings *frame)
{ {
uint8_t *framebuf;
ssize_t framelen = SPDYLAY_FRAME_HEAD_LENGTH+frame->hd.length; ssize_t framelen = SPDYLAY_FRAME_HEAD_LENGTH+frame->hd.length;
int i; int i, r;
framebuf = malloc(framelen); r = spdylay_reserve_buffer(buf_ptr, buflen_ptr, framelen);
if(framebuf == NULL) { if(r != 0) {
return SPDYLAY_ERR_NOMEM; return r;
} }
memset(framebuf, 0, framelen); memset(*buf_ptr, 0, framelen);
spdylay_frame_pack_ctrl_hd(framebuf, &frame->hd); spdylay_frame_pack_ctrl_hd(*buf_ptr, &frame->hd);
spdylay_put_uint32be(&framebuf[8], frame->niv); spdylay_put_uint32be(&(*buf_ptr)[8], frame->niv);
for(i = 0; i < frame->niv; ++i) { for(i = 0; i < frame->niv; ++i) {
int off = i*8; int off = i*8;
/* spdy/2 spec says ID is network byte order, but publicly /* spdy/2 spec says ID is network byte order, but publicly
deployed server sends little endian host byte order. */ deployed server sends little endian host byte order. */
char *id_ptr = (char*)(&frame->iv[i].settings_id); char *id_ptr = (char*)(&frame->iv[i].settings_id);
#ifdef WORDS_BIGENDIAN #ifdef WORDS_BIGENDIAN
framebuf[12+off] = id_ptr[3]; (*buf_ptr)[12+off] = id_ptr[3];
framebuf[12+off+1] = id_ptr[2]; (*buf_ptr)[12+off+1] = id_ptr[2];
framebuf[12+off+2] = id_ptr[1]; (*buf_ptr)[12+off+2] = id_ptr[1];
#else /* !WORDS_BIGENDIAN */ #else /* !WORDS_BIGENDIAN */
memcpy(&framebuf[12+off], id_ptr, 3); memcpy(&(*buf_ptr)[12+off], id_ptr, 3);
#endif /* !WORDS_BIGENDIAN */ #endif /* !WORDS_BIGENDIAN */
framebuf[15+off] = frame->iv[i].flags; (*buf_ptr)[15+off] = frame->iv[i].flags;
spdylay_put_uint32be(&framebuf[16+off], frame->iv[i].value); spdylay_put_uint32be(&(*buf_ptr)[16+off], frame->iv[i].value);
} }
*buf_ptr = framebuf;
return framelen; return framelen;
} }

View File

@ -44,14 +44,25 @@
#define SPDYLAY_FRAME_HEAD_LENGTH 8 #define SPDYLAY_FRAME_HEAD_LENGTH 8
/* /*
* Packs SYN_STREAM frame |frame| in wire frame format and store it in * Packs SYN_STREAM frame |frame| in wire format and store it in
* |*buf_ptr|. This function allocates enough memory to store given * |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr| bytes.
* frame in |*buf_ptr|. This function returns the size of packed * The |*nvbuf_ptr| is used to store inflated name/value pairs in wire
* frame if it succeeds, or returns negative error * format temporarily. Its length is |*nvbuflen_ptr| bytes. This
* function expands |*buf_ptr| and |*nvbuf_ptr| as necessary to store
* frame and name/value pairs. When expansion occurred, memory
* previously pointed by |*buf_ptr| and |*nvbuf_ptr| is freed.
* |*buf_ptr|, |*buflen_ptr|, |*nvbuf_ptr| and |*nvbuflen_ptr| are
* updated accordingly.
*
* This function returns the size of
* packed frame if it succeeds, or returns negative error
* code. frame->hd.length is assigned after length is determined * code. frame->hd.length is assigned after length is determined
* during packing process. * during packing process.
*/ */
ssize_t spdylay_frame_pack_syn_stream(uint8_t **buf_ptr, ssize_t spdylay_frame_pack_syn_stream(uint8_t **buf_ptr,
size_t *buflen_ptr,
uint8_t **nvbuf_ptr,
size_t *nvbuflen_ptr,
spdylay_syn_stream *frame, spdylay_syn_stream *frame,
spdylay_zlib *deflater); spdylay_zlib *deflater);
@ -68,12 +79,22 @@ int spdylay_frame_unpack_syn_stream(spdylay_syn_stream *frame,
/* /*
* Packs SYN_REPLY frame |frame| in wire frame format and store it in * Packs SYN_REPLY frame |frame| in wire frame format and store it in
* |*buf_ptr|. This function allocates enough memory to store given * |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr| bytes.
* frame in |*buf_ptr|. This function returns the size of packed frame * The |*nvbuf_ptr| is used to store inflated name/value pairs in wire
* it it succeeds, or returns negative error code. frame->hd.length is * format temporarily. Its length is |*nvbuflen_ptr| bytes. This
* assigned after length is determined during packing process. * function expands |*buf_ptr| and |*nvbuf_ptr| as necessary to store
* frame and name/value pairs. When expansion occurred, memory
* previously pointed by |*buf_ptr| and |*nvbuf_ptr| is freed.
* |*buf_ptr|, |*buflen_ptr|, |*nvbuf_ptr| and |*nvbuflen_ptr| are
* updated accordingly. 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_syn_reply(uint8_t **buf_ptr, ssize_t spdylay_frame_pack_syn_reply(uint8_t **buf_ptr,
size_t *buflen_ptr,
uint8_t **nvbuf_ptr,
size_t *nvbuflen_ptr,
spdylay_syn_reply *frame, spdylay_syn_reply *frame,
spdylay_zlib *deflater); spdylay_zlib *deflater);
@ -88,11 +109,13 @@ int spdylay_frame_unpack_syn_reply(spdylay_syn_reply *frame,
/* /*
* Packs PING frame |frame| in wire format and store it in * Packs PING frame |frame| in wire format and store it in
* |*buf_ptr|. This function allocates enough memory in |*buf_ptr| to * |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* store given |frame|. This function returns the size of packed frame * length. This function expands |*buf_ptr| as necessary to store
* if it succeeds, or negative error code. * given |frame|. This function returns the size of packed frame if it
* succeeds, or negative error code.
*/ */
ssize_t spdylay_frame_pack_ping(uint8_t **buf_ptr, spdylay_ping *frame); ssize_t spdylay_frame_pack_ping(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_ping *frame);
/* /*
* Unpacks PING wire format into |frame|. This function returns 0 if * Unpacks PING wire format into |frame|. This function returns 0 if
@ -104,11 +127,13 @@ int spdylay_frame_unpack_ping(spdylay_ping *frame,
/* /*
* Packs GOAWAY frame |frame | in wire format and store it in * Packs GOAWAY frame |frame | in wire format and store it in
* |*buf_ptr|. This function allocates enough memory in |*buf_ptr| to * |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* store given |frame|. This function returns the size of packed frame * length. This function expands |*buf_ptr| as necessary to store
* if it succeeds, or negative error code. * given |frame|. This function returns the size of packed frame if it
* succeeds, or negative error code.
*/ */
ssize_t spdylay_frame_pack_goaway(uint8_t **buf_ptr, spdylay_goaway *frame); ssize_t spdylay_frame_pack_goaway(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_goaway *frame);
/* /*
* Unpacks GOAWAY wire format into |frame|. This function returns 0 if * Unpacks GOAWAY wire format into |frame|. This function returns 0 if
@ -120,12 +145,20 @@ int spdylay_frame_unpack_goaway(spdylay_goaway *frame,
/* /*
* Packs HEADERS frame |frame| in wire format and store it in * Packs HEADERS frame |frame| in wire format and store it in
* |*buf_ptr|. This function allocates enough memory in |*buf_ptr| to * |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr| bytes.
* store given |frame|. This function returns the size of packed frame * The |*nvbuf_ptr| is used to store inflated name/value pairs in wire
* it it succeeds, or returns negative error code. frame->hd.length is * format temporarily. Its length is |*nvbuflen_ptr| bytes. This
* assigned after length is determined during packing process. * function expands |*buf_ptr| and |*nvbuf_ptr| as necessary to store
* frame and name/value pairs. When expansion occurred, memory
* previously pointed by |*buf_ptr| and |*nvbuf_ptr| is freed.
* |*buf_ptr|, |*buflen_ptr|, |*nvbuf_ptr| and |*nvbuflen_ptr| are
* updated accordingly. 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, ssize_t spdylay_frame_pack_headers(uint8_t **buf_ptr, size_t *buflen_ptr,
uint8_t **nvbuf_ptr, size_t *nvbuflen_ptr,
spdylay_headers *frame, spdylay_headers *frame,
spdylay_zlib *deflater); spdylay_zlib *deflater);
@ -140,12 +173,13 @@ int spdylay_frame_unpack_headers(spdylay_headers *frame,
/* /*
* Packs RST_STREAM frame |frame| in wire frame format and store it in * Packs RST_STREAM frame |frame| in wire frame format and store it in
* |*buf_ptr|. This function allocates enough memory to store given * |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* frame in |*buf_ptr|. In spdy/2 spc, RST_STREAM wire format is * length. This function expands |*buf_ptr| as necessary to store
* always 16 bytes long. This function returns the size of packed * given |frame|. In spdy/2 spc, RST_STREAM wire format is always 16
* frame if it succeeds, or negative error code. * bytes long. This function returns the size of packed frame if it
* succeeds, or negative error code.
*/ */
ssize_t spdylay_frame_pack_rst_stream(uint8_t **buf_ptr, ssize_t spdylay_frame_pack_rst_stream(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_rst_stream *frame); spdylay_rst_stream *frame);
/* /*
@ -158,11 +192,13 @@ int spdylay_frame_unpack_rst_stream(spdylay_rst_stream *frame,
/* /*
* Packs SETTINGS frame |frame| in wire format and store it in * Packs SETTINGS frame |frame| in wire format and store it in
* |*buf_ptr|. This function allocates enough memory to store given * |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* frame in |*buf_ptr|. This function returns the size of packed frame * length. This function expands |*buf_ptr| as necessary to store
* if it succeeds, or negative error code. * given |frame|. This function returns the size of packed frame if it
* succeeds, or negative error code.
*/ */
ssize_t spdylay_frame_pack_settings(uint8_t **buf_ptr, spdylay_settings *frame); ssize_t spdylay_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_settings *frame);
/* /*
* Unpacks SETTINGS wire format into |frame|. This function returns 0 * Unpacks SETTINGS wire format into |frame|. This function returns 0

View File

@ -52,3 +52,19 @@ uint32_t spdylay_get_uint32(const uint8_t *data)
memcpy(&n, data, sizeof(uint32_t)); memcpy(&n, data, sizeof(uint32_t));
return ntohl(n); return ntohl(n);
} }
int spdylay_reserve_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t min_length)
{
if(min_length > *buflen_ptr) {
uint8_t *temp = malloc(min_length);
if(temp == NULL) {
return SPDYLAY_ERR_NOMEM;
} else {
free(*buf_ptr);
*buf_ptr = temp;
*buflen_ptr = min_length;
}
}
return 0;
}

View File

@ -55,4 +55,18 @@ uint16_t spdylay_get_uint16(const uint8_t *data);
*/ */
uint32_t spdylay_get_uint32(const uint8_t *data); uint32_t spdylay_get_uint32(const uint8_t *data);
/*
* Ensures that buffer |*buf_ptr| with |*buflen_ptr| length has at
* least |min_length| bytes. If |min_length| > |*buflen_ptr|,
* allocates new buffer having at least |min_length| bytes and assigns
* its pointer to |*buf_ptr| and allocated number of bytes to
* |*buflen_ptr|. The memory pointed by |*buf_ptr| previously is
* freed. No memory copy is done between old and new buffer. This
* function returns 0 if it succeeds, or negative error code.
* |*buf_ptr| and |*buflen_ptr| are only updated iff this function
* succeeds.
*/
int spdylay_reserve_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
size_t min_length);
#endif /* SPDYLAY_HELPER_H */ #endif /* SPDYLAY_HELPER_H */

View File

@ -130,6 +130,31 @@ static int spdylay_session_new(spdylay_session **session_ptr,
return r; return r;
} }
(*session_ptr)->aob.framebuf = malloc(SPDYLAY_INITIAL_OUTBOUND_BUFFER_LENGTH);
if((*session_ptr)->aob.framebuf == NULL) {
spdylay_pq_free(&(*session_ptr)->ob_ss_pq);
spdylay_pq_free(&(*session_ptr)->ob_pq);
spdylay_map_free(&(*session_ptr)->streams);
spdylay_zlib_inflate_free(&(*session_ptr)->hd_inflater);
spdylay_zlib_deflate_free(&(*session_ptr)->hd_deflater);
free(*session_ptr);
return r;
}
(*session_ptr)->aob.framebufmax = SPDYLAY_INITIAL_OUTBOUND_BUFFER_LENGTH;
(*session_ptr)->nvbuf = malloc(SPDYLAY_INITIAL_NV_BUFFER_LENGTH);
if((*session_ptr)->nvbuf == NULL) {
free((*session_ptr)->aob.framebuf);
spdylay_pq_free(&(*session_ptr)->ob_ss_pq);
spdylay_pq_free(&(*session_ptr)->ob_pq);
spdylay_map_free(&(*session_ptr)->streams);
spdylay_zlib_inflate_free(&(*session_ptr)->hd_inflater);
spdylay_zlib_deflate_free(&(*session_ptr)->hd_deflater);
free(*session_ptr);
return r;
}
(*session_ptr)->nvbuflen = SPDYLAY_INITIAL_NV_BUFFER_LENGTH;
memset((*session_ptr)->settings, 0, sizeof((*session_ptr)->settings)); memset((*session_ptr)->settings, 0, sizeof((*session_ptr)->settings));
(*session_ptr)->settings[SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS] = (*session_ptr)->settings[SPDYLAY_SETTINGS_MAX_CONCURRENT_STREAMS] =
SPDYLAY_CONCURRENT_STREAMS_MAX; SPDYLAY_CONCURRENT_STREAMS_MAX;
@ -244,6 +269,8 @@ void spdylay_session_del(spdylay_session *session)
spdylay_zlib_deflate_free(&session->hd_deflater); spdylay_zlib_deflate_free(&session->hd_deflater);
spdylay_zlib_inflate_free(&session->hd_inflater); spdylay_zlib_inflate_free(&session->hd_inflater);
free(session->iframe.buf); free(session->iframe.buf);
free(session->aob.framebuf);
free(session->nvbuf);
free(session); free(session);
} }
@ -454,12 +481,10 @@ static int spdylay_session_is_data_allowed(spdylay_session *session,
} }
ssize_t spdylay_session_prep_frame(spdylay_session *session, ssize_t spdylay_session_prep_frame(spdylay_session *session,
spdylay_outbound_item *item, spdylay_outbound_item *item)
uint8_t **framebuf_ptr)
{ {
/* TODO Get or validate stream ID here */ /* TODO Get or validate stream ID here */
/* TODO Validate assoc_stream_id here */ /* TODO Validate assoc_stream_id here */
uint8_t *framebuf;
ssize_t framebuflen; ssize_t framebuflen;
switch(item->frame_type) { switch(item->frame_type) {
case SPDYLAY_SYN_STREAM: { case SPDYLAY_SYN_STREAM: {
@ -473,7 +498,10 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
stream_id = session->next_stream_id; stream_id = session->next_stream_id;
item->frame->syn_stream.stream_id = stream_id; item->frame->syn_stream.stream_id = stream_id;
session->next_stream_id += 2; session->next_stream_id += 2;
framebuflen = spdylay_frame_pack_syn_stream(&framebuf, framebuflen = spdylay_frame_pack_syn_stream(&session->aob.framebuf,
&session->aob.framebufmax,
&session->nvbuf,
&session->nvbuflen,
&item->frame->syn_stream, &item->frame->syn_stream,
&session->hd_deflater); &session->hd_deflater);
if(framebuflen < 0) { if(framebuflen < 0) {
@ -485,7 +513,6 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
item->frame->syn_stream.pri, item->frame->syn_stream.pri,
SPDYLAY_STREAM_INITIAL, SPDYLAY_STREAM_INITIAL,
aux_data->stream_user_data) == NULL) { aux_data->stream_user_data) == NULL) {
free(framebuf);
return SPDYLAY_ERR_NOMEM; return SPDYLAY_ERR_NOMEM;
} }
break; break;
@ -495,7 +522,10 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
item->frame->syn_reply.stream_id)) { item->frame->syn_reply.stream_id)) {
return SPDYLAY_ERR_INVALID_FRAME; return SPDYLAY_ERR_INVALID_FRAME;
} }
framebuflen = spdylay_frame_pack_syn_reply(&framebuf, framebuflen = spdylay_frame_pack_syn_reply(&session->aob.framebuf,
&session->aob.framebufmax,
&session->nvbuf,
&session->nvbuflen,
&item->frame->syn_reply, &item->frame->syn_reply,
&session->hd_deflater); &session->hd_deflater);
if(framebuflen < 0) { if(framebuflen < 0) {
@ -504,14 +534,16 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
break; break;
} }
case SPDYLAY_RST_STREAM: case SPDYLAY_RST_STREAM:
framebuflen = spdylay_frame_pack_rst_stream(&framebuf, framebuflen = spdylay_frame_pack_rst_stream(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->rst_stream); &item->frame->rst_stream);
if(framebuflen < 0) { if(framebuflen < 0) {
return framebuflen; return framebuflen;
} }
break; break;
case SPDYLAY_SETTINGS: case SPDYLAY_SETTINGS:
framebuflen = spdylay_frame_pack_settings(&framebuf, framebuflen = spdylay_frame_pack_settings(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->settings); &item->frame->settings);
if(framebuflen < 0) { if(framebuflen < 0) {
return framebuflen; return framebuflen;
@ -522,7 +554,9 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
unreachable. */ unreachable. */
abort(); abort();
case SPDYLAY_PING: case SPDYLAY_PING:
framebuflen = spdylay_frame_pack_ping(&framebuf, &item->frame->ping); framebuflen = spdylay_frame_pack_ping(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->ping);
if(framebuflen < 0) { if(framebuflen < 0) {
return framebuflen; return framebuflen;
} }
@ -539,7 +573,9 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
last-good-stream-id. */ last-good-stream-id. */
return SPDYLAY_ERR_INVALID_FRAME; return SPDYLAY_ERR_INVALID_FRAME;
} }
framebuflen = spdylay_frame_pack_goaway(&framebuf, &item->frame->goaway); framebuflen = spdylay_frame_pack_goaway(&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->goaway);
if(framebuflen < 0) { if(framebuflen < 0) {
return framebuflen; return framebuflen;
} }
@ -548,7 +584,9 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
if(!spdylay_session_is_data_allowed(session, item->frame->data.stream_id)) { if(!spdylay_session_is_data_allowed(session, item->frame->data.stream_id)) {
return SPDYLAY_ERR_INVALID_FRAME; return SPDYLAY_ERR_INVALID_FRAME;
} }
framebuflen = spdylay_session_pack_data(session, &framebuf, framebuflen = spdylay_session_pack_data(session,
&session->aob.framebuf,
&session->aob.framebufmax,
&item->frame->data); &item->frame->data);
if(framebuflen < 0) { if(framebuflen < 0) {
return framebuflen; return framebuflen;
@ -558,7 +596,6 @@ ssize_t spdylay_session_prep_frame(spdylay_session *session,
default: default:
framebuflen = SPDYLAY_ERR_INVALID_ARGUMENT; framebuflen = SPDYLAY_ERR_INVALID_ARGUMENT;
} }
*framebuf_ptr = framebuf;
return framebuflen; return framebuflen;
} }
@ -567,8 +604,8 @@ static void spdylay_active_outbound_item_reset
{ {
spdylay_outbound_item_free(aob->item); spdylay_outbound_item_free(aob->item);
free(aob->item); free(aob->item);
free(aob->framebuf); aob->item = NULL;
memset(aob, 0, sizeof(spdylay_active_outbound_item)); aob->framebuflen = aob->framebufoff = 0;
} }
spdylay_outbound_item* spdylay_session_get_ob_pq_top spdylay_outbound_item* spdylay_session_get_ob_pq_top
@ -815,13 +852,12 @@ int spdylay_session_send(spdylay_session *session)
ssize_t sentlen; ssize_t sentlen;
if(session->aob.item == NULL) { if(session->aob.item == NULL) {
spdylay_outbound_item *item; spdylay_outbound_item *item;
uint8_t *framebuf;
ssize_t framebuflen; ssize_t framebuflen;
item = spdylay_session_pop_next_ob_item(session); item = spdylay_session_pop_next_ob_item(session);
if(item == NULL) { if(item == NULL) {
break; break;
} }
framebuflen = spdylay_session_prep_frame(session, item, &framebuf); framebuflen = spdylay_session_prep_frame(session, item);
if(framebuflen < 0) { if(framebuflen < 0) {
/* TODO Call error callback? */ /* TODO Call error callback? */
spdylay_outbound_item_free(item); spdylay_outbound_item_free(item);
@ -833,7 +869,6 @@ int spdylay_session_send(spdylay_session *session)
} }
} }
session->aob.item = item; session->aob.item = item;
session->aob.framebuf = framebuf;
session->aob.framebuflen = framebuflen; session->aob.framebuflen = framebuflen;
/* Call before_send callback */ /* Call before_send callback */
if(item->frame_type != SPDYLAY_DATA && if(item->frame_type != SPDYLAY_DATA &&
@ -1582,21 +1617,17 @@ int spdylay_session_add_goaway(spdylay_session *session,
} }
ssize_t spdylay_session_pack_data(spdylay_session *session, ssize_t spdylay_session_pack_data(spdylay_session *session,
uint8_t **buf_ptr, spdylay_data *frame) uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_data *frame)
{ {
uint8_t *framebuf;
ssize_t framelen = SPDYLAY_DATA_FRAME_LENGTH; ssize_t framelen = SPDYLAY_DATA_FRAME_LENGTH;
framebuf = malloc(framelen); int r;
if(framebuf == NULL) { r = spdylay_reserve_buffer(buf_ptr, buflen_ptr, framelen);
return SPDYLAY_ERR_NOMEM; if(r != 0) {
return r;
} }
framelen = spdylay_session_pack_data_overwrite(session, framebuf, framelen, framelen = spdylay_session_pack_data_overwrite(session, *buf_ptr, framelen,
frame); frame);
if(framelen < 0) {
free(framebuf);
} else {
*buf_ptr = framebuf;
}
return framelen; return framelen;
} }

View File

@ -46,8 +46,16 @@ typedef struct {
typedef struct { typedef struct {
spdylay_outbound_item *item; spdylay_outbound_item *item;
/* Buffer for outbound frames. Used to pack one frame. The memory
pointed by framebuf is initially allocated by
spdylay_session_{client,server}_new() and deallocated by
spdylay_session_del() */
uint8_t *framebuf; uint8_t *framebuf;
/* The capacity of framebuf in bytes */
size_t framebufmax;
/* The length of the frame stored in framebuf */
size_t framebuflen; size_t framebuflen;
/* The number of bytes has been sent */
size_t framebufoff; size_t framebufoff;
} spdylay_active_outbound_item; } spdylay_active_outbound_item;
@ -55,6 +63,9 @@ typedef struct {
message block of SSLv3/TLSv1 */ message block of SSLv3/TLSv1 */
#define SPDYLAY_INBOUND_BUFFER_LENGTH 16384 #define SPDYLAY_INBOUND_BUFFER_LENGTH 16384
#define SPDYLAY_INITIAL_OUTBOUND_BUFFER_LENGTH SPDYLAY_DATA_FRAME_LENGTH
#define SPDYLAY_INITIAL_NV_BUFFER_LENGTH 4096
typedef struct { typedef struct {
uint8_t buf[SPDYLAY_INBOUND_BUFFER_LENGTH]; uint8_t buf[SPDYLAY_INBOUND_BUFFER_LENGTH];
uint8_t *mark; uint8_t *mark;
@ -114,6 +125,12 @@ struct spdylay_session {
spdylay_inbound_buffer ibuf; spdylay_inbound_buffer ibuf;
spdylay_inbound_frame iframe; spdylay_inbound_frame iframe;
/* Buffer used to store inflated name/value pairs in wire format
temporarily on pack/unpack. */
uint8_t *nvbuf;
/* The number of bytes allocated for nvbuf */
size_t nvbuflen;
spdylay_zlib hd_deflater; spdylay_zlib hd_deflater;
spdylay_zlib hd_inflater; spdylay_zlib hd_inflater;
@ -274,14 +291,15 @@ spdylay_stream* spdylay_session_get_stream(spdylay_session *session,
/* /*
* Packs DATA frame |frame| in wire frame format and store it in * Packs DATA frame |frame| in wire frame format and store it in
* |*buf_ptr|. This function always allocates * |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* 8+SPDYLAY_DATA_CHUNK_LENGTH bytes. It packs header in first 8 * length. This function expands |*buf_ptr| as necessary to store
* bytes. Remaining bytes are filled using frame->data_prd. This * given |frame|. It packs header in first 8 bytes. Remaining bytes
* function returns the size of packed frame if it succeeds, or * are filled using frame->data_prd. This function returns the size
* negative error code. * of packed frame if it succeeds, or negative error code.
*/ */
ssize_t spdylay_session_pack_data(spdylay_session *session, ssize_t spdylay_session_pack_data(spdylay_session *session,
uint8_t **buf_ptr, spdylay_data *frame); uint8_t **buf_ptr, size_t *buflen_ptr,
spdylay_data *frame);
/* /*
* Packs DATA frame |frame| in wire frame format and store it in * Packs DATA frame |frame| in wire frame format and store it in

View File

@ -95,15 +95,16 @@ void test_spdylay_frame_count_unpack_nv_space()
void test_spdylay_frame_pack_ping() void test_spdylay_frame_pack_ping()
{ {
spdylay_frame frame, oframe; spdylay_frame frame, oframe;
uint8_t *buf; uint8_t *buf = NULL;
ssize_t buflen; size_t buflen = 0;
ssize_t framelen;
spdylay_frame_ping_init(&frame.ping, 1); spdylay_frame_ping_init(&frame.ping, 1);
buflen = spdylay_frame_pack_ping(&buf, &frame.ping); framelen = spdylay_frame_pack_ping(&buf, &buflen, &frame.ping);
CU_ASSERT(0 == spdylay_frame_unpack_ping CU_ASSERT(0 == spdylay_frame_unpack_ping
(&oframe.ping, (&oframe.ping,
&buf[0], SPDYLAY_FRAME_HEAD_LENGTH, &buf[0], SPDYLAY_FRAME_HEAD_LENGTH,
&buf[SPDYLAY_FRAME_HEAD_LENGTH], &buf[SPDYLAY_FRAME_HEAD_LENGTH],
buflen-SPDYLAY_FRAME_HEAD_LENGTH)); framelen-SPDYLAY_FRAME_HEAD_LENGTH));
CU_ASSERT(1 == oframe.ping.unique_id); CU_ASSERT(1 == oframe.ping.unique_id);
free(buf); free(buf);
spdylay_frame_ping_free(&oframe.ping); spdylay_frame_ping_free(&oframe.ping);
@ -113,20 +114,21 @@ void test_spdylay_frame_pack_ping()
void test_spdylay_frame_pack_goaway() void test_spdylay_frame_pack_goaway()
{ {
spdylay_frame frame, oframe; spdylay_frame frame, oframe;
uint8_t *buf; uint8_t *buf = NULL;
ssize_t buflen; size_t buflen = 0;
ssize_t framelen;
spdylay_frame_goaway_init(&frame.goaway, 1000000007); spdylay_frame_goaway_init(&frame.goaway, 1000000007);
buflen = spdylay_frame_pack_goaway(&buf, &frame.goaway); framelen = spdylay_frame_pack_goaway(&buf, &buflen, &frame.goaway);
CU_ASSERT(0 == spdylay_frame_unpack_goaway CU_ASSERT(0 == spdylay_frame_unpack_goaway
(&oframe.goaway, (&oframe.goaway,
&buf[0], SPDYLAY_FRAME_HEAD_LENGTH, &buf[0], SPDYLAY_FRAME_HEAD_LENGTH,
&buf[SPDYLAY_FRAME_HEAD_LENGTH], &buf[SPDYLAY_FRAME_HEAD_LENGTH],
buflen-SPDYLAY_FRAME_HEAD_LENGTH)); framelen-SPDYLAY_FRAME_HEAD_LENGTH));
CU_ASSERT(1000000007 == oframe.goaway.last_good_stream_id); CU_ASSERT(1000000007 == oframe.goaway.last_good_stream_id);
CU_ASSERT(SPDYLAY_PROTO_VERSION == oframe.headers.hd.version); CU_ASSERT(SPDYLAY_PROTO_VERSION == oframe.headers.hd.version);
CU_ASSERT(SPDYLAY_GOAWAY == oframe.headers.hd.type); CU_ASSERT(SPDYLAY_GOAWAY == oframe.headers.hd.type);
CU_ASSERT(SPDYLAY_FLAG_NONE == oframe.headers.hd.flags); CU_ASSERT(SPDYLAY_FLAG_NONE == oframe.headers.hd.flags);
CU_ASSERT(buflen-SPDYLAY_FRAME_HEAD_LENGTH == oframe.ping.hd.length); CU_ASSERT(framelen-SPDYLAY_FRAME_HEAD_LENGTH == oframe.ping.hd.length);
free(buf); free(buf);
spdylay_frame_goaway_free(&oframe.goaway); spdylay_frame_goaway_free(&oframe.goaway);
spdylay_frame_goaway_free(&frame.goaway); spdylay_frame_goaway_free(&frame.goaway);
@ -136,28 +138,32 @@ void test_spdylay_frame_pack_headers()
{ {
spdylay_zlib deflater, inflater; spdylay_zlib deflater, inflater;
spdylay_frame frame, oframe; spdylay_frame frame, oframe;
uint8_t *buf; uint8_t *buf = NULL, *nvbuf = NULL;
ssize_t buflen; size_t buflen = 0, nvbuflen = 0;
ssize_t framelen;
spdylay_zlib_deflate_hd_init(&deflater); spdylay_zlib_deflate_hd_init(&deflater);
spdylay_zlib_inflate_hd_init(&inflater); spdylay_zlib_inflate_hd_init(&inflater);
spdylay_frame_headers_init(&frame.headers, SPDYLAY_FLAG_FIN, 3, spdylay_frame_headers_init(&frame.headers, SPDYLAY_FLAG_FIN, 3,
spdylay_frame_nv_copy(headers)); spdylay_frame_nv_copy(headers));
buflen = spdylay_frame_pack_headers(&buf, &frame.headers, &deflater); framelen = spdylay_frame_pack_headers(&buf, &buflen,
&nvbuf, &nvbuflen,
&frame.headers, &deflater);
CU_ASSERT(0 == spdylay_frame_unpack_headers CU_ASSERT(0 == spdylay_frame_unpack_headers
(&oframe.headers, (&oframe.headers,
&buf[0], SPDYLAY_FRAME_HEAD_LENGTH, &buf[0], SPDYLAY_FRAME_HEAD_LENGTH,
&buf[SPDYLAY_FRAME_HEAD_LENGTH], &buf[SPDYLAY_FRAME_HEAD_LENGTH],
buflen-SPDYLAY_FRAME_HEAD_LENGTH, framelen-SPDYLAY_FRAME_HEAD_LENGTH,
&inflater)); &inflater));
CU_ASSERT(3 == oframe.headers.stream_id); CU_ASSERT(3 == oframe.headers.stream_id);
CU_ASSERT(SPDYLAY_PROTO_VERSION == oframe.headers.hd.version); CU_ASSERT(SPDYLAY_PROTO_VERSION == oframe.headers.hd.version);
CU_ASSERT(SPDYLAY_HEADERS == oframe.headers.hd.type); CU_ASSERT(SPDYLAY_HEADERS == oframe.headers.hd.type);
CU_ASSERT(SPDYLAY_FLAG_FIN == oframe.headers.hd.flags); CU_ASSERT(SPDYLAY_FLAG_FIN == oframe.headers.hd.flags);
CU_ASSERT(buflen-SPDYLAY_FRAME_HEAD_LENGTH == oframe.ping.hd.length); CU_ASSERT(framelen-SPDYLAY_FRAME_HEAD_LENGTH == oframe.ping.hd.length);
CU_ASSERT(strcmp("method", oframe.headers.nv[0]) == 0); CU_ASSERT(strcmp("method", oframe.headers.nv[0]) == 0);
CU_ASSERT(strcmp("GET", oframe.headers.nv[1]) == 0); CU_ASSERT(strcmp("GET", oframe.headers.nv[1]) == 0);
CU_ASSERT(NULL == oframe.headers.nv[12]); CU_ASSERT(NULL == oframe.headers.nv[12]);
free(buf); free(buf);
free(nvbuf);
spdylay_frame_headers_free(&oframe.headers); spdylay_frame_headers_free(&oframe.headers);
spdylay_frame_headers_free(&frame.headers); spdylay_frame_headers_free(&frame.headers);
spdylay_zlib_inflate_free(&inflater); spdylay_zlib_inflate_free(&inflater);
@ -167,8 +173,9 @@ void test_spdylay_frame_pack_headers()
void test_spdylay_frame_pack_settings() void test_spdylay_frame_pack_settings()
{ {
spdylay_frame frame, oframe; spdylay_frame frame, oframe;
uint8_t *buf; uint8_t *buf = NULL;
ssize_t buflen; size_t buflen = 0;
ssize_t framelen;
int i; int i;
spdylay_settings_entry iv[3]; spdylay_settings_entry iv[3];
iv[0].settings_id = SPDYLAY_SETTINGS_UPLOAD_BANDWIDTH; iv[0].settings_id = SPDYLAY_SETTINGS_UPLOAD_BANDWIDTH;
@ -185,20 +192,20 @@ void test_spdylay_frame_pack_settings()
(&frame.settings, (&frame.settings,
SPDYLAY_FLAG_SETTINGS_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS, SPDYLAY_FLAG_SETTINGS_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS,
spdylay_frame_iv_copy(iv, 3), 3); spdylay_frame_iv_copy(iv, 3), 3);
buflen = spdylay_frame_pack_settings(&buf, &frame.settings); framelen = spdylay_frame_pack_settings(&buf, &buflen, &frame.settings);
CU_ASSERT(8+4+3*8 == buflen); CU_ASSERT(8+4+3*8 == framelen);
CU_ASSERT(0 == spdylay_frame_unpack_settings CU_ASSERT(0 == spdylay_frame_unpack_settings
(&oframe.settings, (&oframe.settings,
&buf[0], SPDYLAY_FRAME_HEAD_LENGTH, &buf[0], SPDYLAY_FRAME_HEAD_LENGTH,
&buf[SPDYLAY_FRAME_HEAD_LENGTH], &buf[SPDYLAY_FRAME_HEAD_LENGTH],
buflen-SPDYLAY_FRAME_HEAD_LENGTH)); framelen-SPDYLAY_FRAME_HEAD_LENGTH));
CU_ASSERT(SPDYLAY_PROTO_VERSION == oframe.settings.hd.version); CU_ASSERT(SPDYLAY_PROTO_VERSION == oframe.settings.hd.version);
CU_ASSERT(SPDYLAY_SETTINGS == oframe.settings.hd.type); CU_ASSERT(SPDYLAY_SETTINGS == oframe.settings.hd.type);
CU_ASSERT(SPDYLAY_FLAG_SETTINGS_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS == CU_ASSERT(SPDYLAY_FLAG_SETTINGS_CLEAR_PREVIOUSLY_PERSISTED_SETTINGS ==
oframe.settings.hd.flags); oframe.settings.hd.flags);
CU_ASSERT(buflen-SPDYLAY_FRAME_HEAD_LENGTH == oframe.settings.hd.length); CU_ASSERT(framelen-SPDYLAY_FRAME_HEAD_LENGTH == oframe.settings.hd.length);
CU_ASSERT(3 == oframe.settings.niv); CU_ASSERT(3 == oframe.settings.niv);
for(i = 0; i < 3; ++i) { for(i = 0; i < 3; ++i) {

View File

@ -190,18 +190,22 @@ void test_spdylay_session_recv()
const char *nv[] = { const char *nv[] = {
"url", "/", NULL "url", "/", NULL
}; };
uint8_t *framedata; uint8_t *framedata = NULL, *nvbuf = NULL;
size_t framelen; size_t framedatalen = 0, nvbuflen = 0;
ssize_t framelen;
spdylay_frame frame; spdylay_frame frame;
user_data.df = &df; user_data.df = &df;
spdylay_session_client_new(&session, &callbacks, &user_data); spdylay_session_client_new(&session, &callbacks, &user_data);
spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_FLAG_NONE, 0, 0, 3, spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_FLAG_NONE, 0, 0, 3,
dup_nv(nv)); dup_nv(nv));
framelen = spdylay_frame_pack_syn_stream(&framedata, &frame.syn_stream, framelen = spdylay_frame_pack_syn_stream(&framedata, &framedatalen,
&nvbuf, &nvbuflen,
&frame.syn_stream,
&session->hd_deflater); &session->hd_deflater);
scripted_data_feed_init(&df, framedata, framelen); scripted_data_feed_init(&df, framedata, framelen);
free(framedata); free(framedata);
free(nvbuf);
spdylay_frame_syn_stream_free(&frame.syn_stream); spdylay_frame_syn_stream_free(&frame.syn_stream);
CU_ASSERT(0 == spdylay_session_recv(session)); CU_ASSERT(0 == spdylay_session_recv(session));
@ -272,8 +276,9 @@ void test_spdylay_session_recv_invalid_stream_id()
scripted_data_feed df; scripted_data_feed df;
my_user_data user_data; my_user_data user_data;
const char *nv[] = { NULL }; const char *nv[] = { NULL };
uint8_t *framedata; uint8_t *framedata = NULL, *nvbuf = NULL;
size_t framelen; size_t framedatalen = 0, nvbuflen = 0;
ssize_t framelen;
spdylay_frame frame; spdylay_frame frame;
user_data.df = &df; user_data.df = &df;
@ -281,10 +286,11 @@ void test_spdylay_session_recv_invalid_stream_id()
spdylay_session_client_new(&session, &callbacks, &user_data); spdylay_session_client_new(&session, &callbacks, &user_data);
spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_FLAG_NONE, 1, 0, 3, spdylay_frame_syn_stream_init(&frame.syn_stream, SPDYLAY_FLAG_NONE, 1, 0, 3,
dup_nv(nv)); dup_nv(nv));
framelen = spdylay_frame_pack_syn_stream(&framedata, &frame.syn_stream, framelen = spdylay_frame_pack_syn_stream(&framedata, &framedatalen,
&nvbuf, &nvbuflen,
&frame.syn_stream,
&session->hd_deflater); &session->hd_deflater);
scripted_data_feed_init(&df, framedata, framelen); scripted_data_feed_init(&df, framedata, framelen);
free(framedata);
spdylay_frame_syn_stream_free(&frame.syn_stream); spdylay_frame_syn_stream_free(&frame.syn_stream);
CU_ASSERT(0 == spdylay_session_recv(session)); CU_ASSERT(0 == spdylay_session_recv(session));
@ -292,15 +298,18 @@ void test_spdylay_session_recv_invalid_stream_id()
spdylay_frame_syn_reply_init(&frame.syn_reply, SPDYLAY_FLAG_NONE, 100, spdylay_frame_syn_reply_init(&frame.syn_reply, SPDYLAY_FLAG_NONE, 100,
dup_nv(nv)); dup_nv(nv));
framelen = spdylay_frame_pack_syn_reply(&framedata, &frame.syn_reply, framelen = spdylay_frame_pack_syn_reply(&framedata, &framedatalen,
&nvbuf, &nvbuflen,
&frame.syn_reply,
&session->hd_deflater); &session->hd_deflater);
scripted_data_feed_init(&df, framedata, framelen); scripted_data_feed_init(&df, framedata, framelen);
free(framedata);
spdylay_frame_syn_reply_free(&frame.syn_reply); spdylay_frame_syn_reply_free(&frame.syn_reply);
CU_ASSERT(0 == spdylay_session_recv(session)); CU_ASSERT(0 == spdylay_session_recv(session));
CU_ASSERT(2 == user_data.invalid_ctrl_recv_cb_called); CU_ASSERT(2 == user_data.invalid_ctrl_recv_cb_called);
free(framedata);
free(nvbuf);
spdylay_session_del(session); spdylay_session_del(session);
} }