Rework outbound frame buffers
This commit is contained in:
parent
0666a73e10
commit
d07bb1ddff
|
@ -123,11 +123,17 @@ static void nghttp2_buf_chain_del(nghttp2_buf_chain *chain)
|
|||
|
||||
int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length,
|
||||
size_t max_chunk)
|
||||
{
|
||||
return nghttp2_bufs_init2(bufs, chunk_length, max_chunk, 0);
|
||||
}
|
||||
|
||||
int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
|
||||
size_t max_chunk, size_t offset)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_buf_chain *chain;
|
||||
|
||||
if(max_chunk == 0) {
|
||||
if(max_chunk == 0 || chunk_length < offset) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
|
||||
|
@ -136,9 +142,13 @@ int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length,
|
|||
return rv;
|
||||
}
|
||||
|
||||
bufs->offset = offset;
|
||||
|
||||
bufs->head = chain;
|
||||
bufs->cur = bufs->head;
|
||||
|
||||
nghttp2_buf_shift_right(&bufs->cur->buf, offset);
|
||||
|
||||
bufs->chunk_length = chunk_length;
|
||||
bufs->chunk_left = max_chunk - 1;
|
||||
|
||||
|
@ -158,10 +168,36 @@ void nghttp2_bufs_free(nghttp2_bufs *bufs)
|
|||
}
|
||||
}
|
||||
|
||||
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs)
|
||||
{
|
||||
nghttp2_buf_chain *ci;
|
||||
|
||||
for(ci = bufs->cur; ci->next; ci = ci->next) {
|
||||
if(nghttp2_buf_len(&ci->buf) == 0) {
|
||||
return;
|
||||
} else {
|
||||
bufs->cur = ci;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs)
|
||||
{
|
||||
nghttp2_buf_chain *ci;
|
||||
ssize_t len;
|
||||
|
||||
len = 0;
|
||||
for(ci = bufs->head; ci; ci = ci->next) {
|
||||
len += nghttp2_buf_len(&ci->buf);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int nghttp2_bufs_avail(nghttp2_bufs *bufs)
|
||||
{
|
||||
return nghttp2_buf_avail(&bufs->cur->buf) +
|
||||
bufs->chunk_left * bufs->chunk_left;
|
||||
(bufs->chunk_left - bufs->offset) * bufs->chunk_left;
|
||||
}
|
||||
|
||||
static int nghttp2_bufs_alloc_chain(nghttp2_bufs *bufs)
|
||||
|
@ -189,6 +225,8 @@ static int nghttp2_bufs_alloc_chain(nghttp2_bufs *bufs)
|
|||
bufs->cur->next = chain;
|
||||
bufs->cur = chain;
|
||||
|
||||
nghttp2_buf_shift_right(&bufs->cur->buf, bufs->offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -199,7 +237,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len)
|
|||
nghttp2_buf *buf;
|
||||
const uint8_t *p;
|
||||
|
||||
if((size_t)nghttp2_bufs_avail(bufs) < len) {
|
||||
if(nghttp2_bufs_avail(bufs) < (ssize_t)len) {
|
||||
return NGHTTP2_ERR_BUFFER_ERROR;
|
||||
}
|
||||
|
||||
|
@ -224,7 +262,7 @@ int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b)
|
||||
static int nghttp2_bufs_ensure_addb(nghttp2_bufs *bufs)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
|
@ -232,7 +270,6 @@ int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b)
|
|||
buf = &bufs->cur->buf;
|
||||
|
||||
if(nghttp2_buf_avail(buf) > 0) {
|
||||
*buf->last++ = b;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -241,9 +278,61 @@ int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b)
|
|||
return rv;
|
||||
}
|
||||
|
||||
buf = &bufs->cur->buf;
|
||||
return 0;
|
||||
}
|
||||
|
||||
*buf->last++ = b;
|
||||
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = nghttp2_bufs_ensure_addb(bufs);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*bufs->cur->buf.last++ = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = nghttp2_bufs_ensure_addb(bufs);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*bufs->cur->buf.last = b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = nghttp2_bufs_ensure_addb(bufs);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*bufs->cur->buf.last++ |= b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = nghttp2_bufs_ensure_addb(bufs);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*bufs->cur->buf.last |= b;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -272,7 +361,9 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out)
|
|||
for(chain = bufs->head; chain; chain = chain->next) {
|
||||
buf = &chain->buf;
|
||||
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
|
||||
|
||||
nghttp2_buf_reset(buf);
|
||||
nghttp2_buf_shift_right(&chain->buf, bufs->offset);
|
||||
}
|
||||
|
||||
bufs->cur = bufs->head;
|
||||
|
@ -288,5 +379,23 @@ void nghttp2_bufs_reset(nghttp2_bufs *bufs)
|
|||
|
||||
for(chain = bufs->head; chain; chain = chain->next) {
|
||||
nghttp2_buf_reset(&chain->buf);
|
||||
nghttp2_buf_shift_right(&chain->buf, bufs->offset);
|
||||
}
|
||||
|
||||
bufs->cur = bufs->head;
|
||||
}
|
||||
|
||||
int nghttp2_bufs_advance(nghttp2_bufs *bufs)
|
||||
{
|
||||
return nghttp2_bufs_alloc_chain(bufs);
|
||||
}
|
||||
|
||||
int nghttp2_bufs_next_present(nghttp2_bufs *bufs)
|
||||
{
|
||||
nghttp2_buf_chain *chain;
|
||||
|
||||
chain = bufs->cur->next;
|
||||
|
||||
return chain && nghttp2_buf_len(&chain->buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -134,39 +134,202 @@ void nghttp2_buf_reset(nghttp2_buf *buf);
|
|||
*/
|
||||
void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len);
|
||||
|
||||
/*
|
||||
* List of nghttp2_buf
|
||||
*/
|
||||
|
||||
struct nghttp2_buf_chain;
|
||||
|
||||
typedef struct nghttp2_buf_chain nghttp2_buf_chain;
|
||||
|
||||
/* Chains 2 buffers */
|
||||
struct nghttp2_buf_chain {
|
||||
/* Points to the subsequent buffer. NULL if there is no such
|
||||
buffer. */
|
||||
nghttp2_buf_chain *next;
|
||||
nghttp2_buf buf;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
/* Points to the first buffer */
|
||||
nghttp2_buf_chain *head;
|
||||
/* Buffer pointer where write occurs. */
|
||||
nghttp2_buf_chain *cur;
|
||||
/* The buffer capacity of each buf */
|
||||
size_t chunk_length;
|
||||
/* The maximum number of nghttp2_buf_chain */
|
||||
size_t chunk_left;
|
||||
/* pos offset from begin in each buffers. On initialization and
|
||||
reset, buf->pos and buf->last are positioned at buf->begin +
|
||||
offset. */
|
||||
size_t offset;
|
||||
} nghttp2_bufs;
|
||||
|
||||
/*
|
||||
* This is the same as calling nghttp2_bufs_init2 with the given
|
||||
* arguments and offset = 0.
|
||||
*/
|
||||
int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length,
|
||||
size_t max_chunk);
|
||||
|
||||
/*
|
||||
* Initializes |bufs|. Each buffer size is given in the
|
||||
* |chunk_length|. The maximum number of buffers is given in the
|
||||
* |max_chunk|. Each buffer will have bufs->pos and bufs->last shifted
|
||||
* to left by |offset| bytes on creation and reset.
|
||||
*
|
||||
* This function allocates first buffer. bufs->head and bufs->cur
|
||||
* will point to the first buffer after this call.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_INVALID_ARGUMENT
|
||||
* max_chunk is 0
|
||||
*/
|
||||
int nghttp2_bufs_init2(nghttp2_bufs *bufs, size_t chunk_length,
|
||||
size_t max_chunk, size_t offset);
|
||||
|
||||
/*
|
||||
* Frees any related resources to the |bufs|.
|
||||
*/
|
||||
void nghttp2_bufs_free(nghttp2_bufs *bufs);
|
||||
|
||||
/*
|
||||
* Appends the |data| of length |len| to the |bufs|. The write starts
|
||||
* at bufs->cur->buf.last. A new buffers will be allocated to store
|
||||
* all data.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Out of buffer space.
|
||||
*/
|
||||
int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len);
|
||||
|
||||
/*
|
||||
* Appends a single byte |b| to the |bufs|. The write starts at
|
||||
* bufs->cur->buf.last. A new buffers will be allocated to store all
|
||||
* data.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Out of buffer space.
|
||||
*/
|
||||
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
|
||||
|
||||
/*
|
||||
* Behaves like nghttp2_bufs_addb(), but this does not update
|
||||
* buf->last pointer.
|
||||
*/
|
||||
int nghttp2_bufs_addb_hold(nghttp2_bufs *bufs, uint8_t b);
|
||||
|
||||
#define nghttp2_bufs_fast_addb(BUFS, B) \
|
||||
do { \
|
||||
*(BUFS)->cur->buf.last++ = B; \
|
||||
} while(0)
|
||||
|
||||
#define nghttp2_bufs_fast_addb_hold(BUFS, B) \
|
||||
do { \
|
||||
*(BUFS)->cur->buf.last = B; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Performs bitwise-OR of |b| at bufs->cur->buf.last. A new buffers
|
||||
* will be allocated if necessary.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Out of buffer space.
|
||||
*/
|
||||
int nghttp2_bufs_orb(nghttp2_bufs *bufs, uint8_t b);
|
||||
|
||||
/*
|
||||
* Behaves like nghttp2_bufs_orb(), but does not update buf->last
|
||||
* pointer.
|
||||
*/
|
||||
int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
|
||||
|
||||
#define nghttp2_bufs_fast_orb(BUFS, B) \
|
||||
do { \
|
||||
*(BUFS)->cur->buf.last++ |= B; \
|
||||
} while(0)
|
||||
|
||||
#define nghttp2_bufs_fast_orb_hold(BUFS, B) \
|
||||
do { \
|
||||
*(BUFS)->cur->buf.last |= B; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Copies all data stored in |bufs| to the contagious buffer. This
|
||||
* function allocates the contagious memory to store all data in
|
||||
* |bufs| and assigns it to |*out|.
|
||||
*
|
||||
* On successful return, nghttp2_bufs_len(bufs) returns 0, just like
|
||||
* after calling nghttp2_bufs_reset().
|
||||
|
||||
* This function returns the length of copied data and assigns the
|
||||
* pointer to copied data to |*out| if it succeeds, or one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
|
||||
|
||||
/*
|
||||
* Resets |bufs| and makes the buffers empty.
|
||||
*/
|
||||
void nghttp2_bufs_reset(nghttp2_bufs *bufs);
|
||||
|
||||
/*
|
||||
* Moves bufs->cur to bufs->cur->next. If resulting bufs->cur is
|
||||
* NULL, this function allocates new buffers and bufs->cur points to
|
||||
* it.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Out of buffer space.
|
||||
*/
|
||||
int nghttp2_bufs_advance(nghttp2_bufs *bufs);
|
||||
|
||||
/* Sets bufs->cur to bufs->head */
|
||||
#define nghttp2_bufs_rewind(BUFS) \
|
||||
do { \
|
||||
(BUFS)->cur = (BUFS)->head; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Move bufs->cur, from the current position, using next member, to
|
||||
* the last buf which has nghttp2_buf_len(buf) > 0 without seeing buf
|
||||
* which satisfies nghttp2_buf_len(buf) == 0. If bufs->cur->next is
|
||||
* NULL, bufs->cur is unchanged.
|
||||
*/
|
||||
void nghttp2_bufs_seek_last_present(nghttp2_bufs *bufs);
|
||||
|
||||
/*
|
||||
* Returns nonzero if bufs->cur->next is not emtpy.
|
||||
*/
|
||||
int nghttp2_bufs_next_present(nghttp2_bufs *bufs);
|
||||
|
||||
#define nghttp2_bufs_cur_avail(BUFS) nghttp2_buf_avail(&(BUFS)->cur->buf)
|
||||
|
||||
/*
|
||||
* Returns the buffer length of |bufs|.
|
||||
*/
|
||||
ssize_t nghttp2_bufs_len(nghttp2_bufs *bufs);
|
||||
|
||||
#endif /* NGHTTP2_BUF_H */
|
||||
|
|
|
@ -224,64 +224,109 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame)
|
|||
}
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_headers(nghttp2_buf *buf,
|
||||
/*
|
||||
* Call this function after payload was serialized, but not before
|
||||
* changing buf->pos and serializing frame header.
|
||||
*
|
||||
* This function assumes bufs->cur points to the last buf chain of the
|
||||
* frame(s).
|
||||
*
|
||||
* This function serializes frame header for HEADERS/PUSH_PROMISE and
|
||||
* handles their successive CONTINUATION frames.
|
||||
*
|
||||
* We don't process any padding here.
|
||||
*/
|
||||
static int frame_pack_headers_shared(nghttp2_bufs *bufs,
|
||||
nghttp2_frame_hd *frame_hd)
|
||||
{
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_buf_chain *ci, *ce;
|
||||
nghttp2_frame_hd hd;
|
||||
|
||||
buf = &bufs->head->buf;
|
||||
|
||||
hd = *frame_hd;
|
||||
hd.length = nghttp2_buf_len(buf);
|
||||
|
||||
DEBUGF(fprintf(stderr, "HEADERS/PUSH_PROMISE, payloadlen=%zu\n", hd.length));
|
||||
|
||||
/* We have multiple frame buffers, which means one or more
|
||||
CONTINUATION frame is involved. Remove END_HEADERS flag from the
|
||||
first frame. */
|
||||
if(bufs->head != bufs->cur) {
|
||||
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
}
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
|
||||
if(bufs->head != bufs->cur) {
|
||||
/* 2nd and later frames are CONTINUATION frames. */
|
||||
hd.type = NGHTTP2_CONTINUATION;
|
||||
/* We don't have no flags except for last CONTINUATION */
|
||||
hd.flags = NGHTTP2_FLAG_NONE;
|
||||
|
||||
ce = bufs->cur;
|
||||
|
||||
for(ci = bufs->head->next; ci != ce; ci = ci->next) {
|
||||
buf = &ci->buf;
|
||||
|
||||
hd.length = nghttp2_buf_len(buf);
|
||||
|
||||
DEBUGF(fprintf(stderr, "int CONTINUATION, payloadlen=%zu\n", hd.length));
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
}
|
||||
|
||||
buf = &ci->buf;
|
||||
hd.length = nghttp2_buf_len(buf);
|
||||
/* Set END_HEADERS flag for last CONTINUATION */
|
||||
hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
||||
|
||||
DEBUGF(fprintf(stderr, "last CONTINUATION, payloadlen=%zu\n", hd.length));
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
|
||||
nghttp2_headers *frame,
|
||||
nghttp2_hd_deflater *deflater)
|
||||
{
|
||||
size_t nv_offset;
|
||||
ssize_t rv;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
/* Account for possible PAD_HIGH and PAD_LOW */
|
||||
buf->pos += 2;
|
||||
nv_offset = nghttp2_frame_headers_payload_nv_offset(frame);
|
||||
|
||||
nv_offset =
|
||||
NGHTTP2_FRAME_HDLEN + nghttp2_frame_headers_payload_nv_offset(frame);
|
||||
|
||||
/* If frame->nvlen == 0, nghttp2_buf_len(buf) may be smaller than
|
||||
nv_offset */
|
||||
rv = nghttp2_buf_pos_reserve(buf, nv_offset);
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
buf = &bufs->cur->buf;
|
||||
|
||||
buf->pos += nv_offset;
|
||||
buf->last = buf->pos;
|
||||
|
||||
/* This call will adjust buf->last to the correct position */
|
||||
rv = nghttp2_hd_deflate_hd(deflater, buf, frame->nva, frame->nvlen);
|
||||
rv = nghttp2_hd_deflate_hd(deflater, bufs, frame->nva, frame->nvlen);
|
||||
|
||||
buf->pos -= nv_offset;
|
||||
|
||||
if(rv < 0) {
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
frame->hd.length = nghttp2_frame_headers_payload_nv_offset(frame) + rv;
|
||||
frame->padlen = 0;
|
||||
|
||||
/* Don't use buf->last, since it already points to the end of the
|
||||
frame */
|
||||
memset(buf->pos, 0, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
/* pack frame header after length is determined */
|
||||
if(NGHTTP2_MAX_PAYLOADLEN < frame->hd.length) {
|
||||
/* Needs CONTINUATION */
|
||||
nghttp2_frame_hd hd = frame->hd;
|
||||
|
||||
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
hd.length = NGHTTP2_MAX_PAYLOADLEN;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
} else {
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
}
|
||||
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
nghttp2_put_uint32be(buf->pos + NGHTTP2_FRAME_HDLEN, frame->pri);
|
||||
nghttp2_put_uint32be(buf->pos, frame->pri);
|
||||
}
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
frame->padlen = 0;
|
||||
frame->hd.length = nghttp2_bufs_len(bufs);
|
||||
|
||||
return frame_pack_headers_shared(bufs, &frame->hd);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
|
@ -298,28 +343,21 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_priority(nghttp2_buf *buf,
|
||||
nghttp2_priority *frame)
|
||||
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs, nghttp2_priority *frame)
|
||||
{
|
||||
ssize_t framelen= NGHTTP2_FRAME_HDLEN + 4;
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
buf = &bufs->head->buf;
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->pri);
|
||||
buf->last += 4;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
||||
|
@ -329,28 +367,22 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
|||
frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_rst_stream(nghttp2_buf *buf,
|
||||
int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
|
||||
nghttp2_rst_stream *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HDLEN + 4;
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
buf = &bufs->head->buf;
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->error_code);
|
||||
buf->last += 4;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
||||
|
@ -360,28 +392,26 @@ void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
|||
frame->error_code = nghttp2_get_uint32(payload);
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_settings(nghttp2_buf *buf,
|
||||
nghttp2_settings *frame)
|
||||
int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HDLEN + frame->hd.length;
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
buf = &bufs->head->buf;
|
||||
|
||||
if(nghttp2_buf_avail(buf) < (ssize_t)frame->hd.length) {
|
||||
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
|
||||
}
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
buf->last += nghttp2_frame_pack_settings_payload(buf->last,
|
||||
frame->iv, frame->niv);
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
|
||||
|
@ -436,60 +466,36 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_push_promise(nghttp2_buf *buf,
|
||||
int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
|
||||
nghttp2_push_promise *frame,
|
||||
nghttp2_hd_deflater *deflater)
|
||||
{
|
||||
size_t nv_offset = NGHTTP2_FRAME_HDLEN + 4;
|
||||
size_t nv_offset = 4;
|
||||
ssize_t rv;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
/* Account for possible PAD_HIGH and PAD_LOW */
|
||||
buf->pos += 2;
|
||||
|
||||
/* If frame->nvlen == 0, nghttp2_buf_len(buf) may be smaller than
|
||||
nv_offset */
|
||||
rv = nghttp2_buf_pos_reserve(buf, nv_offset);
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
buf = &bufs->cur->buf;
|
||||
|
||||
buf->pos += nv_offset;
|
||||
buf->last = buf->pos;
|
||||
|
||||
/* This call will adjust buf->last to the correct position */
|
||||
rv = nghttp2_hd_deflate_hd(deflater, buf, frame->nva, frame->nvlen);
|
||||
rv = nghttp2_hd_deflate_hd(deflater, bufs, frame->nva, frame->nvlen);
|
||||
|
||||
buf->pos -= nv_offset;
|
||||
|
||||
if(rv < 0) {
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
frame->hd.length = 4 + rv;
|
||||
nghttp2_put_uint32be(buf->pos, frame->promised_stream_id);
|
||||
|
||||
frame->padlen = 0;
|
||||
frame->hd.length = nghttp2_bufs_len(bufs);
|
||||
|
||||
/* Don't use buf->last, since it already points to the end of the
|
||||
frame */
|
||||
memset(buf->pos, 0, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
/* pack frame header after length is determined */
|
||||
if(NGHTTP2_MAX_PAYLOADLEN < frame->hd.length) {
|
||||
/* Needs CONTINUATION */
|
||||
nghttp2_frame_hd hd = frame->hd;
|
||||
|
||||
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
hd.length = NGHTTP2_MAX_PAYLOADLEN;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
} else {
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
}
|
||||
|
||||
nghttp2_put_uint32be(buf->pos + NGHTTP2_FRAME_HDLEN,
|
||||
frame->promised_stream_id);
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
return frame_pack_headers_shared(bufs, &frame->hd);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
|
@ -503,27 +509,21 @@ int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_ping(nghttp2_buf *buf, nghttp2_ping *frame)
|
||||
int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HDLEN + 8;
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
buf = &bufs->head->buf;
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
buf->last = nghttp2_cpymem(buf->last, frame->opaque_data,
|
||||
sizeof(frame->opaque_data));
|
||||
|
||||
memcpy(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
|
||||
buf->last += sizeof(frame->opaque_data);
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
||||
|
@ -533,22 +533,18 @@ void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
|||
memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data));
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_goaway(nghttp2_buf *buf, nghttp2_goaway *frame)
|
||||
int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HDLEN + frame->hd.length;
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
buf = &bufs->head->buf;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->last_stream_id);
|
||||
buf->last += 4;
|
||||
|
@ -556,10 +552,12 @@ ssize_t nghttp2_frame_pack_goaway(nghttp2_buf *buf, nghttp2_goaway *frame)
|
|||
nghttp2_put_uint32be(buf->last, frame->error_code);
|
||||
buf->last += 4;
|
||||
|
||||
memcpy(buf->last, frame->opaque_data, frame->opaque_data_len);
|
||||
buf->last += frame->opaque_data_len;
|
||||
rv = nghttp2_bufs_add(bufs, frame->opaque_data, frame->opaque_data_len);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
||||
|
@ -573,28 +571,22 @@ void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
|||
frame->opaque_data_len = 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_window_update(nghttp2_buf *buf,
|
||||
int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
|
||||
nghttp2_window_update *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HDLEN + 4;
|
||||
int rv;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
buf = &bufs->head->buf;
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->window_size_increment);
|
||||
buf->last += 4;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
|
@ -737,34 +729,158 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
void nghttp2_frame_set_pad(nghttp2_buf *buf, uint8_t *flags_ptr, size_t padlen)
|
||||
static void frame_set_pad(nghttp2_buf *buf, size_t padlen)
|
||||
{
|
||||
size_t trail_padlen = 0;
|
||||
size_t trail_padlen;
|
||||
|
||||
if(padlen > 256) {
|
||||
uint8_t *p;
|
||||
DEBUGF(fprintf(stderr, "padlen=%zu, shift left 2 bytes\n", padlen));
|
||||
|
||||
memmove(buf->pos - 2, buf->pos, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
buf->pos -= 2;
|
||||
|
||||
buf->pos[3] |= NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW;
|
||||
|
||||
nghttp2_put_uint16be(buf->pos, nghttp2_get_uint16(buf->pos) + padlen);
|
||||
|
||||
trail_padlen = padlen - 2;
|
||||
*flags_ptr |= NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW;
|
||||
|
||||
assert(nghttp2_buf_pos_offset(buf) >= 2);
|
||||
|
||||
/* Consume previous 2 bytes, shifting 2 bytes to the left */
|
||||
nghttp2_buf_shift_left(buf, 2);
|
||||
|
||||
p = buf->pos + NGHTTP2_FRAME_HDLEN;
|
||||
*p++ = trail_padlen >> 8;
|
||||
*p = trail_padlen & 0xff;
|
||||
buf->pos[NGHTTP2_FRAME_HDLEN] = trail_padlen >> 8;
|
||||
buf->pos[NGHTTP2_FRAME_HDLEN + 1] = trail_padlen & 0xff;
|
||||
|
||||
} else if(padlen > 0) {
|
||||
assert(nghttp2_buf_pos_offset(buf) >= 1);
|
||||
DEBUGF(fprintf(stderr, "padlen=%zu, shift left 1 bytes\n", padlen));
|
||||
|
||||
/* Consume previous 1 byte, shifting 1 bytes to the left */
|
||||
nghttp2_buf_shift_left(buf, 1);
|
||||
memmove(buf->pos - 1, buf->pos, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
--buf->pos;
|
||||
|
||||
buf->pos[3] |= NGHTTP2_FLAG_PAD_LOW;
|
||||
|
||||
nghttp2_put_uint16be(buf->pos, nghttp2_get_uint16(buf->pos) + padlen);
|
||||
|
||||
trail_padlen = padlen - 1;
|
||||
*flags_ptr |= NGHTTP2_FLAG_PAD_LOW;
|
||||
buf->pos[NGHTTP2_FRAME_HDLEN] = trail_padlen;
|
||||
|
||||
*(buf->pos + NGHTTP2_FRAME_HDLEN) = trail_padlen;
|
||||
} else {
|
||||
DEBUGF(fprintf(stderr, "padlen=0, no shift left was made\n"));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* zero out padding */
|
||||
memset(buf->last, 0, trail_padlen);
|
||||
/* extend buffers trail_padlen bytes, since we ate previous padlen -
|
||||
trail_padlen byte(s) */
|
||||
buf->last += trail_padlen;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen, nghttp2_frame_type type)
|
||||
{
|
||||
int rv;
|
||||
size_t trail_padlen;
|
||||
size_t last_avail;
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_frame_hd last_hd;
|
||||
|
||||
if(padlen == 0) {
|
||||
DEBUGF(fprintf(stderr, "padlen = 0, nothing to do\n"));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* We have arranged bufs like this:
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | | |Frame header | Frame payload... |
|
||||
* +-+-+---------------+-------------------------------------------+
|
||||
* | | |Frame header | Frame payload... |
|
||||
* +-+-+---------------+-------------------------------------------+
|
||||
* | | |Frame header | Frame payload... |
|
||||
* +-+-+---------------+-------------------------------------------+
|
||||
*
|
||||
* Since we limit the length of the padding bytes, they are
|
||||
* completely included in one frame payload or across 2 frames. We
|
||||
* are going to adjust buf->pos of frame which includes part of
|
||||
* padding. And serialize (memmove) frame header in the correct
|
||||
* position. Also extends buf->last to include padding.
|
||||
*/
|
||||
|
||||
nghttp2_bufs_seek_last_present(bufs);
|
||||
|
||||
buf = &bufs->cur->buf;
|
||||
|
||||
last_avail = nghttp2_buf_avail(buf);
|
||||
|
||||
if(last_avail >= padlen) {
|
||||
/* Last frame can include all paddings bytes */
|
||||
DEBUGF(fprintf(stderr, "last frame includes all paddings\n"));
|
||||
|
||||
frame_set_pad(buf, padlen);
|
||||
|
||||
} else {
|
||||
/* padding across 2 frames */
|
||||
|
||||
/* type = DATA must not be here */
|
||||
assert(type == NGHTTP2_CONTINUATION);
|
||||
|
||||
/* This will seek to the last chain */
|
||||
rv = nghttp2_bufs_advance(bufs);
|
||||
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
|
||||
return NGHTTP2_ERR_FRAME_SIZE_ERROR;
|
||||
}
|
||||
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if(type == NGHTTP2_CONTINUATION) {
|
||||
/* former last frame has END_HEADERS flag set. Clear it. */
|
||||
buf->pos[3] &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
}
|
||||
|
||||
trail_padlen = nghttp2_buf_avail(buf);
|
||||
|
||||
/* former last frame may have zero buffer available */
|
||||
if(trail_padlen == 0) {
|
||||
DEBUGF(fprintf(stderr, "last frame has no space to include padding\n"));
|
||||
} else {
|
||||
DEBUGF(fprintf(stderr, "padding across 2 frames\n"));
|
||||
|
||||
frame_set_pad(buf, trail_padlen);
|
||||
}
|
||||
|
||||
/* This buffer does not have frame header serialized */
|
||||
buf = &bufs->cur->buf;
|
||||
|
||||
trail_padlen = padlen - trail_padlen;
|
||||
|
||||
last_hd.length = 0;
|
||||
last_hd.type = type;
|
||||
last_hd.stream_id = hd->stream_id;
|
||||
|
||||
if(type == NGHTTP2_CONTINUATION) {
|
||||
last_hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
||||
} else {
|
||||
last_hd.flags = NGHTTP2_FLAG_NONE;
|
||||
}
|
||||
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &last_hd);
|
||||
|
||||
frame_set_pad(buf, trail_padlen);
|
||||
}
|
||||
|
||||
hd->length += padlen;
|
||||
|
||||
DEBUGF(fprintf(stderr, "final payloadlen=%zu, padlen=%zu\n",
|
||||
hd->length, padlen));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -39,17 +39,21 @@
|
|||
#define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK ((1u << 31) - 1)
|
||||
#define NGHTTP2_SETTINGS_ID_MASK ((1 << 24) - 1)
|
||||
|
||||
/* The maximum payload length of a frame TODO: Must be renamed as
|
||||
NGHTTP2_MAX_PAYLOAD_LENGTH */
|
||||
#define NGHTTP2_MAX_PAYLOADLEN ((1 << 14) - 1)
|
||||
/* The number of bytes of frame header. */
|
||||
#define NGHTTP2_FRAME_HDLEN 8
|
||||
|
||||
/* The maximum frame and payload length. The spec allows maximum
|
||||
payload length up to 16383 bytes. Due to efficient buffer
|
||||
allocation, we choose smaller buffer. Actual payload limit offsets
|
||||
frame header and possible PAD_HIGH and PAD_LOW to ease
|
||||
serialization and save memcopying. */
|
||||
#define NGHTTP2_MAX_FRAMELEN 8192
|
||||
#define NGHTTP2_MAX_PAYLOADLEN (NGHTTP2_MAX_FRAMELEN - NGHTTP2_FRAME_HDLEN - 2)
|
||||
|
||||
/* The maximum length of DATA frame payload. To fit entire DATA frame
|
||||
into 4096K buffer, we use subtract header size (8 bytes) + 2 bytes
|
||||
padding. See nghttp2_session_pack_data(). */
|
||||
#define NGHTTP2_DATA_PAYLOAD_LENGTH 4086
|
||||
|
||||
/* The number of bytes of frame header. */
|
||||
#define NGHTTP2_FRAME_HDLEN 8
|
||||
#define NGHTTP2_DATA_PAYLOAD_LENGTH (4096 - NGHTTP2_FRAME_HDLEN - 2)
|
||||
|
||||
/* The number of bytes for each SETTINGS entry */
|
||||
#define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 5
|
||||
|
@ -101,31 +105,27 @@ void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t* buf);
|
|||
size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
|
||||
|
||||
/*
|
||||
* Packs HEADERS frame |frame| in wire format and store it in |buf|.
|
||||
* This function expands |buf| as necessary to store frame. The caller
|
||||
* must make sure that nghttp2_buf_len(buf) == 0 holds when calling
|
||||
* this function.
|
||||
* Packs HEADERS frame |frame| in wire format and store it in |bufs|.
|
||||
* This function expands |bufs| as necessary to store frame.
|
||||
*
|
||||
* The first byte the frame is serialized is returned in the |buf|.
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* frame->hd.length is assigned after length is determined during
|
||||
* packing process. If payload length is strictly larger than
|
||||
* NGHTTP2_MAX_PAYLOADLEN, payload data is still serialized as is, but
|
||||
* serialized header's payload length is set to NGHTTP2_MAX_PAYLOADLEN
|
||||
* and NGHTTP2_FLAG_END_HEADERS flag is cleared.
|
||||
* packing process. CONTINUATION frames are also serialized in this
|
||||
* function. This function does not handle padding.
|
||||
*
|
||||
* This function returns the size of packed frame (which equals to
|
||||
* nghttp2_buf_len(buf)) if it succeeds, or returns one of the
|
||||
* This function returns 0 if it succeeds, or returns one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* The deflate operation failed.
|
||||
* NGHTTP2_ERR_FRAME_TOO_LARGE
|
||||
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||
* The length of the frame is too large.
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_headers(nghttp2_buf *buf,
|
||||
int nghttp2_frame_pack_headers(nghttp2_bufs *bufs,
|
||||
nghttp2_headers *frame,
|
||||
nghttp2_hd_deflater *deflater);
|
||||
|
||||
|
@ -145,8 +145,10 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
|||
|
||||
/*
|
||||
* Packs PRIORITY frame |frame| in wire format and store it in
|
||||
* |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
* |bufs|.
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
|
@ -154,7 +156,7 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_priority(nghttp2_buf *buf,
|
||||
int nghttp2_frame_pack_priority(nghttp2_bufs *bufs,
|
||||
nghttp2_priority *frame);
|
||||
|
||||
/*
|
||||
|
@ -166,16 +168,18 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
|||
|
||||
/*
|
||||
* Packs RST_STREAM frame |frame| in wire frame format and store it in
|
||||
* |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
* |bufs|.
|
||||
*
|
||||
* This function returns the size of packed frame if it succeeds, or
|
||||
* returns one of the following negative error codes:
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or returns one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_rst_stream(nghttp2_buf *buf,
|
||||
int nghttp2_frame_pack_rst_stream(nghttp2_bufs *bufs,
|
||||
nghttp2_rst_stream *frame);
|
||||
|
||||
/*
|
||||
|
@ -187,17 +191,20 @@ void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
|||
|
||||
/*
|
||||
* Packs SETTINGS frame |frame| in wire format and store it in
|
||||
* |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
* |bufs|.
|
||||
*
|
||||
* This function returns the size of packed frame if it succeeds, or
|
||||
* returns one of the following negative error codes:
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or returns one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||
* The length of the frame is too large.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_settings(nghttp2_buf *buf,
|
||||
nghttp2_settings *frame);
|
||||
int nghttp2_frame_pack_settings(nghttp2_bufs *bufs, nghttp2_settings *frame);
|
||||
|
||||
/*
|
||||
* Packs the |iv|, which includes |niv| entries, in the |buf|,
|
||||
|
@ -245,30 +252,27 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
|||
|
||||
/*
|
||||
* Packs PUSH_PROMISE frame |frame| in wire format and store it in
|
||||
* |buf|. This function expands |buf| as necessary to store
|
||||
* frame. The caller must make sure that nghttp2_buf_len(buf) == 0
|
||||
* holds when calling this function.
|
||||
* |bufs|. This function expands |bufs| as necessary to store
|
||||
* frame.
|
||||
*
|
||||
* The first byte the frame is serialized is returned in the |buf|.
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* frame->hd.length is assigned after length is determined during
|
||||
* packing process. If payload length is strictly larger than
|
||||
* NGHTTP2_MAX_PAYLOADLEN, payload data is still serialized as is, but
|
||||
* serialized header's payload length is set to NGHTTP2_MAX_PAYLOADLEN
|
||||
* and NGHTTP2_FLAG_END_HEADERS flag is cleared.
|
||||
* packing process. CONTINUATION frames are also serialized in this
|
||||
* function. This function does not handle padding.
|
||||
*
|
||||
* This function returns the size of packed frame (which equals to
|
||||
* nghttp2_buf_len(buf)) if it succeeds, or returns one of the
|
||||
* This function returns 0 if it succeeds, or returns one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* The deflate operation failed.
|
||||
* NGHTTP2_ERR_FRAME_TOO_LARGE
|
||||
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||
* The length of the frame is too large.
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_push_promise(nghttp2_buf *buf,
|
||||
int nghttp2_frame_pack_push_promise(nghttp2_bufs *bufs,
|
||||
nghttp2_push_promise *frame,
|
||||
nghttp2_hd_deflater *deflater);
|
||||
|
||||
|
@ -287,8 +291,11 @@ int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
|||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs PING frame |frame| in wire format and store it in |buf|. This
|
||||
* function expands |buf| as necessary to store given |frame|.
|
||||
* Packs PING frame |frame| in wire format and store it in
|
||||
* |bufs|.
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
|
@ -296,7 +303,7 @@ int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_ping(nghttp2_buf *buf, nghttp2_ping *frame);
|
||||
int nghttp2_frame_pack_ping(nghttp2_bufs *bufs, nghttp2_ping *frame);
|
||||
|
||||
/*
|
||||
* Unpacks PING wire format into |frame|.
|
||||
|
@ -306,17 +313,21 @@ void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
|||
size_t payloadlen);
|
||||
|
||||
/*
|
||||
* Packs GOAWAY frame |frame | in wire format and store it in
|
||||
* |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
* Packs GOAWAY frame |frame| in wire format and store it in |bufs|.
|
||||
* This function expands |bufs| as necessary to store frame.
|
||||
*
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_FRAME_SIZE_ERROR
|
||||
* The length of the frame is too large.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_goaway(nghttp2_buf *buf, nghttp2_goaway *frame);
|
||||
int nghttp2_frame_pack_goaway(nghttp2_bufs *bufs, nghttp2_goaway *frame);
|
||||
|
||||
/*
|
||||
* Unpacks GOAWAY wire format into |frame|.
|
||||
|
@ -327,16 +338,18 @@ void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
|||
|
||||
/*
|
||||
* Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
|
||||
* in |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
* in |bufs|.
|
||||
*
|
||||
* This function returns the size of packed frame if it succeeds, or
|
||||
* returns one of the following negative error codes:
|
||||
* The caller must make sure that nghttp2_bufs_reset(bufs) is called
|
||||
* before calling this function.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or returns one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_window_update(nghttp2_buf *buf,
|
||||
int nghttp2_frame_pack_window_update(nghttp2_bufs *bufs,
|
||||
nghttp2_window_update *frame);
|
||||
|
||||
/*
|
||||
|
@ -486,66 +499,21 @@ void nghttp2_nv_array_del(nghttp2_nv *nva);
|
|||
int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
||||
|
||||
/*
|
||||
* Sets PAD_HIGH and PAD_LOW fields, flags and adjust buf->pos and
|
||||
* buf->last accordingly based on given padding length. The padding is
|
||||
* given in the |padlen|.
|
||||
* Sets PAD_HIGH and PAD_LOW fields, flags and adjust frame header
|
||||
* position of each buffers in |bufs|. The padding is given in the
|
||||
* |padlen|. The |hd| is the frame header for the serialized data.
|
||||
* The |type| is used as a frame type when padding requires additional
|
||||
* buffers.
|
||||
*
|
||||
* The |*flags_ptr| is updated to include NGHTTP2_FLAG_PAD_LOW and
|
||||
* NGHTTP2_FLAG_PAD_HIGH based on the padding length.
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* This function does not allocate memory at all.
|
||||
*
|
||||
* The padding specifier PAD_HIGH and PAD_LOW are located right after
|
||||
* the frame header. But they may not be there depending of the length
|
||||
* of the padding. To save the additional buffer copy, we shift
|
||||
* buf->pos to 2 bytes right before this call. Depending of the length
|
||||
* of the padding, we shift left buf->pos and buf->last. If more than
|
||||
* or equal to 256 padding is made, 2 left shift is done |buf| looks
|
||||
* like this:
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Frame header ...
|
||||
* +---------------------------------------------------------------+
|
||||
* . Frame header |
|
||||
* +---------------+---------------+-------------------------------+
|
||||
* | Pad high | Pad low | Payload ...
|
||||
* +---------------+---------------+-------------------------------+
|
||||
*
|
||||
*
|
||||
* If padding is less than 256 but strictly more than 0, the |buf| is
|
||||
* 1 left shift and the |buf| looks like this:
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Unused | Frame header ...
|
||||
* +---------------+-----------------------------------------------+
|
||||
* . Frame header ...
|
||||
* +---------------+---------------+-------------------------------+
|
||||
* . Frame Header | Pad low | Payload ...
|
||||
* +---------------+---------------+-------------------------------+
|
||||
*
|
||||
* If no padding is added, no shift is done and the |buf| looks like
|
||||
* this:
|
||||
*
|
||||
* 0 1 2 3
|
||||
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
* | Unused | Frame header ...
|
||||
* +-------------------------------+-------------------------------+
|
||||
* . Frame header ...
|
||||
* +-------------------------------+-------------------------------+
|
||||
* . Frame Header | Payload ...
|
||||
* +-------------------------------+-------------------------------+
|
||||
*
|
||||
* Notice that the position of payload does not change. This way, we
|
||||
* can set PAD_HIGH and PAD_LOW after payload was serialized and no
|
||||
* additional copy operation is required (if the |buf| is large enough
|
||||
* to account the additional padding, of course).
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Out of buffer space. This is not a fatal.
|
||||
*/
|
||||
void nghttp2_frame_set_pad(nghttp2_buf *buf, uint8_t *flags_ptr,
|
||||
size_t padlen);
|
||||
int nghttp2_frame_add_pad(nghttp2_bufs *bufs, nghttp2_frame_hd *hd,
|
||||
size_t padlen, nghttp2_frame_type type);
|
||||
|
||||
#endif /* NGHTTP2_FRAME_H */
|
||||
|
|
220
lib/nghttp2_hd.c
220
lib/nghttp2_hd.c
|
@ -421,24 +421,6 @@ static int emit_literal_header(nghttp2_nv *nv_out, nghttp2_nv *nv)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ensure_write_buffer(nghttp2_buf *buf, size_t need)
|
||||
{
|
||||
int rv;
|
||||
|
||||
need += nghttp2_buf_last_offset(buf);
|
||||
|
||||
if(need > NGHTTP2_HD_MAX_BUFFER_LENGTH) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
rv = nghttp2_buf_reserve(buf, need);
|
||||
if(rv != 0) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t count_encoded_length(size_t n, int prefix)
|
||||
{
|
||||
size_t k = (1 << prefix) - 1;
|
||||
|
@ -545,90 +527,116 @@ static uint8_t* decode_length(ssize_t *res, int *final, ssize_t initial,
|
|||
return in + 1;
|
||||
}
|
||||
|
||||
static int emit_clear_refset(nghttp2_buf *buf)
|
||||
static int nghttp2_hd_handle_buffer_error(int rv)
|
||||
{
|
||||
if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
static int emit_clear_refset(nghttp2_bufs *bufs)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *bufp;
|
||||
uint8_t sb[] = {0x80u, 0x80u};
|
||||
|
||||
rv = ensure_write_buffer(buf, 2);
|
||||
rv = nghttp2_bufs_add(bufs, sb, sizeof(sb));
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
return nghttp2_hd_handle_buffer_error(rv);
|
||||
}
|
||||
|
||||
bufp = buf->last;
|
||||
*bufp++ = 0x80u;
|
||||
*bufp++ = 0x80u;
|
||||
|
||||
buf->last = bufp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emit_table_size(nghttp2_buf *buf, size_t table_size)
|
||||
static int emit_table_size(nghttp2_bufs *bufs, size_t table_size)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *bufp;
|
||||
size_t blocklen;
|
||||
uint8_t sb[16];
|
||||
|
||||
blocklen = 1 + count_encoded_length(table_size, 7);
|
||||
|
||||
rv = ensure_write_buffer(buf, blocklen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
if(sizeof(sb) < blocklen) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
DEBUGF(fprintf(stderr, "emit table_size=%zu\n", table_size));
|
||||
|
||||
bufp = buf->last;
|
||||
bufp = sb;
|
||||
|
||||
*bufp++ = 0x80u;
|
||||
*bufp = 0;
|
||||
encode_length(bufp, table_size, 7);
|
||||
|
||||
buf->last += blocklen;
|
||||
rv = nghttp2_bufs_add(bufs, sb, blocklen);
|
||||
if(rv != 0) {
|
||||
return nghttp2_hd_handle_buffer_error(rv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emit_indexed_block(nghttp2_buf *buf, size_t index)
|
||||
static int emit_indexed_block(nghttp2_bufs *bufs, size_t index)
|
||||
{
|
||||
int rv;
|
||||
size_t blocklen;
|
||||
uint8_t sb[16];
|
||||
uint8_t *bufp;
|
||||
|
||||
blocklen = count_encoded_length(index + 1, 7);
|
||||
|
||||
rv = ensure_write_buffer(buf, blocklen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
if(sizeof(sb) < blocklen) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
*buf->last = 0x80u;
|
||||
encode_length(buf->last, index + 1, 7);
|
||||
bufp = sb;
|
||||
*bufp = 0x80u;
|
||||
encode_length(bufp, index + 1, 7);
|
||||
|
||||
buf->last += blocklen;
|
||||
rv = nghttp2_bufs_add(bufs, sb, blocklen);
|
||||
if(rv != 0) {
|
||||
return nghttp2_hd_handle_buffer_error(rv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t emit_string(uint8_t *buf, size_t buflen,
|
||||
static int emit_string(nghttp2_bufs *bufs,
|
||||
size_t enclen, int huffman,
|
||||
const uint8_t *str, size_t len)
|
||||
{
|
||||
size_t rv;
|
||||
uint8_t sb[16];
|
||||
uint8_t *bufp;
|
||||
size_t blocklen;
|
||||
|
||||
blocklen = count_encoded_length(enclen, 7);
|
||||
|
||||
if(sizeof(sb) < blocklen) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
bufp = sb;
|
||||
*bufp = huffman ? 1 << 7 : 0;
|
||||
rv = encode_length(bufp, enclen, 7);
|
||||
|
||||
rv = nghttp2_bufs_add(bufs, sb, blocklen);
|
||||
if(rv != 0) {
|
||||
return nghttp2_hd_handle_buffer_error(rv);
|
||||
}
|
||||
|
||||
*buf = huffman ? 1 << 7 : 0;
|
||||
rv = encode_length(buf, enclen, 7);
|
||||
buf += rv;
|
||||
if(huffman) {
|
||||
nghttp2_hd_huff_encode(buf, buflen - rv, str, len);
|
||||
rv = nghttp2_hd_huff_encode(bufs, str, len);
|
||||
} else {
|
||||
assert(enclen == len);
|
||||
memcpy(buf, str, len);
|
||||
rv = nghttp2_bufs_add(bufs, str, len);
|
||||
}
|
||||
return rv + enclen;
|
||||
|
||||
return nghttp2_hd_handle_buffer_error(rv);
|
||||
}
|
||||
|
||||
static int emit_indname_block(nghttp2_buf *buf, size_t index,
|
||||
static int emit_indname_block(nghttp2_bufs *bufs, size_t index,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
int inc_indexing)
|
||||
{
|
||||
|
@ -637,6 +645,7 @@ static int emit_indname_block(nghttp2_buf *buf, size_t index,
|
|||
size_t encvallen;
|
||||
size_t blocklen;
|
||||
int huffman;
|
||||
uint8_t sb[16];
|
||||
|
||||
encvallen = nghttp2_hd_huff_encode_count(value, valuelen);
|
||||
blocklen = count_encoded_length(index + 1, 6);
|
||||
|
@ -646,41 +655,39 @@ static int emit_indname_block(nghttp2_buf *buf, size_t index,
|
|||
encvallen = valuelen;
|
||||
}
|
||||
|
||||
blocklen += count_encoded_length(encvallen, 7) + encvallen;
|
||||
if(sizeof(sb) < blocklen) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
rv = ensure_write_buffer(buf, blocklen);
|
||||
bufp = sb;
|
||||
|
||||
*bufp = inc_indexing ? 0 : 0x40u;
|
||||
bufp += encode_length(bufp, index + 1, 6);
|
||||
|
||||
rv = nghttp2_bufs_add(bufs, sb, blocklen);
|
||||
if(rv != 0) {
|
||||
return nghttp2_hd_handle_buffer_error(rv);
|
||||
}
|
||||
|
||||
rv = emit_string(bufs, encvallen, huffman, value, valuelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bufp = buf->last;
|
||||
|
||||
*bufp = inc_indexing ? 0 : 0x40u;
|
||||
bufp += encode_length(bufp, index + 1, 6);
|
||||
bufp += emit_string(bufp, buf->end - bufp,
|
||||
encvallen, huffman, value, valuelen);
|
||||
|
||||
assert(bufp - buf->last == (ssize_t)blocklen);
|
||||
|
||||
buf->last = bufp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emit_newname_block(nghttp2_buf *buf, nghttp2_nv *nv,
|
||||
static int emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
|
||||
int inc_indexing)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *bufp;
|
||||
size_t encnamelen;
|
||||
size_t encvallen;
|
||||
size_t blocklen;
|
||||
int name_huffman;
|
||||
int value_huffman;
|
||||
|
||||
encnamelen = nghttp2_hd_huff_encode_count(nv->name, nv->namelen);
|
||||
encvallen = nghttp2_hd_huff_encode_count(nv->value, nv->valuelen);
|
||||
blocklen = 1;
|
||||
name_huffman = encnamelen < nv->namelen;
|
||||
value_huffman = encvallen < nv->valuelen;
|
||||
|
||||
|
@ -691,25 +698,20 @@ static int emit_newname_block(nghttp2_buf *buf, nghttp2_nv *nv,
|
|||
encvallen = nv->valuelen;
|
||||
}
|
||||
|
||||
blocklen += count_encoded_length(encnamelen, 7) + encnamelen +
|
||||
count_encoded_length(encvallen, 7) + encvallen;
|
||||
rv = nghttp2_bufs_addb(bufs, inc_indexing ? 0 : 0x40u);
|
||||
if(rv != 0) {
|
||||
return nghttp2_hd_handle_buffer_error(rv);
|
||||
}
|
||||
|
||||
rv = ensure_write_buffer(buf, blocklen);
|
||||
rv = emit_string(bufs, encnamelen, name_huffman, nv->name, nv->namelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bufp = buf->last;
|
||||
|
||||
*bufp++ = inc_indexing ? 0 : 0x40u;
|
||||
bufp += emit_string(bufp, buf->end - bufp,
|
||||
encnamelen, name_huffman, nv->name, nv->namelen);
|
||||
bufp += emit_string(bufp, buf->end - bufp,
|
||||
encvallen, value_huffman, nv->value, nv->valuelen);
|
||||
|
||||
assert(bufp - buf->last == (ssize_t)blocklen);
|
||||
|
||||
buf->last = bufp;
|
||||
rv = emit_string(bufs, encvallen, value_huffman, nv->value, nv->valuelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -718,12 +720,12 @@ static int emit_newname_block(nghttp2_buf *buf, nghttp2_nv *nv,
|
|||
* Emit common header with |index| by toggle off and on (thus 2
|
||||
* indexed representation emissions).
|
||||
*/
|
||||
static int emit_implicit(nghttp2_buf *buf, size_t index)
|
||||
static int emit_implicit(nghttp2_bufs *bufs, size_t index)
|
||||
{
|
||||
int i, rv;
|
||||
|
||||
for(i = 0; i < 2; ++i) {
|
||||
rv = emit_indexed_block(buf, index);
|
||||
rv = emit_indexed_block(bufs, index);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -732,7 +734,7 @@ static int emit_implicit(nghttp2_buf *buf, size_t index)
|
|||
}
|
||||
|
||||
static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
|
||||
nghttp2_buf *buf,
|
||||
nghttp2_bufs *bufs,
|
||||
nghttp2_nv *nv,
|
||||
uint8_t entry_flags)
|
||||
{
|
||||
|
@ -754,7 +756,7 @@ static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
|
|||
/* Emit common header just before it slips away from the
|
||||
table. If we don't do this, we have to emit it in literal
|
||||
representation which hurts compression. */
|
||||
rv = emit_implicit(buf, index);
|
||||
rv = emit_implicit(bufs, index);
|
||||
if(rv != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -974,7 +976,7 @@ static int hd_deflate_should_indexing(nghttp2_hd_deflater *deflater,
|
|||
}
|
||||
|
||||
static int deflate_nv(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_buf *buf, nghttp2_nv *nv)
|
||||
nghttp2_bufs *bufs, nghttp2_nv *nv)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_hd_entry *ent;
|
||||
|
@ -992,7 +994,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
/* It is important to first add entry to the header table and
|
||||
let eviction go. If NGHTTP2_HD_FLAG_IMPLICIT_EMIT entry is
|
||||
evicted, it must be emitted before the |nv|. */
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, buf, &ent->nv,
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, bufs, &ent->nv,
|
||||
NGHTTP2_HD_FLAG_NONE);
|
||||
if(!new_ent) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
|
@ -1006,13 +1008,13 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
set */
|
||||
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
|
||||
}
|
||||
rv = emit_indexed_block(buf, index);
|
||||
rv = emit_indexed_block(bufs, index);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
} else if((ent->flags & NGHTTP2_HD_FLAG_REFSET) == 0) {
|
||||
ent->flags |= NGHTTP2_HD_FLAG_REFSET | NGHTTP2_HD_FLAG_EMIT;
|
||||
rv = emit_indexed_block(buf, index);
|
||||
rv = emit_indexed_block(bufs, index);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1042,7 +1044,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
ent->flags |= NGHTTP2_HD_FLAG_IMPLICIT_EMIT;
|
||||
}
|
||||
for(; num_emits > 0; --num_emits) {
|
||||
rv = emit_indexed_block(buf, index);
|
||||
rv = emit_indexed_block(bufs, index);
|
||||
if(rv != 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -1060,10 +1062,10 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
nghttp2_nv nv_indname;
|
||||
nv_indname = *nv;
|
||||
nv_indname.name = nghttp2_hd_table_get(&deflater->ctx, index)->nv.name;
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, buf, &nv_indname,
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, bufs, &nv_indname,
|
||||
NGHTTP2_HD_FLAG_VALUE_ALLOC);
|
||||
} else {
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, buf, nv,
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, bufs, nv,
|
||||
NGHTTP2_HD_FLAG_NAME_ALLOC |
|
||||
NGHTTP2_HD_FLAG_VALUE_ALLOC);
|
||||
}
|
||||
|
@ -1081,9 +1083,9 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
incidx = 1;
|
||||
}
|
||||
if(index == -1) {
|
||||
rv = emit_newname_block(buf, nv, incidx);
|
||||
rv = emit_newname_block(bufs, nv, incidx);
|
||||
} else {
|
||||
rv = emit_indname_block(buf, index, nv->value, nv->valuelen, incidx);
|
||||
rv = emit_indname_block(bufs, index, nv->value, nv->valuelen, incidx);
|
||||
}
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
|
@ -1094,7 +1096,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
|
||||
static int deflate_post_process_hd_entry(nghttp2_hd_entry *ent,
|
||||
size_t index,
|
||||
nghttp2_buf *buf)
|
||||
nghttp2_bufs *bufs)
|
||||
{
|
||||
int rv;
|
||||
|
||||
|
@ -1105,7 +1107,7 @@ static int deflate_post_process_hd_entry(nghttp2_hd_entry *ent,
|
|||
be removed. */
|
||||
ent->flags ^= NGHTTP2_HD_FLAG_REFSET;
|
||||
|
||||
rv = emit_indexed_block(buf, index);
|
||||
rv = emit_indexed_block(bufs, index);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1116,22 +1118,20 @@ static int deflate_post_process_hd_entry(nghttp2_hd_entry *ent,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_buf *buf,
|
||||
int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_bufs *bufs,
|
||||
nghttp2_nv *nv, size_t nvlen)
|
||||
{
|
||||
size_t i;
|
||||
int rv = 0;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
if(deflater->ctx.bad) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
|
||||
if(deflater->ctx.hd_table_bufsize_max >
|
||||
deflater->deflate_hd_table_bufsize_max) {
|
||||
rv = emit_table_size(buf, deflater->deflate_hd_table_bufsize_max);
|
||||
rv = emit_table_size(bufs, deflater->deflate_hd_table_bufsize_max);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1140,14 +1140,14 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
|||
}
|
||||
|
||||
if(deflater->no_refset) {
|
||||
rv = emit_clear_refset(buf);
|
||||
rv = emit_clear_refset(bufs);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
clear_refset(&deflater->ctx);
|
||||
}
|
||||
for(i = 0; i < nvlen; ++i) {
|
||||
rv = deflate_nv(deflater, buf, &nv[i]);
|
||||
rv = deflate_nv(deflater, bufs, &nv[i]);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1155,13 +1155,13 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
|||
for(i = 0; i < deflater->ctx.hd_table.len; ++i) {
|
||||
nghttp2_hd_entry *ent = nghttp2_hd_ringbuf_get(&deflater->ctx.hd_table, i);
|
||||
|
||||
rv = deflate_post_process_hd_entry(ent, i, buf);
|
||||
rv = deflate_post_process_hd_entry(ent, i, bufs);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
return 0;
|
||||
fail:
|
||||
deflater->ctx.bad = 1;
|
||||
return rv;
|
||||
|
@ -1788,20 +1788,20 @@ int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_buf *buf, size_t index,
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
int inc_indexing)
|
||||
{
|
||||
return emit_indname_block(buf, index, value, valuelen, inc_indexing);
|
||||
return emit_indname_block(bufs, index, value, valuelen, inc_indexing);
|
||||
}
|
||||
|
||||
int nghttp2_hd_emit_newname_block(nghttp2_buf *buf, nghttp2_nv *nv,
|
||||
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
|
||||
int inc_indexing)
|
||||
{
|
||||
return emit_newname_block(buf, nv, inc_indexing);
|
||||
return emit_newname_block(bufs, nv, inc_indexing);
|
||||
}
|
||||
|
||||
int nghttp2_hd_emit_table_size(nghttp2_buf *buf, size_t table_size)
|
||||
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size)
|
||||
{
|
||||
return emit_table_size(buf, table_size);
|
||||
return emit_table_size(bufs, table_size);
|
||||
}
|
||||
|
|
|
@ -295,28 +295,28 @@ int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
|
|||
|
||||
/*
|
||||
* Deflates the |nva|, which has the |nvlen| name/value pairs, into
|
||||
* the buffer pointed by the |buf|. The caller must ensure that
|
||||
* nghttp2_buf_len(buf) == 0 holds. Write starts at buf->last.
|
||||
* the |bufs|.
|
||||
*
|
||||
* This function expands |buf| as necessary to store the result.
|
||||
* This function expands |bufs| as necessary to store the result. If
|
||||
* buffers is full and the process still requires more space, this
|
||||
* funtion fails and returns NGHTTP2_ERR_HEADER_COMP.
|
||||
*
|
||||
* This function copies necessary data into |buf|. After this function
|
||||
* returns, it is safe to delete the |nva|.
|
||||
* After this function returns, it is safe to delete the |nva|.
|
||||
*
|
||||
* TODO: The rest of the code call nghttp2_hd_end_headers() after this
|
||||
* call, but it is just a regacy of the first implementation. Now it
|
||||
* is not required to be called as of now.
|
||||
*
|
||||
* This function returns the number of bytes outputted if it succeeds,
|
||||
* or one of the following negative error codes:
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Deflation process has failed.
|
||||
*/
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_buf *buf,
|
||||
int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_bufs *bufs,
|
||||
nghttp2_nv *nva, size_t nvlen);
|
||||
|
||||
typedef enum {
|
||||
|
@ -369,16 +369,16 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
|||
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_buf *buf, size_t index,
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
int inc_indexing);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_newname_block(nghttp2_buf *buf, nghttp2_nv *nv,
|
||||
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
|
||||
int inc_indexing);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_table_size(nghttp2_buf *buf, size_t table_size);
|
||||
int nghttp2_hd_emit_table_size(nghttp2_bufs *bufs, size_t table_size);
|
||||
|
||||
/* For unittesting purpose */
|
||||
nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
|
||||
|
@ -396,18 +396,18 @@ nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
|
|||
size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len);
|
||||
|
||||
/*
|
||||
* Encodes the given data |src| with length |srclen| to the given
|
||||
* memory location pointed by |dest|, allocated at lest |destlen|
|
||||
* bytes. The caller is responsible to specify |destlen| at least the
|
||||
* length that nghttp2_hd_huff_encode_count() returns.
|
||||
* Encodes the given data |src| with length |srclen| to the |bufs|.
|
||||
* This function expands extra buffers in |bufs| if necessary.
|
||||
*
|
||||
* This function returns the number of written bytes, including
|
||||
* padding of prefix of terminal symbol code. This return value is
|
||||
* exactly the same with the return value of
|
||||
* nghttp2_hd_huff_encode_count() if it is given with the same |src|
|
||||
* and |srclen|. This function always succeeds.
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_BUFFER_ERROR
|
||||
* Out of buffer space.
|
||||
*/
|
||||
ssize_t nghttp2_hd_huff_encode(uint8_t *dest, size_t destlen,
|
||||
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs,
|
||||
const uint8_t *src, size_t srclen);
|
||||
|
||||
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
|
||||
|
|
|
@ -40,24 +40,60 @@ extern const nghttp2_huff_decode huff_decode_table[][16];
|
|||
* and points where next output should be placed. The number of
|
||||
* unfilled bits in the pointed location is returned.
|
||||
*/
|
||||
static size_t huff_encode_sym(uint8_t **dest_ptr, size_t rembits,
|
||||
static ssize_t huff_encode_sym(nghttp2_bufs *bufs, size_t *avail_ptr,
|
||||
size_t rembits,
|
||||
const nghttp2_huff_sym *sym)
|
||||
{
|
||||
int rv;
|
||||
size_t nbits = sym->nbits;
|
||||
|
||||
for(;;) {
|
||||
if(rembits > nbits) {
|
||||
**dest_ptr |= sym->code << (rembits - nbits);
|
||||
if(*avail_ptr) {
|
||||
nghttp2_bufs_fast_orb_hold(bufs, sym->code << (rembits - nbits));
|
||||
} else {
|
||||
rv = nghttp2_bufs_orb_hold(bufs, sym->code << (rembits - nbits));
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
}
|
||||
|
||||
rembits -= nbits;
|
||||
|
||||
break;
|
||||
}
|
||||
**dest_ptr |= sym->code >> (nbits - rembits);
|
||||
++*dest_ptr;
|
||||
|
||||
if(*avail_ptr) {
|
||||
nghttp2_bufs_fast_orb(bufs, sym->code >> (nbits - rembits));
|
||||
--*avail_ptr;
|
||||
} else {
|
||||
rv = nghttp2_bufs_orb(bufs, sym->code >> (nbits - rembits));
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
}
|
||||
|
||||
nbits -= rembits;
|
||||
rembits = 8;
|
||||
|
||||
if(nbits == 0) {
|
||||
break;
|
||||
}
|
||||
**dest_ptr = 0;
|
||||
|
||||
if(*avail_ptr) {
|
||||
nghttp2_bufs_fast_addb_hold(bufs, 0);
|
||||
} else {
|
||||
rv = nghttp2_bufs_addb_hold(bufs, 0);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*avail_ptr = nghttp2_bufs_cur_avail(bufs);
|
||||
}
|
||||
}
|
||||
return rembits;
|
||||
}
|
||||
|
@ -74,27 +110,50 @@ size_t nghttp2_hd_huff_encode_count(const uint8_t *src, size_t len)
|
|||
return (nbits + 7) / 8;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_huff_encode(uint8_t *dest, size_t destlen,
|
||||
int nghttp2_hd_huff_encode(nghttp2_bufs *bufs,
|
||||
const uint8_t *src, size_t srclen)
|
||||
{
|
||||
int rv;
|
||||
int rembits = 8;
|
||||
uint8_t *dest_first = dest;
|
||||
size_t i;
|
||||
size_t avail;
|
||||
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
|
||||
for(i = 0; i < srclen; ++i) {
|
||||
const nghttp2_huff_sym *sym = &huff_sym_table[src[i]];
|
||||
if(rembits == 8) {
|
||||
*dest = 0;
|
||||
if(avail) {
|
||||
nghttp2_bufs_fast_addb_hold(bufs, 0);
|
||||
} else {
|
||||
rv = nghttp2_bufs_addb_hold(bufs, 0);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
}
|
||||
}
|
||||
rembits = huff_encode_sym(bufs, &avail, rembits, sym);
|
||||
if(rembits < 0) {
|
||||
return rembits;
|
||||
}
|
||||
rembits = huff_encode_sym(&dest, rembits, sym);
|
||||
}
|
||||
/* 256 is special terminal symbol, pad with its prefix */
|
||||
if(rembits < 8) {
|
||||
const nghttp2_huff_sym *sym = &huff_sym_table[256];
|
||||
*dest |= sym->code >> (sym->nbits - rembits);
|
||||
++dest;
|
||||
|
||||
/* Caution we no longer adjust avail here */
|
||||
if(avail) {
|
||||
nghttp2_bufs_fast_orb(bufs, sym->code >> (sym->nbits - rembits));
|
||||
} else {
|
||||
rv = nghttp2_bufs_orb(bufs, sym->code >> (sym->nbits - rembits));
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
return dest - dest_first;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx)
|
||||
|
@ -109,6 +168,10 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
|||
{
|
||||
size_t i, j;
|
||||
int rv;
|
||||
size_t avail;
|
||||
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
|
||||
/* We use the decoding algorithm described in
|
||||
http://graphics.ics.uci.edu/pub/Prefix.pdf */
|
||||
for(i = 0; i < srclen; ++i) {
|
||||
|
@ -119,10 +182,16 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
|
|||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
if(t->flags & NGHTTP2_HUFF_SYM) {
|
||||
if(avail) {
|
||||
nghttp2_bufs_fast_addb(bufs, t->sym);
|
||||
--avail;
|
||||
} else {
|
||||
rv = nghttp2_bufs_addb(bufs, t->sym);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
avail = nghttp2_bufs_cur_avail(bufs);
|
||||
}
|
||||
}
|
||||
ctx->state = t->state;
|
||||
ctx->accept = (t->flags & NGHTTP2_HUFF_ACCEPTED) != 0;
|
||||
|
|
|
@ -211,7 +211,7 @@ static void nghttp2_active_outbound_item_reset
|
|||
nghttp2_outbound_item_free(aob->item);
|
||||
free(aob->item);
|
||||
aob->item = NULL;
|
||||
nghttp2_buf_reset(&aob->framebuf);
|
||||
nghttp2_bufs_reset(&aob->framebufs);
|
||||
aob->state = NGHTTP2_OB_POP_ITEM;
|
||||
}
|
||||
|
||||
|
@ -290,8 +290,12 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
|
|||
(*session_ptr)->server = 1;
|
||||
}
|
||||
|
||||
rv = nghttp2_buf_init2(&(*session_ptr)->aob.framebuf,
|
||||
NGHTTP2_INITIAL_OUTBOUND_FRAMEBUF_LENGTH);
|
||||
/* 2 for PAD_HIGH and PAD_LOW. We have maximum 64KB of frame
|
||||
serialization buffer for transmission */
|
||||
rv = nghttp2_bufs_init2(&(*session_ptr)->aob.framebufs,
|
||||
NGHTTP2_MAX_FRAMELEN,
|
||||
65536 / NGHTTP2_MAX_FRAMELEN,
|
||||
NGHTTP2_FRAME_HDLEN + 2);
|
||||
if(rv != 0) {
|
||||
goto fail_aob_framebuf;
|
||||
}
|
||||
|
@ -418,7 +422,7 @@ void nghttp2_session_del(nghttp2_session *session)
|
|||
nghttp2_hd_deflate_free(&session->hd_deflater);
|
||||
nghttp2_hd_inflate_free(&session->hd_inflater);
|
||||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
nghttp2_buf_free(&session->aob.framebuf);
|
||||
nghttp2_bufs_free(&session->aob.framebufs);
|
||||
free(session);
|
||||
}
|
||||
|
||||
|
@ -1124,47 +1128,20 @@ static ssize_t session_call_select_padding(nghttp2_session *session,
|
|||
return frame->hd.length;
|
||||
}
|
||||
|
||||
static int session_reserve_pad_trail(nghttp2_session *session, size_t padlen)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
|
||||
if(padlen == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
aob = &session->aob;
|
||||
|
||||
DEBUGF(fprintf(stderr,
|
||||
"reserving extra %zu padding bytes, including garbage, "
|
||||
"but adjusted later\n",
|
||||
padlen));
|
||||
|
||||
rv = nghttp2_buf_last_reserve(&aob->framebuf, padlen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* We have to zero out padding bytes so that we won't reveal the
|
||||
possible internal data to the remote peer */
|
||||
memset(aob->framebuf.last, 0, padlen);
|
||||
|
||||
aob->framebuf.last += padlen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Add padding to HEADERS or PUSH_PROMISE. We use
|
||||
frame->headers.padlen in this function to use the fact that
|
||||
frame->push_promise has also padlen in the same position. */
|
||||
static ssize_t session_headers_add_pad(nghttp2_session *session,
|
||||
static int session_headers_add_pad(nghttp2_session *session,
|
||||
nghttp2_frame *frame)
|
||||
{
|
||||
int rv;
|
||||
ssize_t padded_payloadlen;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
nghttp2_bufs *framebufs;
|
||||
size_t padlen;
|
||||
|
||||
aob = &session->aob;
|
||||
framebufs = &aob->framebufs;
|
||||
|
||||
padded_payloadlen = session_call_select_padding(session, frame,
|
||||
frame->hd.length + 1024);
|
||||
|
@ -1172,70 +1149,20 @@ static ssize_t session_headers_add_pad(nghttp2_session *session,
|
|||
return padded_payloadlen;
|
||||
}
|
||||
|
||||
frame->headers.padlen = padded_payloadlen - frame->hd.length;
|
||||
frame->hd.length = padded_payloadlen;
|
||||
padlen = padded_payloadlen - frame->hd.length;
|
||||
|
||||
DEBUGF(fprintf(stderr, "padding selected: payloadlen=%zu, padlen=%zu\n",
|
||||
frame->hd.length, frame->headers.padlen));
|
||||
padded_payloadlen, padlen));
|
||||
|
||||
if(frame->hd.length > NGHTTP2_MAX_PAYLOADLEN) {
|
||||
nghttp2_frame_hd hd = frame->hd;
|
||||
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
hd.length = NGHTTP2_MAX_PAYLOADLEN;
|
||||
|
||||
if(NGHTTP2_MAX_PAYLOADLEN > frame->hd.length - frame->headers.padlen) {
|
||||
size_t padlen;
|
||||
|
||||
padlen = NGHTTP2_MAX_PAYLOADLEN -
|
||||
(frame->hd.length - frame->headers.padlen);
|
||||
|
||||
DEBUGF(fprintf(stderr, "padding across 2 frames\n"));
|
||||
DEBUGF(fprintf(stderr, "first HEADERS/PUSH_PROMISE "
|
||||
"payloadlen=%zu, padlen=%zu\n", hd.length, padlen));
|
||||
|
||||
rv = session_reserve_pad_trail(session, frame->headers.padlen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
rv = nghttp2_frame_add_pad(framebufs, &frame->hd, padlen,
|
||||
NGHTTP2_CONTINUATION);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_frame_set_pad(&aob->framebuf, &hd.flags, padlen);
|
||||
} else {
|
||||
/* PAD_HIGH and PAD_LOW will be added in
|
||||
nghttp2_session_after_frame_sent(). */
|
||||
DEBUGF(fprintf(stderr,
|
||||
"first HEADERS/PUSH_PROMISE does not have "
|
||||
"padding payloadlen=%zu", hd.length));
|
||||
frame->headers.padlen = padlen;
|
||||
|
||||
/* Ensure that we have allocated buffer */
|
||||
rv = session_reserve_pad_trail(session, frame->headers.padlen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
nghttp2_frame_pack_frame_hd(aob->framebuf.pos, &hd);
|
||||
|
||||
} else if(frame->headers.padlen > 0) {
|
||||
nghttp2_frame_hd hd = frame->hd;
|
||||
|
||||
rv = session_reserve_pad_trail(session, frame->headers.padlen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
DEBUGF(fprintf(stderr,
|
||||
"first HEADERS/PUSH_PROMISE payloadlen=%zu, padlen=%zu\n",
|
||||
frame->hd.length, frame->headers.padlen));
|
||||
|
||||
nghttp2_frame_set_pad(&aob->framebuf, &hd.flags, frame->headers.padlen);
|
||||
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_frame_pack_frame_hd(aob->framebuf.pos, &hd);
|
||||
}
|
||||
|
||||
return nghttp2_buf_len(&session->aob.framebuf);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1281,7 +1208,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
return rv;
|
||||
}
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_headers(&session->aob.framebuf,
|
||||
framebuflen = nghttp2_frame_pack_headers(&session->aob.framebufs,
|
||||
&frame->headers,
|
||||
&session->hd_deflater);
|
||||
if(framebuflen < 0) {
|
||||
|
@ -1290,7 +1217,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
|
||||
DEBUGF(fprintf(stderr,
|
||||
"before padding, HEADERS serialized in %zd bytes\n",
|
||||
nghttp2_buf_len(&session->aob.framebuf)));
|
||||
nghttp2_bufs_len(&session->aob.framebufs)));
|
||||
|
||||
framebuflen = session_headers_add_pad(session, frame);
|
||||
if(framebuflen < 0) {
|
||||
|
@ -1320,7 +1247,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
}
|
||||
|
||||
DEBUGF(fprintf(stderr, "HEADERS serialized in %zd bytes\n",
|
||||
nghttp2_buf_len(&session->aob.framebuf)));
|
||||
nghttp2_bufs_len(&session->aob.framebufs)));
|
||||
|
||||
break;
|
||||
}
|
||||
|
@ -1330,7 +1257,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_priority(&session->aob.framebuf,
|
||||
framebuflen = nghttp2_frame_pack_priority(&session->aob.framebufs,
|
||||
&frame->priority);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1338,7 +1265,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
break;
|
||||
}
|
||||
case NGHTTP2_RST_STREAM:
|
||||
framebuflen = nghttp2_frame_pack_rst_stream(&session->aob.framebuf,
|
||||
framebuflen = nghttp2_frame_pack_rst_stream(&session->aob.framebufs,
|
||||
&frame->rst_stream);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1349,7 +1276,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_settings(&session->aob.framebuf,
|
||||
framebuflen = nghttp2_frame_pack_settings(&session->aob.framebufs,
|
||||
&frame->settings);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1368,7 +1295,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
}
|
||||
frame->push_promise.promised_stream_id = session->next_stream_id;
|
||||
session->next_stream_id += 2;
|
||||
framebuflen = nghttp2_frame_pack_push_promise(&session->aob.framebuf,
|
||||
framebuflen = nghttp2_frame_pack_push_promise(&session->aob.framebufs,
|
||||
&frame->push_promise,
|
||||
&session->hd_deflater);
|
||||
if(framebuflen < 0) {
|
||||
|
@ -1393,7 +1320,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
break;
|
||||
}
|
||||
case NGHTTP2_PING:
|
||||
framebuflen = nghttp2_frame_pack_ping(&session->aob.framebuf,
|
||||
framebuflen = nghttp2_frame_pack_ping(&session->aob.framebufs,
|
||||
&frame->ping);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1405,7 +1332,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_window_update(&session->aob.framebuf,
|
||||
framebuflen = nghttp2_frame_pack_window_update(&session->aob.framebufs,
|
||||
&frame->window_update);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1420,7 +1347,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
peer that last-stream-id. */
|
||||
return NGHTTP2_ERR_GOAWAY_ALREADY_SENT;
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_goaway(&session->aob.framebuf,
|
||||
framebuflen = nghttp2_frame_pack_goaway(&session->aob.framebufs,
|
||||
&frame->goaway);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1450,7 +1377,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
return NGHTTP2_ERR_DEFERRED;
|
||||
}
|
||||
framebuflen = nghttp2_session_pack_data(session,
|
||||
&session->aob.framebuf,
|
||||
&session->aob.framebufs,
|
||||
next_readmax,
|
||||
data_frame);
|
||||
if(framebuflen == NGHTTP2_ERR_DEFERRED) {
|
||||
|
@ -1603,7 +1530,7 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
int rv;
|
||||
nghttp2_active_outbound_item *aob = &session->aob;
|
||||
nghttp2_outbound_item *item = aob->item;
|
||||
nghttp2_buf *framebuf = &aob->framebuf;
|
||||
nghttp2_bufs *framebufs = &aob->framebufs;
|
||||
|
||||
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
|
||||
nghttp2_frame *frame;
|
||||
|
@ -1613,63 +1540,11 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
if(frame->hd.type == NGHTTP2_HEADERS ||
|
||||
frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
|
||||
if(framebuf->mark < framebuf->last) {
|
||||
nghttp2_frame_hd cont_hd;
|
||||
if(nghttp2_bufs_next_present(framebufs)) {
|
||||
framebufs->cur = framebufs->cur->next;
|
||||
|
||||
cont_hd.length = nghttp2_min(framebuf->last - framebuf->mark,
|
||||
NGHTTP2_MAX_PAYLOADLEN);
|
||||
cont_hd.type = NGHTTP2_CONTINUATION;
|
||||
cont_hd.stream_id = frame->hd.stream_id;
|
||||
cont_hd.flags = NGHTTP2_FLAG_NONE;
|
||||
|
||||
/* Reuse previous buffers for frame header */
|
||||
framebuf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
if(cont_hd.length + framebuf->mark == framebuf->last) {
|
||||
size_t padlen;
|
||||
|
||||
if(cont_hd.length < frame->headers.padlen) {
|
||||
padlen = cont_hd.length;
|
||||
} else {
|
||||
/* We use frame->headers.padlen for PUSH_PROMISE too. This
|
||||
is possible because padlen is located in the same
|
||||
position. */
|
||||
padlen = frame->headers.padlen;
|
||||
}
|
||||
|
||||
cont_hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
||||
|
||||
DEBUGF(fprintf(stderr,
|
||||
"last CONTINUATION payloadlen=%zu, padlen=%zu\n",
|
||||
cont_hd.length, padlen));
|
||||
|
||||
nghttp2_frame_set_pad(framebuf, &cont_hd.flags, padlen);
|
||||
|
||||
framebuf->mark = framebuf->last;
|
||||
} else {
|
||||
ssize_t padlen;
|
||||
|
||||
framebuf->mark += cont_hd.length;
|
||||
|
||||
padlen = frame->headers.padlen - (framebuf->last - framebuf->mark);
|
||||
|
||||
if(padlen > 0) {
|
||||
/* frame payload includes a part of padding */
|
||||
DEBUGF(fprintf(stderr,
|
||||
"padding across 2 CONTINUATION frames. "
|
||||
"payloadlen=%zu, padlen=%zd\n",
|
||||
cont_hd.length, padlen));
|
||||
|
||||
nghttp2_frame_set_pad(framebuf, &cont_hd.flags, padlen);
|
||||
|
||||
framebuf->mark = framebuf->pos + NGHTTP2_FRAME_HDLEN +
|
||||
cont_hd.length;
|
||||
} else {
|
||||
/* If no padding, nothing to be done here */
|
||||
}
|
||||
}
|
||||
|
||||
nghttp2_frame_pack_frame_hd(framebuf->pos, &cont_hd);
|
||||
DEBUGF(fprintf(stderr, "send CONTINUATION frame, %zu bytes\n",
|
||||
nghttp2_buf_len(&framebufs->cur->buf)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1865,7 +1740,10 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
|
||||
return 0;
|
||||
}
|
||||
rv = nghttp2_session_pack_data(session, framebuf, next_readmax,
|
||||
|
||||
nghttp2_bufs_reset(framebufs);
|
||||
|
||||
rv = nghttp2_session_pack_data(session, framebufs, next_readmax,
|
||||
data_frame);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
|
@ -1892,7 +1770,6 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
return 0;
|
||||
}
|
||||
assert(rv >= 0);
|
||||
framebuf->mark = framebuf->last;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1916,10 +1793,10 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
|||
{
|
||||
int rv;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
nghttp2_buf *framebuf;
|
||||
nghttp2_bufs *framebufs;
|
||||
|
||||
aob = &session->aob;
|
||||
framebuf = &aob->framebuf;
|
||||
framebufs = &aob->framebufs;
|
||||
|
||||
*data_ptr = NULL;
|
||||
for(;;) {
|
||||
|
@ -1974,29 +1851,22 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
|||
}
|
||||
aob->item = item;
|
||||
|
||||
nghttp2_bufs_rewind(framebufs);
|
||||
|
||||
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
|
||||
nghttp2_frame *frame;
|
||||
|
||||
/* We have to get frame size from headers, because
|
||||
frame->hd.length does not always shows the actual frame
|
||||
size, especially for HEADERS size >
|
||||
NGHTTP2_MAX_PAYLOADLEN */
|
||||
frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
||||
|
||||
framebuf->mark = framebuf->pos + NGHTTP2_FRAME_HDLEN +
|
||||
nghttp2_get_uint16(framebuf->pos);
|
||||
|
||||
rv = session_call_before_frame_send(session, frame);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
} else {
|
||||
framebuf->mark = framebuf->last;
|
||||
}
|
||||
|
||||
DEBUGF(fprintf(stderr, "start transmitting type %d frame %zd bytes\n",
|
||||
framebuf->pos[2], framebuf->mark - framebuf->pos));
|
||||
framebufs->cur->buf.pos[2],
|
||||
framebufs->cur->buf.last - framebufs->cur->buf.pos));
|
||||
|
||||
aob->state = NGHTTP2_OB_SEND_DATA;
|
||||
|
||||
|
@ -2004,10 +1874,12 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
|||
}
|
||||
case NGHTTP2_OB_SEND_DATA: {
|
||||
size_t datalen;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
if(framebuf->pos == framebuf->mark) {
|
||||
DEBUGF(fprintf(stderr, "end transmission of frame, left %zd\n",
|
||||
framebuf->last - framebuf->mark));
|
||||
buf = &framebufs->cur->buf;
|
||||
|
||||
if(buf->pos == buf->last) {
|
||||
DEBUGF(fprintf(stderr, "end transmission of frame\n"));
|
||||
|
||||
/* Frame has completely sent */
|
||||
rv = nghttp2_session_after_frame_sent(session);
|
||||
|
@ -2020,11 +1892,12 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
|||
break;
|
||||
}
|
||||
|
||||
*data_ptr = framebuf->pos;
|
||||
datalen = framebuf->mark - framebuf->pos;
|
||||
*data_ptr = buf->pos;
|
||||
datalen = nghttp2_buf_len(buf);
|
||||
|
||||
/* We increment the offset here. If send_callback does not send
|
||||
everything, we will adjust it. */
|
||||
framebuf->pos += datalen;
|
||||
buf->pos += datalen;
|
||||
|
||||
return datalen;
|
||||
}
|
||||
|
@ -2037,9 +1910,9 @@ int nghttp2_session_send(nghttp2_session *session)
|
|||
const uint8_t *data;
|
||||
ssize_t datalen;
|
||||
ssize_t sentlen;
|
||||
nghttp2_buf *framebuf;
|
||||
nghttp2_bufs *framebufs;
|
||||
|
||||
framebuf = &session->aob.framebuf;
|
||||
framebufs = &session->aob.framebufs;
|
||||
|
||||
for(;;) {
|
||||
datalen = nghttp2_session_mem_send(session, &data);
|
||||
|
@ -2051,15 +1924,16 @@ int nghttp2_session_send(nghttp2_session *session)
|
|||
if(sentlen < 0) {
|
||||
if(sentlen == NGHTTP2_ERR_WOULDBLOCK) {
|
||||
/* Transmission canceled. Rewind the offset */
|
||||
framebuf->pos -= datalen;
|
||||
framebufs->cur->buf.pos -= datalen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
/* Rewind the offset to the amount of unsent bytes */
|
||||
framebuf->pos -= datalen - sentlen;
|
||||
framebufs->cur->buf.pos -= datalen - sentlen;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -4572,36 +4446,30 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
|
|||
}
|
||||
|
||||
ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
||||
nghttp2_buf *buf,
|
||||
nghttp2_bufs *bufs,
|
||||
size_t datamax,
|
||||
nghttp2_private_data *frame)
|
||||
{
|
||||
ssize_t framelen;
|
||||
ssize_t rv;
|
||||
int eof_flags;
|
||||
uint8_t flags;
|
||||
ssize_t payloadlen;
|
||||
ssize_t padded_payloadlen;
|
||||
size_t padlen;
|
||||
nghttp2_frame data_frame;
|
||||
nghttp2_frame data_frame = {{0}}; /* FIXME padlen is also initialized? */
|
||||
nghttp2_frame_hd hd;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
/* extra 2 bytes for PAD_HIGH and PAD_LOW. We allocate extra 2 bytes
|
||||
for padding. Based on the padding length, we adjust the starting
|
||||
offset of frame data. The starting offset is assigned into
|
||||
|*bufoff_ptr|. */
|
||||
buf->pos += 2;
|
||||
assert(bufs->head == bufs->cur);
|
||||
|
||||
framelen = NGHTTP2_FRAME_HDLEN + datamax;
|
||||
buf = &bufs->cur->buf;
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
/* Current max DATA length is less then buffer chunk size */
|
||||
assert(nghttp2_buf_avail(buf) >= (ssize_t)datamax);
|
||||
|
||||
eof_flags = 0;
|
||||
payloadlen = frame->data_prd.read_callback
|
||||
(session, frame->hd.stream_id, buf->pos + NGHTTP2_FRAME_HDLEN, datamax,
|
||||
(session, frame->hd.stream_id, buf->pos, datamax,
|
||||
&eof_flags, &frame->data_prd.source, session->user_data);
|
||||
|
||||
if(payloadlen == NGHTTP2_ERR_DEFERRED ||
|
||||
|
@ -4617,7 +4485,8 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
|||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
buf->last = buf->pos + NGHTTP2_FRAME_HDLEN + payloadlen;
|
||||
buf->last = buf->pos + payloadlen;
|
||||
buf->pos -= NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
/* Clear flags, because this may contain previous flags of previous
|
||||
DATA */
|
||||
|
@ -4635,8 +4504,6 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
|||
}
|
||||
|
||||
/* The primary reason of data_frame is pass to the user callback */
|
||||
memset(&data_frame, 0, sizeof(data_frame));
|
||||
|
||||
data_frame.hd.length = payloadlen;
|
||||
data_frame.hd.stream_id = frame->hd.stream_id;
|
||||
data_frame.hd.type = NGHTTP2_DATA;
|
||||
|
@ -4650,27 +4517,21 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
|||
|
||||
padlen = padded_payloadlen - payloadlen;
|
||||
|
||||
rv = session_reserve_pad_trail(session, padlen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
nghttp2_frame_set_pad(buf, &flags, padlen);
|
||||
|
||||
frame->padlen = padlen;
|
||||
frame->hd.length = padded_payloadlen;
|
||||
|
||||
/* Set PAD flags so that we can supply frame to the callback with
|
||||
the correct flags */
|
||||
frame->hd.flags |= flags;
|
||||
|
||||
memset(buf->pos, 0, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
hd = frame->hd;
|
||||
hd.length = payloadlen;
|
||||
hd.flags = flags;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
|
||||
rv = nghttp2_frame_add_pad(bufs, &hd, padlen, NGHTTP2_DATA);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
frame->hd.length = hd.length;
|
||||
frame->hd.flags |= hd.flags;
|
||||
frame->padlen = padlen;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
|
|
|
@ -55,15 +55,13 @@ typedef enum {
|
|||
typedef struct {
|
||||
nghttp2_outbound_item *item;
|
||||
|
||||
nghttp2_buf framebuf;
|
||||
nghttp2_bufs framebufs;
|
||||
nghttp2_outbound_state state;
|
||||
} nghttp2_active_outbound_item;
|
||||
|
||||
/* Buffer length for inbound raw byte stream. */
|
||||
#define NGHTTP2_INBOUND_BUFFER_LENGTH 16384
|
||||
|
||||
#define NGHTTP2_INITIAL_OUTBOUND_FRAMEBUF_LENGTH 16384
|
||||
|
||||
#define NGHTTP2_INITIAL_NV_BUFFER_LENGTH 4096
|
||||
|
||||
/* Internal state when receiving incoming frame */
|
||||
|
@ -526,7 +524,7 @@ nghttp2_stream* nghttp2_session_get_stream(nghttp2_session *session,
|
|||
* The read_callback failed (session error).
|
||||
*/
|
||||
ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
||||
nghttp2_buf *buf,
|
||||
nghttp2_bufs *bufs,
|
||||
size_t datamax,
|
||||
nghttp2_private_data *frame);
|
||||
|
||||
|
|
|
@ -290,8 +290,8 @@ cdef extern from 'nghttp2_hd.h':
|
|||
int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
|
||||
size_t hd_table_bufsize_max)
|
||||
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_buf *buf,
|
||||
int nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_bufs *bufs,
|
||||
nghttp2_nv *nva, size_t nvlen)
|
||||
|
||||
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
||||
|
@ -305,11 +305,12 @@ cdef extern from 'nghttp2_hd.h':
|
|||
|
||||
cdef extern from 'nghttp2_buf.h':
|
||||
|
||||
ctypedef struct nghttp2_buf:
|
||||
uint8_t *pos
|
||||
uint8_t *last
|
||||
ctypedef struct nghttp2_bufs:
|
||||
pass
|
||||
|
||||
void nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_size,
|
||||
size_t max_chunk)
|
||||
|
||||
void nghttp2_buf_init(nghttp2_buf *buf)
|
||||
void nghttp2_bufs_free(nghttp2_bufs *bufs)
|
||||
|
||||
void nghttp2_buf_free(nghttp2_buf *buf)
|
||||
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out)
|
||||
|
|
|
@ -114,27 +114,36 @@ cdef class HDDeflater:
|
|||
nvap[0].valuelen = len(v)
|
||||
nvap += 1
|
||||
|
||||
cdef cnghttp2.nghttp2_buf buf
|
||||
cdef cnghttp2.nghttp2_bufs bufs
|
||||
cdef size_t outcap = 0
|
||||
cdef ssize_t rv
|
||||
cdef uint8_t *out
|
||||
|
||||
cnghttp2.nghttp2_buf_init(&buf)
|
||||
cnghttp2.nghttp2_bufs_init(&bufs, 4096, 16)
|
||||
|
||||
rv = cnghttp2.nghttp2_hd_deflate_hd(&self._deflater, &buf,
|
||||
rv = cnghttp2.nghttp2_hd_deflate_hd(&self._deflater, &bufs,
|
||||
nva, len(headers))
|
||||
free(nva)
|
||||
|
||||
if rv < 0:
|
||||
cnghttp2.nghttp2_buf_free(&buf);
|
||||
cnghttp2.nghttp2_bufs_free(&bufs);
|
||||
|
||||
raise Exception(_strerror(rv))
|
||||
|
||||
rv = cnghttp2.nghttp2_bufs_remove(&bufs, &out)
|
||||
|
||||
if rv < 0:
|
||||
cnghttp2.nghttp2_bufs_free(&bufs);
|
||||
|
||||
raise Exception(_strerror(rv))
|
||||
|
||||
cdef bytes res
|
||||
|
||||
try:
|
||||
res = buf.pos[:rv]
|
||||
res = out[:rv]
|
||||
finally:
|
||||
cnghttp2.nghttp2_buf_free(&buf)
|
||||
cnghttp2.nghttp2_free(out)
|
||||
cnghttp2.nghttp2_bufs_free(&bufs)
|
||||
|
||||
return res
|
||||
|
||||
|
|
|
@ -324,7 +324,7 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
|
|||
}
|
||||
switch(frame->hd.type) {
|
||||
case NGHTTP2_DATA:
|
||||
if(frame->hd.flags & (NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW)) {
|
||||
if(frame->data.padlen > 0) {
|
||||
print_frame_attr_indent();
|
||||
fprintf(outfile, "(padlen=%zu)\n", frame->data.padlen);
|
||||
}
|
||||
|
|
|
@ -72,26 +72,36 @@ static void to_hex(char *dest, const uint8_t *src, size_t len)
|
|||
}
|
||||
|
||||
static void output_to_json(nghttp2_hd_deflater *deflater,
|
||||
nghttp2_buf *buf, size_t inputlen,
|
||||
nghttp2_bufs *bufs, size_t inputlen,
|
||||
nghttp2_nv *nva, size_t nvlen,
|
||||
int seq)
|
||||
{
|
||||
json_t *obj;
|
||||
char *hex = NULL;
|
||||
char *hex = NULL, *hexp;
|
||||
size_t len;
|
||||
nghttp2_buf_chain *ci;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
len = nghttp2_buf_len(buf);
|
||||
len = nghttp2_bufs_len(bufs);
|
||||
|
||||
if(len > 0) {
|
||||
hex = malloc(len * 2);
|
||||
}
|
||||
|
||||
obj = json_object();
|
||||
json_object_set_new(obj, "seq", json_integer(seq));
|
||||
json_object_set_new(obj, "input_length", json_integer(inputlen));
|
||||
json_object_set_new(obj, "output_length", json_integer(len));
|
||||
json_object_set_new(obj, "percentage_of_original_size",
|
||||
json_real((double)len / inputlen * 100));
|
||||
to_hex(hex, buf->pos, len);
|
||||
|
||||
hexp = hex;
|
||||
for(ci = bufs->head; ci; ci = ci->next) {
|
||||
buf = &ci->buf;
|
||||
to_hex(hexp, buf->pos, nghttp2_buf_len(buf));
|
||||
hexp += nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
if(len == 0) {
|
||||
json_object_set_new(obj, "wire", json_string(""));
|
||||
} else {
|
||||
|
@ -117,11 +127,11 @@ static void deflate_hd(nghttp2_hd_deflater *deflater,
|
|||
nghttp2_nv *nva, size_t nvlen, size_t inputlen, int seq)
|
||||
{
|
||||
ssize_t rv;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
nghttp2_bufs_init2(&bufs, 4096, 16, 0);
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(deflater, &buf, nva, nvlen);
|
||||
rv = nghttp2_hd_deflate_hd(deflater, &bufs, nva, nvlen);
|
||||
if(rv < 0) {
|
||||
fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq);
|
||||
exit(EXIT_FAILURE);
|
||||
|
@ -130,8 +140,8 @@ static void deflate_hd(nghttp2_hd_deflater *deflater,
|
|||
input_sum += inputlen;
|
||||
output_sum += rv;
|
||||
|
||||
output_to_json(deflater, &buf, inputlen, nva, nvlen, seq);
|
||||
nghttp2_buf_free(&buf);
|
||||
output_to_json(deflater, &bufs, inputlen, nva, nvlen, seq);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
}
|
||||
|
||||
static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
|
||||
|
|
|
@ -72,14 +72,14 @@ void test_nghttp2_frame_pack_headers()
|
|||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_headers frame, oframe;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
nva_out out;
|
||||
ssize_t hdblocklen;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_deflate_init(&deflater);
|
||||
|
@ -91,22 +91,24 @@ void test_nghttp2_frame_pack_headers()
|
|||
NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS,
|
||||
1000000007,
|
||||
1 << 20, nva, nvlen);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
nghttp2_bufs_rewind(&bufs);
|
||||
|
||||
check_frame_header(nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN,
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
|
||||
check_frame_header(nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN,
|
||||
NGHTTP2_HEADERS,
|
||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS,
|
||||
1000000007, &oframe.hd);
|
||||
/* We didn't include PRIORITY flag so priority is not packed */
|
||||
CU_ASSERT(1 << 30 == oframe.pri);
|
||||
|
||||
hdblocklen = nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN;
|
||||
hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN;
|
||||
CU_ASSERT(hdblocklen ==
|
||||
inflate_hd(&inflater, &out,
|
||||
buf.pos + NGHTTP2_FRAME_HDLEN, hdblocklen));
|
||||
inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN));
|
||||
|
||||
CU_ASSERT(7 == out.nvlen);
|
||||
CU_ASSERT(nvnameeq("method", &out.nva[0]));
|
||||
|
@ -114,33 +116,33 @@ void test_nghttp2_frame_pack_headers()
|
|||
|
||||
nghttp2_frame_headers_free(&oframe);
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
/* Next, include PRIORITY flag */
|
||||
frame.hd.flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
|
||||
check_frame_header(nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN,
|
||||
check_frame_header(nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN,
|
||||
NGHTTP2_HEADERS,
|
||||
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS |
|
||||
NGHTTP2_FLAG_PRIORITY,
|
||||
1000000007, &oframe.hd);
|
||||
CU_ASSERT(1 << 20 == oframe.pri);
|
||||
|
||||
hdblocklen = nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN - 4;
|
||||
hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN - 4;
|
||||
CU_ASSERT(hdblocklen ==
|
||||
inflate_hd(&inflater, &out,
|
||||
buf.pos + NGHTTP2_FRAME_HDLEN + 4, hdblocklen));
|
||||
inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN + 4));
|
||||
|
||||
nghttp2_nv_array_sort(out.nva, out.nvlen);
|
||||
CU_ASSERT(nvnameeq("method", &out.nva[0]));
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_headers_free(&oframe);
|
||||
nghttp2_frame_headers_free(&frame);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
|
@ -151,16 +153,16 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
{
|
||||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_headers frame;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
size_t big_vallen = NGHTTP2_HD_MAX_VALUE;
|
||||
nghttp2_nv big_hds[16];
|
||||
size_t big_hdslen = ARRLEN(big_hds);
|
||||
size_t i;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
for(i = 0; i < big_hdslen; ++i) {
|
||||
big_hds[i].name = (uint8_t*)"header";
|
||||
|
@ -177,11 +179,11 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS,
|
||||
1000000007,
|
||||
0, nva, nvlen);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame, &deflater);
|
||||
CU_ASSERT_EQUAL(NGHTTP2_ERR_HEADER_COMP, framelen);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
|
||||
CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == rv);
|
||||
|
||||
nghttp2_frame_headers_free(&frame);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
for(i = 0; i < big_hdslen; ++i) {
|
||||
free(big_hds[i].value);
|
||||
}
|
||||
|
@ -191,21 +193,22 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
void test_nghttp2_frame_pack_priority(void)
|
||||
{
|
||||
nghttp2_priority frame, oframe;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nghttp2_frame_priority_init(&frame, 1000000007, 1 << 30);
|
||||
framelen = nghttp2_frame_pack_priority(&buf, &frame);
|
||||
rv = nghttp2_frame_pack_priority(&bufs, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(12 == nghttp2_bufs_len(&bufs));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
check_frame_header(4, NGHTTP2_PRIORITY, NGHTTP2_FLAG_NONE, 1000000007,
|
||||
&oframe.hd);
|
||||
CU_ASSERT(1 << 30 == oframe.pri);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_priority_free(&oframe);
|
||||
nghttp2_frame_priority_free(&frame);
|
||||
}
|
||||
|
@ -213,21 +216,22 @@ void test_nghttp2_frame_pack_priority(void)
|
|||
void test_nghttp2_frame_pack_rst_stream(void)
|
||||
{
|
||||
nghttp2_rst_stream frame, oframe;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nghttp2_frame_rst_stream_init(&frame, 1000000007, NGHTTP2_PROTOCOL_ERROR);
|
||||
framelen = nghttp2_frame_pack_rst_stream(&buf, &frame);
|
||||
rv = nghttp2_frame_pack_rst_stream(&bufs, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(12 == nghttp2_bufs_len(&bufs));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
check_frame_header(4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE, 1000000007,
|
||||
&oframe.hd);
|
||||
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == oframe.error_code);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_rst_stream_free(&oframe);
|
||||
nghttp2_frame_rst_stream_free(&frame);
|
||||
}
|
||||
|
@ -235,9 +239,9 @@ void test_nghttp2_frame_pack_rst_stream(void)
|
|||
void test_nghttp2_frame_pack_settings()
|
||||
{
|
||||
nghttp2_settings frame, oframe;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
int i;
|
||||
int rv;
|
||||
nghttp2_settings_entry iv[] =
|
||||
{
|
||||
{
|
||||
|
@ -251,17 +255,17 @@ void test_nghttp2_frame_pack_settings()
|
|||
}
|
||||
};
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nghttp2_frame_settings_init(&frame, NGHTTP2_FLAG_NONE,
|
||||
nghttp2_frame_iv_copy(iv, 3), 3);
|
||||
framelen = nghttp2_frame_pack_settings(&buf, &frame);
|
||||
rv = nghttp2_frame_pack_settings(&bufs, &frame);
|
||||
|
||||
CU_ASSERT(NGHTTP2_FRAME_HDLEN +
|
||||
3 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == framelen);
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(NGHTTP2_FRAME_HDLEN + 3 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH ==
|
||||
nghttp2_bufs_len(&bufs));
|
||||
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
check_frame_header(3 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH,
|
||||
NGHTTP2_SETTINGS, NGHTTP2_FLAG_NONE, 0, &oframe.hd);
|
||||
CU_ASSERT(3 == oframe.niv);
|
||||
|
@ -270,7 +274,7 @@ void test_nghttp2_frame_pack_settings()
|
|||
CU_ASSERT(iv[i].value == oframe.iv[i].value);
|
||||
}
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_settings_free(&frame);
|
||||
nghttp2_frame_settings_free(&oframe);
|
||||
}
|
||||
|
@ -280,14 +284,14 @@ void test_nghttp2_frame_pack_push_promise()
|
|||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_push_promise frame, oframe;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
nva_out out;
|
||||
ssize_t hdblocklen;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_deflate_init(&deflater);
|
||||
|
@ -297,27 +301,27 @@ void test_nghttp2_frame_pack_push_promise()
|
|||
nvlen = HEADERS_LENGTH;
|
||||
nghttp2_frame_push_promise_init(&frame, NGHTTP2_FLAG_END_HEADERS,
|
||||
1000000007, (1U << 31) - 1, nva, nvlen);
|
||||
framelen = nghttp2_frame_pack_push_promise(&buf, &frame, &deflater);
|
||||
rv = nghttp2_frame_pack_push_promise(&bufs, &frame, &deflater);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
|
||||
check_frame_header(nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN,
|
||||
check_frame_header(nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN,
|
||||
NGHTTP2_PUSH_PROMISE,
|
||||
NGHTTP2_FLAG_END_HEADERS, 1000000007, &oframe.hd);
|
||||
CU_ASSERT((1U << 31) - 1 == oframe.promised_stream_id);
|
||||
|
||||
hdblocklen = nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN - 4;
|
||||
hdblocklen = nghttp2_bufs_len(&bufs) - NGHTTP2_FRAME_HDLEN - 4;
|
||||
CU_ASSERT(hdblocklen ==
|
||||
inflate_hd(&inflater, &out,
|
||||
buf.pos + NGHTTP2_FRAME_HDLEN + 4, hdblocklen));
|
||||
inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN + 4));
|
||||
|
||||
CU_ASSERT(7 == out.nvlen);
|
||||
CU_ASSERT(nvnameeq("method", &out.nva[0]));
|
||||
CU_ASSERT(nvvalueeq("GET", &out.nva[0]));
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_push_promise_free(&oframe);
|
||||
nghttp2_frame_push_promise_free(&frame);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
|
@ -327,22 +331,23 @@ void test_nghttp2_frame_pack_push_promise()
|
|||
void test_nghttp2_frame_pack_ping(void)
|
||||
{
|
||||
nghttp2_ping frame, oframe;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
const uint8_t opaque_data[] = "01234567";
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nghttp2_frame_ping_init(&frame, NGHTTP2_FLAG_ACK, opaque_data);
|
||||
framelen = nghttp2_frame_pack_ping(&buf, &frame);
|
||||
rv = nghttp2_frame_pack_ping(&bufs, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(16 == nghttp2_bufs_len(&bufs));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
check_frame_header(8, NGHTTP2_PING, NGHTTP2_FLAG_ACK, 0, &oframe.hd);
|
||||
CU_ASSERT(memcmp(opaque_data, oframe.opaque_data, sizeof(opaque_data) - 1)
|
||||
== 0);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_ping_free(&oframe);
|
||||
nghttp2_frame_ping_free(&frame);
|
||||
}
|
||||
|
@ -350,20 +355,21 @@ void test_nghttp2_frame_pack_ping(void)
|
|||
void test_nghttp2_frame_pack_goaway()
|
||||
{
|
||||
nghttp2_goaway frame, oframe;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
size_t opaque_data_len = 16;
|
||||
uint8_t *opaque_data = malloc(opaque_data_len);
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
memcpy(opaque_data, "0123456789abcdef", opaque_data_len);
|
||||
nghttp2_frame_goaway_init(&frame, 1000000007, NGHTTP2_PROTOCOL_ERROR,
|
||||
opaque_data, opaque_data_len);
|
||||
framelen = nghttp2_frame_pack_goaway(&buf, &frame);
|
||||
rv = nghttp2_frame_pack_goaway(&bufs, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT((ssize_t)(16 + opaque_data_len) == nghttp2_bufs_len(&bufs));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
check_frame_header(24, NGHTTP2_GOAWAY, NGHTTP2_FLAG_NONE, 0, &oframe.hd);
|
||||
CU_ASSERT(1000000007 == oframe.last_stream_id);
|
||||
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == oframe.error_code);
|
||||
|
@ -373,7 +379,7 @@ void test_nghttp2_frame_pack_goaway()
|
|||
/* CU_ASSERT(opaque_data_len == oframe.opaque_data_len); */
|
||||
/* CU_ASSERT(memcmp(opaque_data, oframe.opaque_data, opaque_data_len) == 0); */
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_goaway_free(&oframe);
|
||||
nghttp2_frame_goaway_free(&frame);
|
||||
}
|
||||
|
@ -381,22 +387,23 @@ void test_nghttp2_frame_pack_goaway()
|
|||
void test_nghttp2_frame_pack_window_update(void)
|
||||
{
|
||||
nghttp2_window_update frame, oframe;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nghttp2_frame_window_update_init(&frame, NGHTTP2_FLAG_NONE,
|
||||
1000000007, 4096);
|
||||
framelen = nghttp2_frame_pack_window_update(&buf, &frame);
|
||||
rv = nghttp2_frame_pack_window_update(&bufs, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(12 == nghttp2_bufs_len(&bufs));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &bufs));
|
||||
check_frame_header(4, NGHTTP2_WINDOW_UPDATE, NGHTTP2_FLAG_NONE,
|
||||
1000000007, &oframe.hd);
|
||||
CU_ASSERT(4096 == oframe.window_size_increment);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_window_update_free(&oframe);
|
||||
nghttp2_frame_window_update_free(&frame);
|
||||
}
|
||||
|
|
|
@ -52,83 +52,89 @@ void test_nghttp2_hd_deflate(void)
|
|||
MAKE_NV("cookie", "k1=v1")};
|
||||
nghttp2_nv nva5[] = {MAKE_NV(":path", "/style.css"),
|
||||
MAKE_NV("x-nghttp2", "")};
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nva_out out;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater));
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater));
|
||||
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva1, ARRLEN(nva1));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva1, ARRLEN(nva1));
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(3 == out.nvlen);
|
||||
assert_nv_equal(nva1, out.nva, 3);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Second headers */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva2, ARRLEN(nva2));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva2, ARRLEN(nva2));
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(2 == out.nvlen);
|
||||
assert_nv_equal(nva2, out.nva, 2);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Third headers, including same header field name, but value is not
|
||||
the same. */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva3, ARRLEN(nva3));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva3, ARRLEN(nva3));
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(3 == out.nvlen);
|
||||
assert_nv_equal(nva3, out.nva, 3);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Fourth headers, including duplicate header fields. */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva4, ARRLEN(nva4));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva4, ARRLEN(nva4));
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(3 == out.nvlen);
|
||||
assert_nv_equal(nva4, out.nva, 3);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Fifth headers includes empty value */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva5, ARRLEN(nva5));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva5, ARRLEN(nva5));
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(2 == out.nvlen);
|
||||
assert_nv_equal(nva5, out.nva, 2);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Cleanup */
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -142,11 +148,12 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
|
|||
nghttp2_nv nva2[] = {MAKE_NV("cookie", "alpha"),
|
||||
MAKE_NV("cookie", "alpha"),
|
||||
MAKE_NV("cookie", "alpha")};
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nva_out out;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater));
|
||||
|
@ -154,34 +161,36 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
|
|||
|
||||
/* Encode 2 same headers. cookie:alpha is not in the reference set,
|
||||
so first emit literal repr and then 2 emits of indexed repr. */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva1, ARRLEN(nva1));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva1, ARRLEN(nva1));
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(2 == out.nvlen);
|
||||
assert_nv_equal(nva1, out.nva, 2);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Encode 3 same headers. This time, cookie:alpha is in the
|
||||
reference set, so the encoder emits indexed repr 6 times */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva2, ARRLEN(nva2));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva2, ARRLEN(nva2));
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen == 6);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(3 == out.nvlen);
|
||||
assert_nv_equal(nva2, out.nva, 3);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Cleanup */
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -192,7 +201,7 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
|
|||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_nv nva[] = {MAKE_NV("h1", ""),
|
||||
MAKE_NV("h2", "")};
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
/* Default header table capacity is 4096. Adding 2 byte header name
|
||||
and 4060 byte value, which is 4094 bytes including overhead, to
|
||||
|
@ -200,8 +209,9 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
|
|||
uint8_t value[3038];
|
||||
nva_out out;
|
||||
size_t i;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
memset(value, '0', sizeof(value));
|
||||
|
@ -215,42 +225,44 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
|
|||
|
||||
/* First emit "h1: ..." to put it in the reference set (index
|
||||
= 0). */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 1);
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 1);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
nghttp2_nv_array_sort(nva, 1);
|
||||
assert_nv_equal(nva, out.nva, 1);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Encode with second header */
|
||||
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
|
||||
/* Check common header "h1: ...:, which is removed from the
|
||||
header table because of eviction, is still emitted by the
|
||||
inflater */
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(2 == out.nvlen);
|
||||
nghttp2_nv_array_sort(nva, 2);
|
||||
assert_nv_equal(nva, out.nva, 2);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
CU_ASSERT(1 == deflater.ctx.hd_table.len);
|
||||
CU_ASSERT(1 == inflater.ctx.hd_table.len);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -259,7 +271,7 @@ void test_nghttp2_hd_deflate_clear_refset(void)
|
|||
{
|
||||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv[] = {
|
||||
MAKE_NV(":path", "/"),
|
||||
|
@ -267,8 +279,9 @@ void test_nghttp2_hd_deflate_clear_refset(void)
|
|||
};
|
||||
size_t i;
|
||||
nva_out out;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_deflate_init2(&deflater,
|
||||
|
@ -277,18 +290,21 @@ void test_nghttp2_hd_deflate_clear_refset(void)
|
|||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
for(i = 0; i < 2; ++i) {
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nv, ARRLEN(nv));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nv, ARRLEN(nv));
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 1);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(ARRLEN(nv) == out.nvlen);
|
||||
assert_nv_equal(nv, out.nva, ARRLEN(nv));
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
}
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -296,7 +312,7 @@ void test_nghttp2_hd_deflate_clear_refset(void)
|
|||
void test_nghttp2_hd_inflate_indname_noinc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv[] = {
|
||||
/* Huffman */
|
||||
|
@ -307,53 +323,53 @@ void test_nghttp2_hd_inflate_indname_noinc(void)
|
|||
size_t i;
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
for(i = 0; i < ARRLEN(nv); ++i) {
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 56,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 56,
|
||||
nv[i].value, nv[i].valuelen,
|
||||
0));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv[i], out.nva, 1);
|
||||
CU_ASSERT(0 == inflater.ctx.hd_table.len);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
}
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_inc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2");
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 56,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 56,
|
||||
nv.value, nv.valuelen, 1));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv, out.nva, 1);
|
||||
|
@ -363,38 +379,38 @@ void test_nghttp2_hd_inflate_indname_inc(void)
|
|||
inflater.ctx.hd_table.len-1)->nv, 1);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_inc_eviction(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
uint8_t value[1024];
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
memset(value, '0', sizeof(value));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 13,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 13,
|
||||
value, sizeof(value), 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 14,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 14,
|
||||
value, sizeof(value), 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 15,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 15,
|
||||
value, sizeof(value), 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 16,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 16,
|
||||
value, sizeof(value), 1));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(4 == out.nvlen);
|
||||
CU_ASSERT(14 == out.nva[0].namelen);
|
||||
|
@ -402,19 +418,19 @@ void test_nghttp2_hd_inflate_indname_inc_eviction(void)
|
|||
CU_ASSERT(sizeof(value) == out.nva[0].valuelen);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
CU_ASSERT(3 == inflater.ctx.hd_table.len);
|
||||
CU_ASSERT(GET_TABLE_ENT(&inflater.ctx, 0)->flags & NGHTTP2_HD_FLAG_REFSET);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_newname_noinc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv[] = {
|
||||
/* Expecting huffman for both */
|
||||
|
@ -429,49 +445,49 @@ void test_nghttp2_hd_inflate_newname_noinc(void)
|
|||
size_t i;
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
for(i = 0; i < ARRLEN(nv); ++i) {
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &nv[i], 0));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv[i], 0));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv[i], out.nva, 1);
|
||||
CU_ASSERT(0 == inflater.ctx.hd_table.len);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
}
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_newname_inc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2");
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &nv, 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv, 1));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv, out.nva, 1);
|
||||
|
@ -481,20 +497,20 @@ void test_nghttp2_hd_inflate_newname_inc(void)
|
|||
inflater.ctx.hd_table.len-1)->nv, 1);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_clearall_inc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv;
|
||||
uint8_t value[4060];
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
bufs_large_init(&bufs, 8192);
|
||||
|
||||
nva_out_init(&out);
|
||||
/* Total 4097 bytes space required to hold this entry */
|
||||
|
@ -506,66 +522,73 @@ void test_nghttp2_hd_inflate_clearall_inc(void)
|
|||
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &nv, 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv, 1));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv, out.nva, 1);
|
||||
CU_ASSERT(0 == inflater.ctx.hd_table.len);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* Do it again */
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv, out.nva, 1);
|
||||
CU_ASSERT(0 == inflater.ctx.hd_table.len);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* This time, 4096 bytes space required, which is just fits in the
|
||||
header table */
|
||||
nv.valuelen = sizeof(value) - 1;
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &nv, 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv, 1));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv, out.nva, 1);
|
||||
CU_ASSERT(1 == inflater.ctx.hd_table.len);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_zero_length_huffman(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
uint8_t buf[4];
|
||||
nghttp2_bufs bufs;
|
||||
/* Literal header without indexing - new name */
|
||||
uint8_t data[] = { 0x40, 0x01, 0x78 /* 'x' */, 0x80 };
|
||||
nva_out out;
|
||||
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
/* Literal header without indexing - new name */
|
||||
buf[0] = 0x40;
|
||||
buf[1] = 1;
|
||||
buf[2] = 'x';
|
||||
buf[3] = 0x80;
|
||||
|
||||
nghttp2_bufs_add(&bufs, data, sizeof(data));
|
||||
|
||||
/* /\* Literal header without indexing - new name *\/ */
|
||||
/* ptr[0] = 0x40; */
|
||||
/* ptr[1] = 1; */
|
||||
/* ptr[2] = 'x'; */
|
||||
/* ptr[3] = 0x80; */
|
||||
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
CU_ASSERT(4 == inflate_hd(&inflater, &out, buf, 4));
|
||||
CU_ASSERT(4 == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
CU_ASSERT(1 == out.nva[0].namelen);
|
||||
|
@ -574,6 +597,7 @@ void test_nghttp2_hd_inflate_zero_length_huffman(void)
|
|||
CU_ASSERT(0 == out.nva[0].valuelen);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
|
@ -583,11 +607,12 @@ void test_nghttp2_hd_change_table_size(void)
|
|||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_nv nva[] = { MAKE_NV(":method", "GET"),
|
||||
MAKE_NV(":path", "/") };
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t rv;
|
||||
nva_out out;
|
||||
ssize_t blocklen;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
|
||||
|
@ -606,19 +631,21 @@ void test_nghttp2_hd_change_table_size(void)
|
|||
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
/* This will emit encoding context update with header table size 4096 */
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv > 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(2 == deflater.ctx.hd_table.len);
|
||||
CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
|
||||
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
CU_ASSERT(2 == inflater.ctx.hd_table.len);
|
||||
CU_ASSERT(4096 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* inflater changes header table size to 1024 */
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 1024));
|
||||
|
@ -631,19 +658,21 @@ void test_nghttp2_hd_change_table_size(void)
|
|||
CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv >= 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(0 == blocklen);
|
||||
CU_ASSERT(2 == deflater.ctx.hd_table.len);
|
||||
CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
|
||||
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
CU_ASSERT(2 == inflater.ctx.hd_table.len);
|
||||
CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(1024 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* inflater changes header table size to 0 */
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
|
||||
|
@ -658,26 +687,28 @@ void test_nghttp2_hd_change_table_size(void)
|
|||
CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv >= 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(0 == deflater.ctx.hd_table.len);
|
||||
CU_ASSERT(0 == deflater.ctx.hd_table_bufsize_max);
|
||||
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
CU_ASSERT(0 == inflater.ctx.hd_table.len);
|
||||
CU_ASSERT(0 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(0 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
|
||||
/* Check table buffer is expanded */
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nghttp2_hd_deflate_init2(&deflater, 8192);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
@ -693,19 +724,21 @@ void test_nghttp2_hd_change_table_size(void)
|
|||
CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv > 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(2 == deflater.ctx.hd_table.len);
|
||||
CU_ASSERT(8000 == deflater.ctx.hd_table_bufsize_max);
|
||||
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
CU_ASSERT(2 == inflater.ctx.hd_table.len);
|
||||
CU_ASSERT(8000 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(8000 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 16383));
|
||||
CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 16383));
|
||||
|
@ -717,29 +750,30 @@ void test_nghttp2_hd_change_table_size(void)
|
|||
CU_ASSERT(16383 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv >= 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(2 == deflater.ctx.hd_table.len);
|
||||
CU_ASSERT(8192 == deflater.ctx.hd_table_bufsize_max);
|
||||
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
CU_ASSERT(2 == inflater.ctx.hd_table.len);
|
||||
CU_ASSERT(8192 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(16383 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Lastly, check the error condition */
|
||||
|
||||
rv = nghttp2_hd_emit_table_size(&buf, 25600);
|
||||
rv = nghttp2_hd_emit_table_size(&bufs, 25600);
|
||||
CU_ASSERT(rv == 0);
|
||||
CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
|
||||
inflate_hd(&inflater, &out, buf.pos, nghttp2_buf_len(&buf)));
|
||||
CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
|
@ -753,21 +787,23 @@ void test_nghttp2_hd_change_table_size(void)
|
|||
CU_ASSERT(4096 == deflater.ctx.hd_table_bufsize_max);
|
||||
|
||||
/* This emits context update with buffer size 1024 */
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv > 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, 2);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(2 == deflater.ctx.hd_table.len);
|
||||
CU_ASSERT(1024 == deflater.ctx.hd_table_bufsize_max);
|
||||
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
|
||||
CU_ASSERT(2 == inflater.ctx.hd_table.len);
|
||||
CU_ASSERT(1024 == inflater.ctx.hd_table_bufsize_max);
|
||||
CU_ASSERT(4096 == inflater.settings_hd_table_bufsize_max);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -776,25 +812,27 @@ static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
|
|||
nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nva, size_t nvlen)
|
||||
{
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t blocklen;
|
||||
nva_out out;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
blocklen = nghttp2_hd_deflate_hd(deflater, &buf, nva, nvlen);
|
||||
rv = nghttp2_hd_deflate_hd(deflater, &bufs, nva, nvlen);
|
||||
blocklen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(blocklen >= 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
|
||||
CU_ASSERT(blocklen == inflate_hd(inflater, &out, buf.pos, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(inflater, &out, &bufs, 0));
|
||||
|
||||
CU_ASSERT(nvlen == out.nvlen);
|
||||
assert_nv_equal(nva, out.nva, nvlen);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_deflate_inflate(void)
|
||||
|
|
|
@ -75,14 +75,27 @@ typedef struct {
|
|||
size_t padding_boundary;
|
||||
} my_user_data;
|
||||
|
||||
static void scripted_data_feed_init(scripted_data_feed *df,
|
||||
uint8_t *data, size_t data_length)
|
||||
static void scripted_data_feed_init2(scripted_data_feed *df,
|
||||
nghttp2_bufs *bufs)
|
||||
{
|
||||
nghttp2_buf_chain *ci;
|
||||
nghttp2_buf *buf;
|
||||
uint8_t *ptr;
|
||||
size_t len;
|
||||
|
||||
memset(df, 0, sizeof(scripted_data_feed));
|
||||
memcpy(df->data, data, data_length);
|
||||
ptr = df->data;
|
||||
len = 0;
|
||||
|
||||
for(ci = bufs->head; ci; ci = ci->next) {
|
||||
buf = &ci->buf;
|
||||
ptr = nghttp2_cpymem(ptr, buf->pos, nghttp2_buf_len(buf));
|
||||
len += nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
df->datamark = df->data;
|
||||
df->datalimit = df->data+data_length;
|
||||
df->feedseq[0] = data_length;
|
||||
df->datalimit = df->data + len;
|
||||
df->feedseq[0] = len;
|
||||
}
|
||||
|
||||
static ssize_t null_send_callback(nghttp2_session *session,
|
||||
|
@ -346,7 +359,7 @@ void test_nghttp2_session_recv(void)
|
|||
const nghttp2_nv nv[] = {
|
||||
MAKE_NV("url", "/")
|
||||
};
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
ssize_t framelen;
|
||||
nghttp2_frame frame;
|
||||
ssize_t i;
|
||||
|
@ -354,8 +367,9 @@ void test_nghttp2_session_recv(void)
|
|||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
nghttp2_hd_deflater deflater;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
|
@ -370,12 +384,16 @@ void test_nghttp2_session_recv(void)
|
|||
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
|
||||
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
|
||||
scripted_data_feed_init2(&df, &bufs);
|
||||
|
||||
framelen = nghttp2_bufs_len(&bufs);
|
||||
|
||||
/* Send 1 byte per each read */
|
||||
for(i = 0; i < nghttp2_buf_len(&buf); ++i) {
|
||||
for(i = 0; i < framelen; ++i) {
|
||||
df.feedseq[i] = 1;
|
||||
}
|
||||
|
||||
|
@ -387,17 +405,20 @@ void test_nghttp2_session_recv(void)
|
|||
}
|
||||
CU_ASSERT(1 == user_data.frame_recv_cb_called);
|
||||
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Received HEADERS without header block, which is valid */
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
|
||||
5, NGHTTP2_PRI_DEFAULT, NULL, 0);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
scripted_data_feed_init2(&df, &bufs);
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(1 == user_data.frame_recv_cb_called);
|
||||
|
||||
|
@ -407,21 +428,25 @@ void test_nghttp2_session_recv(void)
|
|||
/* Some tests for frame too large */
|
||||
nghttp2_session_server_new(&session, &callbacks, &user_data);
|
||||
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
/* Receive PING with too large payload */
|
||||
nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
|
||||
|
||||
framelen = nghttp2_frame_pack_ping(&buf, &frame.ping);
|
||||
rv = nghttp2_frame_pack_ping(&bufs, &frame.ping);
|
||||
|
||||
CU_ASSERT(0 == rv);
|
||||
|
||||
/* Add extra 16 bytes */
|
||||
nghttp2_buf_pos_reserve(&buf, nghttp2_buf_len(&buf) + 16);
|
||||
buf.last += 16;
|
||||
nghttp2_put_uint16be(buf.pos, frame.hd.length + 16);
|
||||
nghttp2_bufs_seek_last_present(&bufs);
|
||||
assert(nghttp2_buf_len(&bufs.cur->buf) >= 16);
|
||||
|
||||
bufs.cur->buf.last += 16;
|
||||
nghttp2_put_uint16be(bufs.cur->buf.pos, frame.hd.length + 16);
|
||||
|
||||
nghttp2_frame_ping_free(&frame.ping);
|
||||
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
scripted_data_feed_init2(&df, &bufs);
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(0 == user_data.frame_recv_cb_called);
|
||||
|
@ -430,7 +455,7 @@ void test_nghttp2_session_recv(void)
|
|||
CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == OB_CTRL(item)->goaway.error_code);
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
|
@ -440,12 +465,12 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
|
|||
nghttp2_session_callbacks callbacks;
|
||||
scripted_data_feed df;
|
||||
my_user_data user_data;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_hd_deflater deflater;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.recv_callback = scripted_recv_callback;
|
||||
|
@ -458,17 +483,18 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
|
|||
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
|
||||
NGHTTP2_PRI_DEFAULT, NULL, 0);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
scripted_data_feed_init2(&df, &bufs);
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -482,14 +508,14 @@ void test_nghttp2_session_recv_invalid_frame(void)
|
|||
const nghttp2_nv nv[] = {
|
||||
MAKE_NV("url", "/")
|
||||
};
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
nghttp2_hd_deflater deflater;
|
||||
int rv;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.recv_callback = scripted_recv_callback;
|
||||
|
@ -503,11 +529,12 @@ void test_nghttp2_session_recv_invalid_frame(void)
|
|||
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
|
||||
NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
scripted_data_feed_init2(&df, &bufs);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
|
@ -515,13 +542,13 @@ void test_nghttp2_session_recv_invalid_frame(void)
|
|||
|
||||
/* Receive exactly same bytes of HEADERS is treated as subsequent
|
||||
HEADERS (e.g., trailers */
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
scripted_data_feed_init2(&df, &bufs);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
CU_ASSERT(0 == user_data.frame_send_cb_called);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
|
@ -680,7 +707,8 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
nghttp2_nv *nva;
|
||||
size_t nvlen;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_buf *buf;
|
||||
ssize_t rv;
|
||||
my_user_data ud;
|
||||
nghttp2_hd_deflater deflater;
|
||||
|
@ -688,7 +716,7 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
size_t datalen;
|
||||
nghttp2_frame_hd cont_hd;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.on_header_callback = on_header_callback;
|
||||
|
@ -702,16 +730,21 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE,
|
||||
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
/* make sure that all data is in the first buf */
|
||||
buf = &bufs.head->buf;
|
||||
assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
/* HEADERS's payload is 1 byte */
|
||||
memcpy(data, buf.pos, 9);
|
||||
memcpy(data, buf->pos, 9);
|
||||
datalen = 9;
|
||||
buf.pos += 9;
|
||||
buf->pos += 9;
|
||||
|
||||
nghttp2_put_uint16be(data, 1);
|
||||
|
||||
|
@ -724,23 +757,23 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
|
||||
datalen += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
memcpy(data + datalen, buf.pos, cont_hd.length);
|
||||
memcpy(data + datalen, buf->pos, cont_hd.length);
|
||||
datalen += cont_hd.length;
|
||||
buf.pos += cont_hd.length;
|
||||
buf->pos += cont_hd.length;
|
||||
|
||||
/* Second CONTINUATION, rest of the bytes */
|
||||
cont_hd.length = nghttp2_buf_len(&buf);
|
||||
cont_hd.length = nghttp2_buf_len(buf);
|
||||
cont_hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
||||
cont_hd.stream_id = 1;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
|
||||
datalen += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
memcpy(data + datalen, buf.pos, cont_hd.length);
|
||||
memcpy(data + datalen, buf->pos, cont_hd.length);
|
||||
datalen += cont_hd.length;
|
||||
buf.pos += cont_hd.length;
|
||||
buf->pos += cont_hd.length;
|
||||
|
||||
CU_ASSERT(0 == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == nghttp2_buf_len(buf));
|
||||
|
||||
ud.header_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, data, datalen);
|
||||
|
@ -759,25 +792,32 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE,
|
||||
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||
nghttp2_buf_reset(&buf);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
memcpy(data, buf.pos, nghttp2_buf_len(&buf));
|
||||
datalen = nghttp2_buf_len(&buf);
|
||||
|
||||
/* make sure that all data is in the first buf */
|
||||
buf = &bufs.head->buf;
|
||||
assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
|
||||
|
||||
memcpy(data, buf->pos, nghttp2_buf_len(buf));
|
||||
datalen = nghttp2_buf_len(buf);
|
||||
|
||||
/* Followed by PRIORITY */
|
||||
nghttp2_frame_priority_init(&frame.priority, 1, 0);
|
||||
nghttp2_buf_reset(&buf);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
|
||||
rv = nghttp2_frame_pack_priority(&buf, &frame.priority);
|
||||
rv = nghttp2_frame_pack_priority(&bufs, &frame.priority);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
memcpy(data + datalen, buf.pos, nghttp2_buf_len(&buf));
|
||||
datalen += nghttp2_buf_len(&buf);
|
||||
memcpy(data + datalen, buf->pos, nghttp2_buf_len(buf));
|
||||
datalen += nghttp2_buf_len(buf);
|
||||
|
||||
ud.begin_headers_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, data, datalen);
|
||||
|
@ -787,7 +827,7 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
CU_ASSERT(NGHTTP2_GOAWAY ==
|
||||
OB_CTRL_TYPE(nghttp2_session_get_next_ob_item(session)));
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -803,13 +843,14 @@ void test_nghttp2_session_recv_premature_headers(void)
|
|||
nghttp2_nv *nva;
|
||||
size_t nvlen;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_buf *buf;
|
||||
ssize_t rv;
|
||||
my_user_data ud;
|
||||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_outbound_item *item;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
|
||||
|
@ -820,24 +861,28 @@ void test_nghttp2_session_recv_premature_headers(void)
|
|||
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
|
||||
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
/* Intentionally feed payload cutting last 1 byte off */
|
||||
nghttp2_put_uint16be(buf.pos, frame.hd.length - 1);
|
||||
rv = nghttp2_session_mem_recv(session, buf.pos, nghttp2_buf_len(&buf) - 1);
|
||||
buf = &bufs.head->buf;
|
||||
assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
|
||||
|
||||
CU_ASSERT((ssize_t)(nghttp2_buf_len(&buf) - 1) == rv);
|
||||
/* Intentionally feed payload cutting last 1 byte off */
|
||||
nghttp2_put_uint16be(buf->pos, frame.hd.length - 1);
|
||||
rv = nghttp2_session_mem_recv(session, buf->pos, nghttp2_buf_len(buf) - 1);
|
||||
|
||||
CU_ASSERT((ssize_t)(nghttp2_buf_len(buf) - 1) == rv);
|
||||
|
||||
item = nghttp2_session_get_next_ob_item(session);
|
||||
CU_ASSERT(NULL != item);
|
||||
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
|
||||
CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == OB_CTRL(item)->goaway.error_code);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -855,7 +900,8 @@ void test_nghttp2_session_continue(void)
|
|||
MAKE_NV("user-agent", "nghttp2/1.0.0"),
|
||||
MAKE_NV("alpha", "bravo")
|
||||
};
|
||||
nghttp2_buf buf;
|
||||
nghttp2_bufs bufs;
|
||||
nghttp2_buf *buf;
|
||||
size_t framelen1, framelen2;
|
||||
ssize_t rv;
|
||||
uint8_t buffer[4096];
|
||||
|
@ -867,7 +913,7 @@ void test_nghttp2_session_continue(void)
|
|||
nghttp2_frame_hd data_hd;
|
||||
nghttp2_hd_deflater deflater;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
frame_pack_bufs_init(&bufs);
|
||||
nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
|
@ -885,27 +931,34 @@ void test_nghttp2_session_continue(void)
|
|||
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
|
||||
1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
framelen1 = nghttp2_buf_len(&buf);
|
||||
databuf.last = nghttp2_cpymem(databuf.last, buf.pos, nghttp2_buf_len(&buf));
|
||||
buf = &bufs.head->buf;
|
||||
assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
|
||||
|
||||
framelen1 = nghttp2_buf_len(buf);
|
||||
databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
|
||||
|
||||
nvlen = nghttp2_nv_array_copy(&nva, nv2, ARRLEN(nv2));
|
||||
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
|
||||
3, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||
nghttp2_buf_reset(&buf);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
nghttp2_bufs_reset(&bufs);
|
||||
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(nghttp2_bufs_len(&bufs) > 0);
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
framelen2 = nghttp2_buf_len(&buf);
|
||||
databuf.last = nghttp2_cpymem(databuf.last, buf.pos, nghttp2_buf_len(&buf));
|
||||
assert(nghttp2_bufs_len(&bufs) == nghttp2_buf_len(buf));
|
||||
|
||||
framelen2 = nghttp2_buf_len(buf);
|
||||
databuf.last = nghttp2_cpymem(databuf.last, buf->pos, nghttp2_buf_len(buf));
|
||||
|
||||
/* Receive 1st HEADERS and pause */
|
||||
user_data.begin_headers_cb_called = 0;
|
||||
|
@ -1020,7 +1073,7 @@ void test_nghttp2_session_continue(void)
|
|||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(1 == user_data.frame_recv_cb_called);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -2266,7 +2319,8 @@ void test_nghttp2_submit_data(void)
|
|||
nghttp2_private_data *data_frame;
|
||||
nghttp2_frame_hd hd;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
nghttp2_buf *framebuf;
|
||||
nghttp2_bufs *framebufs;
|
||||
nghttp2_buf *buf;
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = block_count_send_callback;
|
||||
|
@ -2275,7 +2329,7 @@ void test_nghttp2_submit_data(void)
|
|||
ud.data_source_length = NGHTTP2_DATA_PAYLOAD_LENGTH * 2;
|
||||
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
|
||||
aob = &session->aob;
|
||||
framebuf = &aob->framebuf;
|
||||
framebufs = &aob->framebufs;
|
||||
|
||||
nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
|
||||
NGHTTP2_PRI_DEFAULT, NGHTTP2_STREAM_OPENING,
|
||||
|
@ -2287,7 +2341,9 @@ void test_nghttp2_submit_data(void)
|
|||
ud.block_count = 0;
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
|
||||
nghttp2_frame_unpack_frame_hd(&hd, framebuf->pos);
|
||||
|
||||
buf = &framebufs->head->buf;
|
||||
nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
|
||||
|
||||
CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
|
||||
/* frame->hd.flags has these flags */
|
||||
|
@ -2297,7 +2353,7 @@ void test_nghttp2_submit_data(void)
|
|||
ud.block_count = 1;
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
|
||||
nghttp2_frame_unpack_frame_hd(&hd, framebuf->pos);
|
||||
nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
|
||||
|
||||
/* This is the last frame, so we must have following flags */
|
||||
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT) == hd.flags);
|
||||
|
@ -2349,6 +2405,9 @@ void test_nghttp2_submit_request_without_data(void)
|
|||
nghttp2_frame frame;
|
||||
nghttp2_hd_inflater inflater;
|
||||
nva_out out;
|
||||
nghttp2_bufs bufs;
|
||||
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
acc.length = 0;
|
||||
|
@ -2367,12 +2426,14 @@ void test_nghttp2_submit_request_without_data(void)
|
|||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
|
||||
|
||||
inflate_hd(&inflater, &out, acc.buf + 8, acc.length - 8);
|
||||
nghttp2_bufs_add(&bufs, acc.buf, acc.length);
|
||||
inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
CU_ASSERT(nvnameeq(":version", &out.nva[0]));
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
nva_out_reset(&out);
|
||||
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -2421,6 +2482,9 @@ void test_nghttp2_submit_response_without_data(void)
|
|||
nghttp2_frame frame;
|
||||
nghttp2_hd_inflater inflater;
|
||||
nva_out out;
|
||||
nghttp2_bufs bufs;
|
||||
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
acc.length = 0;
|
||||
|
@ -2442,11 +2506,13 @@ void test_nghttp2_submit_response_without_data(void)
|
|||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
|
||||
|
||||
inflate_hd(&inflater, &out, acc.buf + 8, acc.length - 8);
|
||||
nghttp2_bufs_add(&bufs, acc.buf, acc.length);
|
||||
inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
CU_ASSERT(nvnameeq(":version", &out.nva[0]));
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_session_del(session);
|
||||
|
@ -2591,6 +2657,9 @@ void test_nghttp2_submit_headers(void)
|
|||
nghttp2_frame frame;
|
||||
nghttp2_hd_inflater inflater;
|
||||
nva_out out;
|
||||
nghttp2_bufs bufs;
|
||||
|
||||
frame_pack_bufs_init(&bufs);
|
||||
|
||||
nva_out_init(&out);
|
||||
acc.length = 0;
|
||||
|
@ -2633,11 +2702,13 @@ void test_nghttp2_submit_headers(void)
|
|||
|
||||
CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
|
||||
|
||||
inflate_hd(&inflater, &out, acc.buf + 8, acc.length - 8);
|
||||
nghttp2_bufs_add(&bufs, acc.buf, acc.length);
|
||||
inflate_hd(&inflater, &out, &bufs, NGHTTP2_FRAME_HDLEN);
|
||||
|
||||
CU_ASSERT(nvnameeq(":version", &out.nva[0]));
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_bufs_free(&bufs);
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
|
@ -4066,13 +4137,14 @@ void test_nghttp2_session_data_backoff_by_high_pri_frame(void)
|
|||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
static void check_session_recv_data_with_padding(const uint8_t *in,
|
||||
size_t inlen,
|
||||
static void check_session_recv_data_with_padding(nghttp2_bufs *bufs,
|
||||
size_t datalen)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
my_user_data ud;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
uint8_t *in;
|
||||
size_t inlen;
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||
|
@ -4083,13 +4155,17 @@ static void check_session_recv_data_with_padding(const uint8_t *in,
|
|||
NGHTTP2_PRI_DEFAULT, NGHTTP2_STREAM_OPENING,
|
||||
NULL);
|
||||
|
||||
inlen = nghttp2_bufs_remove(bufs, &in);
|
||||
|
||||
ud.frame_recv_cb_called = 0;
|
||||
ud.data_chunk_len = 0;
|
||||
|
||||
CU_ASSERT((ssize_t)inlen == nghttp2_session_mem_recv(session, in, inlen));
|
||||
|
||||
CU_ASSERT(1 == ud.frame_recv_cb_called);
|
||||
CU_ASSERT(datalen == ud.data_chunk_len);
|
||||
|
||||
free(in);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
|
@ -4124,14 +4200,12 @@ void test_nghttp2_session_pack_data_with_padding(void)
|
|||
frame = OB_DATA(session->aob.item);
|
||||
|
||||
CU_ASSERT(ud.padding_boundary - datalen == frame->padlen);
|
||||
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_LOW);
|
||||
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH);
|
||||
/* We no longer set PAD_HIGH and PAD_LOW flags in frame->hd */
|
||||
/* CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_LOW); */
|
||||
/* CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH); */
|
||||
|
||||
/* Check reception of this DATA frame */
|
||||
check_session_recv_data_with_padding
|
||||
(session->aob.framebuf.pos,
|
||||
session->aob.framebuf.mark - session->aob.framebuf.pos,
|
||||
datalen);
|
||||
check_session_recv_data_with_padding(&session->aob.framebufs, datalen);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
||||
|
@ -4150,14 +4224,12 @@ void test_nghttp2_session_pack_data_with_padding(void)
|
|||
|
||||
frame = OB_DATA(session->aob.item);
|
||||
CU_ASSERT((frame->padlen + datalen) % ud.padding_boundary == 0);
|
||||
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_LOW);
|
||||
/* We no longer set PAD_HIGH and PAD_LOW flags in frame->hd */
|
||||
/* CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PAD_LOW); */
|
||||
CU_ASSERT(0 == (frame->hd.flags & NGHTTP2_FLAG_PAD_HIGH));
|
||||
|
||||
/* Check reception of this DATA frame */
|
||||
check_session_recv_data_with_padding
|
||||
(session->aob.framebuf.pos,
|
||||
session->aob.framebuf.mark - session->aob.framebuf.pos,
|
||||
datalen);
|
||||
check_session_recv_data_with_padding(&session->aob.framebufs, datalen);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
|
|
@ -28,8 +28,15 @@
|
|||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
int unpack_framebuf(nghttp2_frame *frame, nghttp2_buf *buf)
|
||||
#include "nghttp2_helper.h"
|
||||
|
||||
int unpack_framebuf(nghttp2_frame *frame, nghttp2_bufs *bufs)
|
||||
{
|
||||
nghttp2_buf *buf;
|
||||
|
||||
/* Assuming we have required data in first buffer. We don't decode
|
||||
header block so, we don't mind its space */
|
||||
buf = &bufs->head->buf;
|
||||
return unpack_frame(frame, buf->pos, nghttp2_buf_len(buf));
|
||||
}
|
||||
|
||||
|
@ -143,21 +150,44 @@ void add_out(nva_out *out, nghttp2_nv *nv)
|
|||
}
|
||||
|
||||
ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
|
||||
uint8_t *buf, size_t buflen)
|
||||
nghttp2_bufs *bufs, size_t offset)
|
||||
{
|
||||
ssize_t rv;
|
||||
nghttp2_nv nv;
|
||||
int inflate_flags;
|
||||
size_t initial = buflen;
|
||||
nghttp2_buf_chain *ci;
|
||||
nghttp2_buf *buf;
|
||||
nghttp2_buf bp;
|
||||
int final;
|
||||
size_t processed;
|
||||
|
||||
processed = 0;
|
||||
|
||||
for(ci = bufs->head; ci; ci = ci->next) {
|
||||
buf = &ci->buf;
|
||||
final = nghttp2_buf_len(buf) == 0 || ci->next == NULL;
|
||||
bp = *buf;
|
||||
|
||||
if(offset) {
|
||||
int n;
|
||||
|
||||
n = nghttp2_min((ssize_t)offset, nghttp2_buf_len(&bp));
|
||||
bp.pos += n;
|
||||
offset -= n;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
inflate_flags = 0;
|
||||
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, buf, buflen, 1);
|
||||
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags,
|
||||
bp.pos, nghttp2_buf_len(&bp), final);
|
||||
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
buf += rv;
|
||||
buflen -= rv;
|
||||
|
||||
bp.pos += rv;
|
||||
processed += rv;
|
||||
|
||||
if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
|
||||
add_out(out, &nv);
|
||||
}
|
||||
|
@ -165,6 +195,21 @@ ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nghttp2_hd_inflate_end_headers(inflater);
|
||||
return initial - buflen;
|
||||
|
||||
return processed;
|
||||
}
|
||||
|
||||
void frame_pack_bufs_init(nghttp2_bufs *bufs)
|
||||
{
|
||||
/* 2 for PAD_HIGH and PAD_LOW */
|
||||
nghttp2_bufs_init2(bufs, 4096, 16, NGHTTP2_FRAME_HDLEN + 2);
|
||||
}
|
||||
|
||||
void bufs_large_init(nghttp2_bufs *bufs, size_t chunk_size)
|
||||
{
|
||||
/* 2 for PAD_HIGH and PAD_LOW */
|
||||
nghttp2_bufs_init2(bufs, chunk_size, 16, NGHTTP2_FRAME_HDLEN + 2);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@
|
|||
free(a); \
|
||||
} while(0);
|
||||
|
||||
int unpack_framebuf(nghttp2_frame *frame, nghttp2_buf *buf);
|
||||
int unpack_framebuf(nghttp2_frame *frame, nghttp2_bufs *bufs);
|
||||
|
||||
int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len);
|
||||
|
||||
|
@ -75,6 +75,10 @@ void nva_out_reset(nva_out *out);
|
|||
void add_out(nva_out *out, nghttp2_nv *nv);
|
||||
|
||||
ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
|
||||
uint8_t *buf, size_t buflen);
|
||||
nghttp2_bufs *bufs, size_t offset);
|
||||
|
||||
void frame_pack_bufs_init(nghttp2_bufs *bufs);
|
||||
|
||||
void bufs_large_init(nghttp2_bufs *bufs, size_t chunk_size);
|
||||
|
||||
#endif /* NGHTTP2_TEST_HELPER_H */
|
||||
|
|
Loading…
Reference in New Issue