Introduce nghttp2_buf to ease buffer management
This commit is contained in:
parent
d074cb611f
commit
358b4386d3
|
@ -33,6 +33,7 @@ lib_LTLIBRARIES = libnghttp2.la
|
|||
|
||||
OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
|
||||
nghttp2_buffer.c nghttp2_frame.c \
|
||||
nghttp2_buf.c \
|
||||
nghttp2_stream.c nghttp2_outbound_item.c \
|
||||
nghttp2_session.c nghttp2_submit.c \
|
||||
nghttp2_helper.c \
|
||||
|
@ -42,6 +43,7 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
|
|||
|
||||
HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
|
||||
nghttp2_buffer.h nghttp2_frame.h \
|
||||
nghttp2_buf.h \
|
||||
nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \
|
||||
nghttp2_npn.h nghttp2_gzip.h \
|
||||
nghttp2_submit.h nghttp2_outbound_item.h \
|
||||
|
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2.0 C Library
|
||||
*
|
||||
* Copyright (c) 2014 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "nghttp2_buf.h"
|
||||
|
||||
#include "nghttp2_helper.h"
|
||||
|
||||
void nghttp2_buf_init(nghttp2_buf *buf)
|
||||
{
|
||||
buf->begin = NULL;
|
||||
buf->end = NULL;
|
||||
buf->pos = NULL;
|
||||
buf->last = NULL;
|
||||
buf->mark = NULL;
|
||||
}
|
||||
|
||||
int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial)
|
||||
{
|
||||
nghttp2_buf_init(buf);
|
||||
return nghttp2_buf_reserve(buf, initial);
|
||||
}
|
||||
|
||||
void nghttp2_buf_free(nghttp2_buf *buf)
|
||||
{
|
||||
free(buf->begin);
|
||||
}
|
||||
|
||||
int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap)
|
||||
{
|
||||
uint8_t *ptr;
|
||||
size_t cap;
|
||||
|
||||
cap = nghttp2_buf_cap(buf);
|
||||
|
||||
if(cap >= new_cap) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
new_cap = nghttp2_max(new_cap, cap * 2);
|
||||
|
||||
ptr = realloc(buf->begin, new_cap);
|
||||
if(ptr == NULL) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
buf->pos = ptr + (buf->pos - buf->begin);
|
||||
buf->last = ptr + (buf->last - buf->begin);
|
||||
buf->mark = ptr + (buf->mark - buf->begin);
|
||||
buf->begin = ptr;
|
||||
buf->end = ptr + new_cap;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_buf_pos_reserve(nghttp2_buf *buf, size_t new_rel_cap)
|
||||
{
|
||||
return nghttp2_buf_reserve(buf, nghttp2_buf_pos_offset(buf) + new_rel_cap);
|
||||
}
|
||||
|
||||
int nghttp2_buf_last_reserve(nghttp2_buf *buf, size_t new_rel_cap)
|
||||
{
|
||||
return nghttp2_buf_reserve(buf, nghttp2_buf_last_offset(buf) + new_rel_cap);
|
||||
}
|
||||
|
||||
void nghttp2_buf_reset(nghttp2_buf *buf)
|
||||
{
|
||||
buf->pos = buf->last = buf->mark = buf->begin;
|
||||
}
|
||||
|
||||
void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len)
|
||||
{
|
||||
buf->begin = buf->pos = buf->last = buf->mark = begin;
|
||||
buf->end = begin + len;
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2.0 C Library
|
||||
*
|
||||
* Copyright (c) 2014 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef NGHTTP2_BUF_H
|
||||
#define NGHTTP2_BUF_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#include "nghttp2_int.h"
|
||||
|
||||
typedef struct {
|
||||
/* This points to the beginning of the buffer. The effective range
|
||||
of buffer is [begin, end). */
|
||||
uint8_t *begin;
|
||||
/* This points to the memory one byte beyond the end of the
|
||||
buffer. */
|
||||
uint8_t *end;
|
||||
/* The position indicator for effective start of the buffer. pos <=
|
||||
last must be hold. */
|
||||
uint8_t *pos;
|
||||
/* The position indicator for effective one beyond of the end of the
|
||||
buffer. last <= end must be hold. */
|
||||
uint8_t *last;
|
||||
/* Mark arbitrary position in buffer [begin, end) */
|
||||
uint8_t *mark;
|
||||
} nghttp2_buf;
|
||||
|
||||
#define nghttp2_buf_len(BUF) ((BUF)->last - (BUF)->pos)
|
||||
#define nghttp2_buf_avail(BUF) ((BUF)->end - (BUF)->last)
|
||||
#define nghttp2_buf_cap(BUF) ((BUF)->end - (BUF)->begin)
|
||||
|
||||
#define nghttp2_buf_pos_offset(BUF) ((BUF)->pos - (BUF)->begin)
|
||||
#define nghttp2_buf_last_offset(BUF) ((BUF)->last - (BUF)->begin)
|
||||
|
||||
#define nghttp2_buf_shift_right(BUF, AMT) \
|
||||
do { \
|
||||
(BUF)->pos += AMT; \
|
||||
(BUF)->last += AMT; \
|
||||
} while(0)
|
||||
|
||||
#define nghttp2_buf_shift_left(BUF, AMT) \
|
||||
do { \
|
||||
(BUF)->pos -= AMT; \
|
||||
(BUF)->last -= AMT; \
|
||||
} while(0)
|
||||
|
||||
/*
|
||||
* Initializes the |buf|. No memory is allocated in this function. Use
|
||||
* nghttp2_buf_reserve() or nghttp2_buf_reserve2() to allocate memory.
|
||||
*/
|
||||
void nghttp2_buf_init(nghttp2_buf *buf);
|
||||
|
||||
|
||||
/*
|
||||
* Initializes the |buf| and allocates at least |initial| bytes of
|
||||
* memory.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_buf_init2(nghttp2_buf *buf, size_t initial);
|
||||
|
||||
/*
|
||||
* Frees buffer in |buf|.
|
||||
*/
|
||||
void nghttp2_buf_free(nghttp2_buf *buf);
|
||||
|
||||
/*
|
||||
* Extends buffer so that nghttp2_buf_cap() returns at least
|
||||
* |new_cap|. If extensions took place, buffer pointers in |buf| will
|
||||
* change.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the followings
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory
|
||||
*/
|
||||
int nghttp2_buf_reserve(nghttp2_buf *buf, size_t new_cap);
|
||||
|
||||
/*
|
||||
* This function behaves like nghttp2_buf_reserve(), but new capacity
|
||||
* is calculated as nghttp2_buf_pos_offset(buf) + new_rel_cap. In
|
||||
* other words, this function reserves memory at least |new_rel_cap|
|
||||
* bytes from buf->pos.
|
||||
*/
|
||||
int nghttp2_buf_pos_reserve(nghttp2_buf *buf, size_t new_rel_cap);
|
||||
|
||||
/*
|
||||
* This function behaves like nghttp2_buf_reserve(), but new capacity
|
||||
* is calculated as nghttp2_buf_last_offset(buf) + new_rel_cap. In
|
||||
* other words, this function reserves memory at least |new_rel_cap|
|
||||
* bytes from buf->last.
|
||||
*/
|
||||
int nghttp2_buf_last_reserve(nghttp2_buf *buf, size_t new_rel_cap);
|
||||
|
||||
/*
|
||||
* Resets pos, last, mark member of |buf| to buf->begin.
|
||||
*/
|
||||
void nghttp2_buf_reset(nghttp2_buf *buf);
|
||||
|
||||
/*
|
||||
* Initializes |buf| using supplied buffer |begin| of length
|
||||
* |len|. Semantically, the application should not call *_reserve() or
|
||||
* nghttp2_free() functions for |buf|.
|
||||
*/
|
||||
void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len);
|
||||
|
||||
#endif /* NGHTTP2_BUF_H */
|
|
@ -224,50 +224,64 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame)
|
|||
}
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
|
||||
size_t *buflen_ptr,
|
||||
size_t *bufoff_ptr,
|
||||
ssize_t nghttp2_frame_pack_headers(nghttp2_buf *buf,
|
||||
nghttp2_headers *frame,
|
||||
nghttp2_hd_deflater *deflater)
|
||||
{
|
||||
size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2;
|
||||
size_t nv_offset =
|
||||
payloadoff + nghttp2_frame_headers_payload_nv_offset(frame);
|
||||
size_t nv_offset;
|
||||
ssize_t rv;
|
||||
size_t payloadlen;
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(deflater, buf_ptr, buflen_ptr, nv_offset,
|
||||
frame->nva, frame->nvlen);
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
payloadlen = nghttp2_frame_headers_payload_nv_offset(frame) + rv;
|
||||
/* Account for possible PAD_HIGH and PAD_LOW */
|
||||
buf->pos += 2;
|
||||
|
||||
*bufoff_ptr = 2;
|
||||
frame->padlen = 0;
|
||||
frame->hd.length = payloadlen;
|
||||
/* If frame->nvlen == 0, *buflen_ptr may be smaller than
|
||||
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_reserve_buffer(buf_ptr, buflen_ptr, nv_offset);
|
||||
rv = nghttp2_buf_pos_reserve(buf, nv_offset);
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
||||
|
||||
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);
|
||||
buf->pos -= nv_offset;
|
||||
|
||||
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_HEAD_LENGTH);
|
||||
|
||||
/* pack ctrl header after length is determined */
|
||||
if(NGHTTP2_MAX_FRAME_LENGTH < payloadlen) {
|
||||
if(NGHTTP2_MAX_FRAME_LENGTH < frame->hd.length) {
|
||||
/* Needs CONTINUATION */
|
||||
nghttp2_frame_hd hd = frame->hd;
|
||||
|
||||
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
hd.length = NGHTTP2_MAX_FRAME_LENGTH;
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &hd);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
} else {
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &frame->hd);
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
}
|
||||
|
||||
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[payloadoff], frame->pri);
|
||||
nghttp2_put_uint32be(buf->pos + NGHTTP2_FRAME_HDLEN, frame->pri);
|
||||
}
|
||||
return *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
||||
|
@ -284,19 +298,28 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_priority(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
ssize_t nghttp2_frame_pack_priority(nghttp2_buf *buf,
|
||||
nghttp2_priority *frame)
|
||||
{
|
||||
ssize_t framelen= NGHTTP2_FRAME_HEAD_LENGTH + 4;
|
||||
int rv;
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
memset(*buf_ptr, 0, framelen);
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd);
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[8], frame->pri);
|
||||
return framelen;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->pri);
|
||||
buf->last += 4;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
||||
|
@ -306,19 +329,28 @@ 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(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
ssize_t nghttp2_frame_pack_rst_stream(nghttp2_buf *buf,
|
||||
nghttp2_rst_stream *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + 4;
|
||||
int rv;
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
memset(*buf_ptr, 0, framelen);
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd);
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[8], frame->error_code);
|
||||
return framelen;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->error_code);
|
||||
buf->last += 4;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
||||
|
@ -328,19 +360,28 @@ void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
|||
frame->error_code = nghttp2_get_uint32(payload);
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
ssize_t nghttp2_frame_pack_settings(nghttp2_buf *buf,
|
||||
nghttp2_settings *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length;
|
||||
int rv;
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
memset(*buf_ptr, 0, framelen);
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd);
|
||||
nghttp2_frame_pack_settings_payload(*buf_ptr + 8, frame->iv, frame->niv);
|
||||
return framelen;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
buf->last += nghttp2_frame_pack_settings_payload(buf->last,
|
||||
frame->iv, frame->niv);
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
size_t nghttp2_frame_pack_settings_payload(uint8_t *buf,
|
||||
|
@ -395,47 +436,60 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_push_promise(uint8_t **buf_ptr,
|
||||
size_t *buflen_ptr,
|
||||
size_t *bufoff_ptr,
|
||||
ssize_t nghttp2_frame_pack_push_promise(nghttp2_buf *buf,
|
||||
nghttp2_push_promise *frame,
|
||||
nghttp2_hd_deflater *deflater)
|
||||
{
|
||||
size_t payloadoff = NGHTTP2_FRAME_HEAD_LENGTH + 2;
|
||||
size_t nv_offset = payloadoff + 4;
|
||||
size_t nv_offset = NGHTTP2_FRAME_HDLEN + 4;
|
||||
ssize_t rv;
|
||||
size_t payloadlen;
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(deflater, buf_ptr, buflen_ptr, nv_offset,
|
||||
frame->nva, frame->nvlen);
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
payloadlen = 4 + rv;
|
||||
/* Account for possible PAD_HIGH and PAD_LOW */
|
||||
buf->pos += 2;
|
||||
|
||||
*bufoff_ptr = 2;
|
||||
frame->padlen = 0;
|
||||
frame->hd.length = payloadlen;
|
||||
/* If frame->nvlen == 0, *buflen_ptr may be smaller than
|
||||
/* If frame->nvlen == 0, nghttp2_buf_len(buf) may be smaller than
|
||||
nv_offset */
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset);
|
||||
rv = nghttp2_buf_pos_reserve(buf, nv_offset);
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
memset(*buf_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
||||
|
||||
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);
|
||||
buf->pos -= nv_offset;
|
||||
|
||||
if(rv < 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
frame->hd.length = 4 + 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_HEAD_LENGTH);
|
||||
|
||||
/* pack ctrl header after length is determined */
|
||||
if(NGHTTP2_MAX_FRAME_LENGTH < payloadlen) {
|
||||
if(NGHTTP2_MAX_FRAME_LENGTH < frame->hd.length) {
|
||||
/* Needs CONTINUATION */
|
||||
nghttp2_frame_hd hd = frame->hd;
|
||||
|
||||
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
hd.length = NGHTTP2_MAX_FRAME_LENGTH;
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &hd);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
} else {
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr + *bufoff_ptr, &frame->hd);
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
|
||||
}
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[payloadoff], frame->promised_stream_id);
|
||||
return *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length;
|
||||
|
||||
nghttp2_put_uint32be(buf->pos + NGHTTP2_FRAME_HDLEN,
|
||||
frame->promised_stream_id);
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
||||
|
@ -449,19 +503,27 @@ int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
|||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_ping(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_ping *frame)
|
||||
ssize_t nghttp2_frame_pack_ping(nghttp2_buf *buf, nghttp2_ping *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + 8;
|
||||
int rv;
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
memset(*buf_ptr, 0, framelen);
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd);
|
||||
memcpy(&(*buf_ptr)[8], frame->opaque_data, sizeof(frame->opaque_data));
|
||||
return framelen;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
memcpy(buf->last, frame->opaque_data, sizeof(frame->opaque_data));
|
||||
buf->last += sizeof(frame->opaque_data);
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
||||
|
@ -471,21 +533,33 @@ void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
|||
memcpy(frame->opaque_data, payload, sizeof(frame->opaque_data));
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_goaway(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_goaway *frame)
|
||||
ssize_t nghttp2_frame_pack_goaway(nghttp2_buf *buf, nghttp2_goaway *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + frame->hd.length;
|
||||
int rv;
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
memset(*buf_ptr, 0, framelen);
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd);
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[8], frame->last_stream_id);
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[12], frame->error_code);
|
||||
memcpy(&(*buf_ptr)[16], frame->opaque_data, frame->opaque_data_len);
|
||||
return framelen;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->last_stream_id);
|
||||
buf->last += 4;
|
||||
|
||||
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;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
||||
|
@ -499,19 +573,28 @@ void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
|||
frame->opaque_data_len = 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_frame_pack_window_update(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
ssize_t nghttp2_frame_pack_window_update(nghttp2_buf *buf,
|
||||
nghttp2_window_update *frame)
|
||||
{
|
||||
ssize_t framelen = NGHTTP2_FRAME_HEAD_LENGTH + 4;
|
||||
int rv;
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
memset(*buf_ptr, 0, framelen);
|
||||
nghttp2_frame_pack_frame_hd(*buf_ptr, &frame->hd);
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[8], frame->window_size_increment);
|
||||
return framelen;
|
||||
|
||||
memset(buf->last, 0, framelen);
|
||||
|
||||
nghttp2_frame_pack_frame_hd(buf->last, &frame->hd);
|
||||
buf->last += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
nghttp2_put_uint32be(buf->last, frame->window_size_increment);
|
||||
buf->last += 4;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
|
||||
|
@ -654,42 +737,34 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *bufoff_ptr,
|
||||
uint8_t *flags_ptr,
|
||||
size_t payloadlen,
|
||||
size_t padlen)
|
||||
void nghttp2_frame_set_pad(nghttp2_buf *buf, uint8_t *flags_ptr, size_t padlen)
|
||||
{
|
||||
int rv;
|
||||
size_t trail_padlen = 0;
|
||||
/* extra 2 bytes for PAD_HIGH and PAD_LOW. */
|
||||
size_t trail_padoff = *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH + payloadlen;
|
||||
|
||||
if(padlen > 257) {
|
||||
if(padlen > 256) {
|
||||
uint8_t *p;
|
||||
*bufoff_ptr -= 2;
|
||||
|
||||
trail_padlen = padlen - 2;
|
||||
*flags_ptr |= NGHTTP2_FLAG_PAD_HIGH | NGHTTP2_FLAG_PAD_LOW;
|
||||
p = *buf_ptr + *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
|
||||
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_HEAD_LENGTH;
|
||||
*p++ = trail_padlen >> 8;
|
||||
*p = trail_padlen & 0xff;
|
||||
|
||||
} else if(padlen > 0) {
|
||||
--*bufoff_ptr;
|
||||
assert(nghttp2_buf_pos_offset(buf) >= 1);
|
||||
|
||||
/* Consume previous 1 byte, shifting 1 bytes to the left */
|
||||
nghttp2_buf_shift_left(buf, 1);
|
||||
|
||||
trail_padlen = padlen - 1;
|
||||
*flags_ptr |= NGHTTP2_FLAG_PAD_LOW;
|
||||
(*buf_ptr)[*bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH] = trail_padlen;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr,
|
||||
trail_padoff + trail_padlen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
*(buf->pos + NGHTTP2_FRAME_HEAD_LENGTH) = trail_padlen;
|
||||
}
|
||||
/* We have to zero out padding bytes so that we won't reveal the
|
||||
possible internal data to the remote peer */
|
||||
memset((*buf_ptr) + trail_padoff, 0, trail_padlen);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include <nghttp2/nghttp2.h>
|
||||
#include "nghttp2_hd.h"
|
||||
#include "nghttp2_buffer.h"
|
||||
#include "nghttp2_buf.h"
|
||||
|
||||
#define NGHTTP2_FRAME_LENGTH_MASK ((1 << 14) - 1)
|
||||
#define NGHTTP2_STREAM_ID_MASK ((1u << 31) - 1)
|
||||
|
@ -39,7 +40,8 @@
|
|||
#define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK ((1u << 31) - 1)
|
||||
#define NGHTTP2_SETTINGS_ID_MASK ((1 << 24) - 1)
|
||||
|
||||
/* The maximum payload length of a frame */
|
||||
/* The maximum payload length of a frame TODO: Must be renamed as
|
||||
NGHTTP2_MAX_PAYLOAD_LENGTH */
|
||||
#define NGHTTP2_MAX_FRAME_LENGTH ((1 << 14) - 1)
|
||||
|
||||
/* The maximum length of DATA frame payload. To fit entire DATA frame
|
||||
|
@ -48,7 +50,8 @@
|
|||
#define NGHTTP2_DATA_PAYLOAD_LENGTH 4086
|
||||
|
||||
/* The number of bytes of frame header. */
|
||||
#define NGHTTP2_FRAME_HEAD_LENGTH 8
|
||||
#define NGHTTP2_FRAME_HDLEN 8
|
||||
#define NGHTTP2_FRAME_HEAD_LENGTH NGHTTP2_FRAME_HDLEN
|
||||
|
||||
/* The number of bytes for each SETTINGS entry */
|
||||
#define NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH 5
|
||||
|
@ -100,15 +103,12 @@ 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_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr| bytes.
|
||||
* This function expands |*buf_ptr| as necessary to store frame. When
|
||||
* expansion occurred, memory previously pointed by |*buf_ptr| may
|
||||
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
|
||||
* 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.
|
||||
*
|
||||
* The first byte the frame is serialized is returned in the
|
||||
* |*bufoff_ptr|. Currently, it is always 2 to account for possible
|
||||
* PAD_HIGH and PAD_LOW.
|
||||
* The first byte the frame is serialized is returned in the |buf|.
|
||||
*
|
||||
* frame->hd.length is assigned after length is determined during
|
||||
* packing process. If payload length is strictly larger than
|
||||
|
@ -116,8 +116,8 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
|
|||
* but frame->hd.length is set to NGHTTP2_MAX_FRAME_LENGTH and
|
||||
* NGHTTP2_FLAG_END_HEADERS flag is cleared from frame->hd.flags.
|
||||
*
|
||||
* This function returns the size of packed frame (which includes
|
||||
* |*bufoff_ptr| bytes) if it succeeds, or returns one of the
|
||||
* This function returns the size of packed frame (which equals to
|
||||
* nghttp2_buf_len(buf)) if it succeeds, or returns one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
|
@ -127,9 +127,7 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
|
||||
size_t *buflen_ptr,
|
||||
size_t *bufoff_ptr,
|
||||
ssize_t nghttp2_frame_pack_headers(nghttp2_buf *buf,
|
||||
nghttp2_headers *frame,
|
||||
nghttp2_hd_deflater *deflater);
|
||||
|
||||
|
@ -149,9 +147,8 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
|||
|
||||
/*
|
||||
* Packs PRIORITY frame |frame| in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
* length. This function expands |*buf_ptr| as necessary to store
|
||||
* given |frame|.
|
||||
* |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
|
@ -159,7 +156,7 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_priority(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
ssize_t nghttp2_frame_pack_priority(nghttp2_buf *buf,
|
||||
nghttp2_priority *frame);
|
||||
|
||||
/*
|
||||
|
@ -171,10 +168,8 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
|||
|
||||
/*
|
||||
* Packs RST_STREAM frame |frame| in wire frame format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
* length. This function expands |*buf_ptr| as necessary to store
|
||||
* given |frame|. In spdy/2 spec, RST_STREAM wire format is always 16
|
||||
* bytes long.
|
||||
* |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
*
|
||||
* This function returns the size of packed frame if it succeeds, or
|
||||
* returns one of the following negative error codes:
|
||||
|
@ -182,7 +177,7 @@ void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_rst_stream(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
ssize_t nghttp2_frame_pack_rst_stream(nghttp2_buf *buf,
|
||||
nghttp2_rst_stream *frame);
|
||||
|
||||
/*
|
||||
|
@ -194,9 +189,8 @@ void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
|||
|
||||
/*
|
||||
* Packs SETTINGS frame |frame| in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
* length. This function expands |*buf_ptr| as necessary to store
|
||||
* given |frame|.
|
||||
* |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
*
|
||||
* This function returns the size of packed frame if it succeeds, or
|
||||
* returns one of the following negative error codes:
|
||||
|
@ -204,7 +198,7 @@ void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
ssize_t nghttp2_frame_pack_settings(nghttp2_buf *buf,
|
||||
nghttp2_settings *frame);
|
||||
|
||||
/*
|
||||
|
@ -253,14 +247,11 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
|||
|
||||
/*
|
||||
* Packs PUSH_PROMISE frame |frame| in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr| bytes.
|
||||
* This function expands |*buf_ptr| as necessary to store frame. When
|
||||
* expansion occurred, memory previously pointed by |*buf_ptr| may
|
||||
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
|
||||
* |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.
|
||||
*
|
||||
* The first byte the frame is serialized is returned in the
|
||||
* |*bufoff_ptr|. Currently, it is always 2 to account for possible
|
||||
* PAD_HIGH and PAD_LOW.
|
||||
* The first byte the frame is serialized is returned in the |buf|.
|
||||
*
|
||||
* frame->hd.length is assigned after length is determined during
|
||||
* packing process. If payload length is strictly larger than
|
||||
|
@ -268,13 +259,10 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
|||
* but frame->hd.length is set to NGHTTP2_MAX_FRAME_LENGTH and
|
||||
* NGHTTP2_FLAG_END_HEADERS flag is cleared from frame->hd.flags.
|
||||
*
|
||||
* This function returns the size of packed frame (which includes
|
||||
* |*bufoff_ptr| bytes) if it succeeds, or returns one of the
|
||||
* This function returns the size of packed frame (which equals to
|
||||
* nghttp2_buf_len(buf)) if it succeeds, or returns one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* This function returns the size of packed frame 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
|
||||
|
@ -282,9 +270,7 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_push_promise(uint8_t **buf_ptr,
|
||||
size_t *buflen_ptr,
|
||||
size_t *bufoff_ptr,
|
||||
ssize_t nghttp2_frame_pack_push_promise(nghttp2_buf *buf,
|
||||
nghttp2_push_promise *frame,
|
||||
nghttp2_hd_deflater *deflater);
|
||||
|
||||
|
@ -303,10 +289,8 @@ 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_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
* length. This function expands |*buf_ptr| as necessary to store
|
||||
* given |frame|.
|
||||
* Packs PING frame |frame| in wire format and store it in |buf|. This
|
||||
* function expands |buf| as necessary to store given |frame|.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
|
@ -314,8 +298,7 @@ int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_ping(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_ping *frame);
|
||||
ssize_t nghttp2_frame_pack_ping(nghttp2_buf *buf, nghttp2_ping *frame);
|
||||
|
||||
/*
|
||||
* Unpacks PING wire format into |frame|.
|
||||
|
@ -326,9 +309,8 @@ void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
|||
|
||||
/*
|
||||
* Packs GOAWAY frame |frame | in wire format and store it in
|
||||
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
* length. This function expands |*buf_ptr| as necessary to store
|
||||
* given |frame|.
|
||||
* |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
*
|
||||
* This function returns 0 if it succeeds or one of the following
|
||||
* negative error codes:
|
||||
|
@ -336,8 +318,7 @@ void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_goaway(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
nghttp2_goaway *frame);
|
||||
ssize_t nghttp2_frame_pack_goaway(nghttp2_buf *buf, nghttp2_goaway *frame);
|
||||
|
||||
/*
|
||||
* Unpacks GOAWAY wire format into |frame|.
|
||||
|
@ -348,9 +329,8 @@ void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
|||
|
||||
/*
|
||||
* Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
|
||||
* in |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
|
||||
* length. This function expands |*buf_ptr| as necessary to store
|
||||
* given |frame|.
|
||||
* in |buf|. This function expands |buf| as necessary to store given
|
||||
* |frame|.
|
||||
*
|
||||
* This function returns the size of packed frame if it succeeds, or
|
||||
* returns one of the following negative error codes:
|
||||
|
@ -358,7 +338,7 @@ void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
|
|||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_frame_pack_window_update(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
ssize_t nghttp2_frame_pack_window_update(nghttp2_buf *buf,
|
||||
nghttp2_window_update *frame);
|
||||
|
||||
/*
|
||||
|
@ -508,29 +488,22 @@ void nghttp2_nv_array_del(nghttp2_nv *nva);
|
|||
int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
||||
|
||||
/*
|
||||
* Add padding to the payload in the |*buf_ptr| of length
|
||||
* |*buflen_ptr|. The payload length is given in |payloadlen|. The
|
||||
* frame header starts at offset |*bufoff_ptr|. Therefore, the payload
|
||||
* must start at offset *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH from
|
||||
* |*buf_ptr| to account for PAD_HIGH and PAD_LOW. The padding is
|
||||
* 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|.
|
||||
*
|
||||
* The |*flags_ptr| is updated to include NGHTTP2_FLAG_PAD_LOW and
|
||||
* NGHTTP2_FLAG_PAD_HIGH based on the padding length. The
|
||||
* |*bufoff_ptr| will have the offset starting the frame header in
|
||||
* |*buf_ptr|.
|
||||
* NGHTTP2_FLAG_PAD_HIGH based on the padding length.
|
||||
*
|
||||
* The |*buf_ptr| and |*buflen_ptr| may be extended to include padding
|
||||
* bytes.
|
||||
* 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 allocate
|
||||
* buffer size as if these 2 bytes always exist. Depending of the
|
||||
* length of the padding, we move the location of frame header and
|
||||
* adjust |*bufoff_ptr|. If more than or equal to 256 padding is made,
|
||||
* the |*bufoff_ptr| is 0 and the content of the |*buf_ptr| looks like
|
||||
* this:
|
||||
* 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
|
||||
|
@ -543,8 +516,8 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
|||
* +---------------+---------------+-------------------------------+
|
||||
*
|
||||
*
|
||||
* If padding is less than 256 but strictly more than 0, the
|
||||
* |*bufoff_ptr| is 1 and the |*buf_ptr| looks like this:
|
||||
* 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
|
||||
|
@ -556,8 +529,8 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
|||
* . Frame Header | Pad low | Payload ...
|
||||
* +---------------+---------------+-------------------------------+
|
||||
*
|
||||
* If no padding is added, the |*bufoff_ptr| is 2 and the |*buf_ptr|
|
||||
* looks like this:
|
||||
* 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
|
||||
|
@ -571,17 +544,10 @@ int nghttp2_iv_check(const nghttp2_settings_entry *iv, size_t niv);
|
|||
*
|
||||
* 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_ptr| is large
|
||||
* enough to account the additional padding, of course).
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* additional copy operation is required (if the |buf| is large enough
|
||||
* to account the additional padding, of course).
|
||||
*/
|
||||
int nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *bufoff_ptr, uint8_t *flags_ptr,
|
||||
size_t payloadlen, size_t padlen);
|
||||
void nghttp2_frame_set_pad(nghttp2_buf *buf, uint8_t *flags_ptr,
|
||||
size_t padlen);
|
||||
|
||||
#endif /* NGHTTP2_FRAME_H */
|
||||
|
|
250
lib/nghttp2_hd.c
250
lib/nghttp2_hd.c
|
@ -436,17 +436,21 @@ static int emit_indname_header(nghttp2_nv *nv_out, nghttp2_hd_entry *ent,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int ensure_write_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t offset, size_t need)
|
||||
static int ensure_write_buffer(nghttp2_buf *buf, size_t need)
|
||||
{
|
||||
int rv;
|
||||
if(need + offset > NGHTTP2_HD_MAX_BUFFER_LENGTH) {
|
||||
|
||||
need += nghttp2_buf_last_offset(buf);
|
||||
|
||||
if(need > NGHTTP2_HD_MAX_BUFFER_LENGTH) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, offset + need);
|
||||
|
||||
rv = nghttp2_buf_reserve(buf, need);
|
||||
if(rv != 0) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -556,55 +560,68 @@ static uint8_t* decode_length(ssize_t *res, int *final, ssize_t initial,
|
|||
return in + 1;
|
||||
}
|
||||
|
||||
static int emit_clear_refset(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr)
|
||||
static int emit_clear_refset(nghttp2_buf *buf)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *bufp;
|
||||
rv = ensure_write_buffer(buf_ptr, buflen_ptr, *offset_ptr, 2);
|
||||
|
||||
rv = ensure_write_buffer(buf, 2);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
bufp = *buf_ptr + *offset_ptr;
|
||||
|
||||
bufp = buf->last;
|
||||
*bufp++ = 0x80u;
|
||||
*bufp = 0x80u;
|
||||
*offset_ptr += 2;
|
||||
*bufp++ = 0x80u;
|
||||
|
||||
buf->last = bufp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emit_table_size(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, size_t table_size)
|
||||
static int emit_table_size(nghttp2_buf *buf, size_t table_size)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *bufp;
|
||||
size_t blocklen = 1 + count_encoded_length(table_size, 7);
|
||||
rv = ensure_write_buffer(buf_ptr, buflen_ptr, *offset_ptr, blocklen);
|
||||
size_t blocklen;
|
||||
|
||||
blocklen = 1 + count_encoded_length(table_size, 7);
|
||||
|
||||
rv = ensure_write_buffer(buf, blocklen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
DEBUGF(fprintf(stderr, "emit table_size=%zu\n", table_size));
|
||||
bufp = *buf_ptr + *offset_ptr;
|
||||
|
||||
bufp = buf->last;
|
||||
|
||||
*bufp++ = 0x80u;
|
||||
*bufp = 0;
|
||||
encode_length(bufp, table_size, 7);
|
||||
*offset_ptr += blocklen;
|
||||
|
||||
buf->last += blocklen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emit_indexed_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, size_t index)
|
||||
static int emit_indexed_block(nghttp2_buf *buf, size_t index)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *bufp;
|
||||
size_t blocklen = count_encoded_length(index + 1, 7);
|
||||
rv = ensure_write_buffer(buf_ptr, buflen_ptr, *offset_ptr, blocklen);
|
||||
size_t blocklen;
|
||||
|
||||
blocklen = count_encoded_length(index + 1, 7);
|
||||
|
||||
rv = ensure_write_buffer(buf, blocklen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
bufp = *buf_ptr + *offset_ptr;
|
||||
*bufp = 0x80u;
|
||||
encode_length(bufp, index + 1, 7);
|
||||
*offset_ptr += blocklen;
|
||||
|
||||
*buf->last = 0x80u;
|
||||
encode_length(buf->last, index + 1, 7);
|
||||
|
||||
buf->last += blocklen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -613,6 +630,7 @@ static size_t emit_string(uint8_t *buf, size_t buflen,
|
|||
const uint8_t *str, size_t len)
|
||||
{
|
||||
size_t rv;
|
||||
|
||||
*buf = huffman ? 1 << 7 : 0;
|
||||
rv = encode_length(buf, enclen, 7);
|
||||
buf += rv;
|
||||
|
@ -625,66 +643,89 @@ static size_t emit_string(uint8_t *buf, size_t buflen,
|
|||
return rv + enclen;
|
||||
}
|
||||
|
||||
static int emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, size_t index,
|
||||
static int emit_indname_block(nghttp2_buf *buf, size_t index,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
int inc_indexing)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *bufp;
|
||||
size_t encvallen = nghttp2_hd_huff_encode_count(value, valuelen);
|
||||
size_t blocklen = count_encoded_length(index + 1, 6);
|
||||
int huffman = encvallen < valuelen;
|
||||
size_t encvallen;
|
||||
size_t blocklen;
|
||||
int huffman;
|
||||
|
||||
encvallen = nghttp2_hd_huff_encode_count(value, valuelen);
|
||||
blocklen = count_encoded_length(index + 1, 6);
|
||||
huffman = encvallen < valuelen;
|
||||
|
||||
if(!huffman) {
|
||||
encvallen = valuelen;
|
||||
}
|
||||
|
||||
blocklen += count_encoded_length(encvallen, 7) + encvallen;
|
||||
rv = ensure_write_buffer(buf_ptr, buflen_ptr, *offset_ptr, blocklen);
|
||||
|
||||
rv = ensure_write_buffer(buf, blocklen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
bufp = *buf_ptr + *offset_ptr;
|
||||
|
||||
bufp = buf->last;
|
||||
|
||||
*bufp = inc_indexing ? 0 : 0x40u;
|
||||
bufp += encode_length(bufp, index + 1, 6);
|
||||
bufp += emit_string(bufp, *buflen_ptr - (bufp - *buf_ptr),
|
||||
bufp += emit_string(bufp, buf->end - bufp,
|
||||
encvallen, huffman, value, valuelen);
|
||||
assert(bufp - (*buf_ptr + *offset_ptr) == (ssize_t)blocklen);
|
||||
*offset_ptr += blocklen;
|
||||
|
||||
assert(bufp - buf->last == (ssize_t)blocklen);
|
||||
|
||||
buf->last = bufp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, nghttp2_nv *nv,
|
||||
static int emit_newname_block(nghttp2_buf *buf, nghttp2_nv *nv,
|
||||
int inc_indexing)
|
||||
{
|
||||
int rv;
|
||||
uint8_t *bufp;
|
||||
size_t encnamelen =
|
||||
nghttp2_hd_huff_encode_count(nv->name, nv->namelen);
|
||||
size_t encvallen =
|
||||
nghttp2_hd_huff_encode_count(nv->value, nv->valuelen);
|
||||
size_t blocklen = 1;
|
||||
int name_huffman = encnamelen < nv->namelen;
|
||||
int value_huffman = encvallen < nv->valuelen;
|
||||
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;
|
||||
|
||||
if(!name_huffman) {
|
||||
encnamelen = nv->namelen;
|
||||
}
|
||||
if(!value_huffman) {
|
||||
encvallen = nv->valuelen;
|
||||
}
|
||||
|
||||
blocklen += count_encoded_length(encnamelen, 7) + encnamelen +
|
||||
count_encoded_length(encvallen, 7) + encvallen;
|
||||
rv = ensure_write_buffer(buf_ptr, buflen_ptr, *offset_ptr, blocklen);
|
||||
|
||||
rv = ensure_write_buffer(buf, blocklen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
bufp = *buf_ptr + *offset_ptr;
|
||||
|
||||
bufp = buf->last;
|
||||
|
||||
*bufp++ = inc_indexing ? 0 : 0x40u;
|
||||
bufp += emit_string(bufp, *buflen_ptr - (bufp - *buf_ptr),
|
||||
bufp += emit_string(bufp, buf->end - bufp,
|
||||
encnamelen, name_huffman, nv->name, nv->namelen);
|
||||
bufp += emit_string(bufp, *buflen_ptr - (bufp - *buf_ptr),
|
||||
bufp += emit_string(bufp, buf->end - bufp,
|
||||
encvallen, value_huffman, nv->value, nv->valuelen);
|
||||
*offset_ptr += blocklen;
|
||||
|
||||
assert(bufp - buf->last == (ssize_t)blocklen);
|
||||
|
||||
buf->last = bufp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -692,15 +733,12 @@ static int emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
|||
* Emit common header with |index| by toggle off and on (thus 2
|
||||
* indexed representation emissions).
|
||||
*/
|
||||
static int emit_implicit(uint8_t **buf_ptr,
|
||||
size_t *buflen_ptr,
|
||||
size_t *offset_ptr,
|
||||
size_t index)
|
||||
static int emit_implicit(nghttp2_buf *buf, size_t index)
|
||||
{
|
||||
int i;
|
||||
int rv;
|
||||
int i, rv;
|
||||
|
||||
for(i = 0; i < 2; ++i) {
|
||||
rv = emit_indexed_block(buf_ptr, buflen_ptr, offset_ptr, index);
|
||||
rv = emit_indexed_block(buf, index);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -709,26 +747,29 @@ static int emit_implicit(uint8_t **buf_ptr,
|
|||
}
|
||||
|
||||
static nghttp2_hd_entry* add_hd_table_incremental(nghttp2_hd_context *context,
|
||||
uint8_t **buf_ptr,
|
||||
size_t *buflen_ptr,
|
||||
size_t *offset_ptr,
|
||||
nghttp2_buf *buf,
|
||||
nghttp2_nv *nv,
|
||||
uint8_t entry_flags)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_hd_entry *new_ent;
|
||||
size_t room = entry_room(nv->namelen, nv->valuelen);
|
||||
size_t room;
|
||||
|
||||
room = entry_room(nv->namelen, nv->valuelen);
|
||||
|
||||
while(context->hd_table_bufsize + room > context->hd_table_bufsize_max &&
|
||||
context->hd_table.len > 0) {
|
||||
|
||||
size_t index = context->hd_table.len - 1;
|
||||
nghttp2_hd_entry* ent = nghttp2_hd_ringbuf_get(&context->hd_table, index);
|
||||
|
||||
context->hd_table_bufsize -= entry_room(ent->nv.namelen, ent->nv.valuelen);
|
||||
if(context->role == NGHTTP2_HD_ROLE_DEFLATE) {
|
||||
if(ent->flags & NGHTTP2_HD_FLAG_IMPLICIT_EMIT) {
|
||||
/* 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_ptr, buflen_ptr, offset_ptr, index);
|
||||
rv = emit_implicit(buf, index);
|
||||
if(rv != 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -948,24 +989,25 @@ static int hd_deflate_should_indexing(nghttp2_hd_deflater *deflater,
|
|||
}
|
||||
|
||||
static int deflate_nv(nghttp2_hd_deflater *deflater,
|
||||
uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr,
|
||||
nghttp2_nv *nv)
|
||||
nghttp2_buf *buf, nghttp2_nv *nv)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_hd_entry *ent;
|
||||
search_result res;
|
||||
|
||||
res = search_hd_table(&deflater->ctx, nv);
|
||||
|
||||
if(res.index != -1 && res.name_value_match) {
|
||||
size_t index = res.index;
|
||||
|
||||
ent = nghttp2_hd_table_get(&deflater->ctx, index);
|
||||
if(index >= deflater->ctx.hd_table.len) {
|
||||
nghttp2_hd_entry *new_ent;
|
||||
|
||||
/* 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_ptr, buflen_ptr,
|
||||
offset_ptr, &ent->nv,
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, buf, &ent->nv,
|
||||
NGHTTP2_HD_FLAG_NONE);
|
||||
if(!new_ent) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
|
@ -979,13 +1021,13 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
set */
|
||||
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
|
||||
}
|
||||
rv = emit_indexed_block(buf_ptr, buflen_ptr, offset_ptr, index);
|
||||
rv = emit_indexed_block(buf, 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_ptr, buflen_ptr, offset_ptr, index);
|
||||
rv = emit_indexed_block(buf, index);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -1015,7 +1057,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_ptr, buflen_ptr, offset_ptr, index);
|
||||
rv = emit_indexed_block(buf, index);
|
||||
if(rv != 0) {
|
||||
break;
|
||||
}
|
||||
|
@ -1033,12 +1075,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_ptr, buflen_ptr,
|
||||
offset_ptr, &nv_indname,
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, buf, &nv_indname,
|
||||
NGHTTP2_HD_FLAG_VALUE_ALLOC);
|
||||
} else {
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, buf_ptr, buflen_ptr,
|
||||
offset_ptr, nv,
|
||||
new_ent = add_hd_table_incremental(&deflater->ctx, buf, nv,
|
||||
NGHTTP2_HD_FLAG_NAME_ALLOC |
|
||||
NGHTTP2_HD_FLAG_VALUE_ALLOC);
|
||||
}
|
||||
|
@ -1056,10 +1096,9 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
incidx = 1;
|
||||
}
|
||||
if(index == -1) {
|
||||
rv = emit_newname_block(buf_ptr, buflen_ptr, offset_ptr, nv, incidx);
|
||||
rv = emit_newname_block(buf, nv, incidx);
|
||||
} else {
|
||||
rv = emit_indname_block(buf_ptr, buflen_ptr, offset_ptr, index,
|
||||
nv->value, nv->valuelen, incidx);
|
||||
rv = emit_indname_block(buf, index, nv->value, nv->valuelen, incidx);
|
||||
}
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
|
@ -1070,42 +1109,44 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
|
|||
|
||||
static int deflate_post_process_hd_entry(nghttp2_hd_entry *ent,
|
||||
size_t index,
|
||||
uint8_t **buf_ptr,
|
||||
size_t *buflen_ptr,
|
||||
size_t *offset_ptr)
|
||||
nghttp2_buf *buf)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if((ent->flags & NGHTTP2_HD_FLAG_REFSET) &&
|
||||
(ent->flags & NGHTTP2_HD_FLAG_IMPLICIT_EMIT) == 0 &&
|
||||
(ent->flags & NGHTTP2_HD_FLAG_EMIT) == 0) {
|
||||
/* This entry is not present in the current header set and must
|
||||
be removed. */
|
||||
ent->flags ^= NGHTTP2_HD_FLAG_REFSET;
|
||||
rv = emit_indexed_block(buf_ptr, buflen_ptr, offset_ptr, index);
|
||||
|
||||
rv = emit_indexed_block(buf, index);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
ent->flags &= ~(NGHTTP2_HD_FLAG_EMIT | NGHTTP2_HD_FLAG_IMPLICIT_EMIT);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t nv_offset,
|
||||
nghttp2_buf *buf,
|
||||
nghttp2_nv *nv, size_t nvlen)
|
||||
{
|
||||
size_t i, offset;
|
||||
size_t i;
|
||||
int rv = 0;
|
||||
|
||||
assert(nghttp2_buf_len(buf) == 0);
|
||||
|
||||
if(deflater->ctx.bad) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
offset = nv_offset;
|
||||
|
||||
if(deflater->ctx.hd_table_bufsize_max >
|
||||
deflater->deflate_hd_table_bufsize_max) {
|
||||
rv = emit_table_size(buf_ptr, buflen_ptr, &offset,
|
||||
deflater->deflate_hd_table_bufsize_max);
|
||||
rv = emit_table_size(buf, deflater->deflate_hd_table_bufsize_max);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
|
@ -1114,26 +1155,28 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
|||
}
|
||||
|
||||
if(deflater->no_refset) {
|
||||
rv = emit_clear_refset(buf_ptr, buflen_ptr, &offset);
|
||||
rv = emit_clear_refset(buf);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
clear_refset(&deflater->ctx);
|
||||
}
|
||||
for(i = 0; i < nvlen; ++i) {
|
||||
rv = deflate_nv(deflater, buf_ptr, buflen_ptr, &offset, &nv[i]);
|
||||
rv = deflate_nv(deflater, buf, &nv[i]);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
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_ptr, buflen_ptr, &offset);
|
||||
|
||||
rv = deflate_post_process_hd_entry(ent, i, buf);
|
||||
if(rv != 0) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return offset - nv_offset;
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
fail:
|
||||
deflater->ctx.bad = 1;
|
||||
return rv;
|
||||
|
@ -1259,8 +1302,8 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
|
|||
nghttp2_hd_entry *ent = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
|
||||
if(inflater->index >= inflater->ctx.hd_table.len) {
|
||||
nghttp2_hd_entry *new_ent;
|
||||
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, NULL, NULL,
|
||||
&ent->nv, NGHTTP2_HD_FLAG_NONE);
|
||||
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, &ent->nv,
|
||||
NGHTTP2_HD_FLAG_NONE);
|
||||
if(!new_ent) {
|
||||
return NGHTTP2_ERR_NOMEM;
|
||||
}
|
||||
|
@ -1307,8 +1350,7 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
|
|||
uint8_t ent_flags =
|
||||
NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_VALUE_ALLOC |
|
||||
NGHTTP2_HD_FLAG_NAME_GIFT | NGHTTP2_HD_FLAG_VALUE_GIFT;
|
||||
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, NULL, NULL, &nv,
|
||||
ent_flags);
|
||||
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, &nv, ent_flags);
|
||||
if(new_ent) {
|
||||
nghttp2_buffer_release(&inflater->namebuf);
|
||||
nghttp2_buffer_release(&inflater->valuebuf);
|
||||
|
@ -1357,10 +1399,8 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
|
|||
nv.namelen = inflater->ent_name->nv.namelen;
|
||||
nv.value = inflater->valuebuf.buf;
|
||||
nv.valuelen = inflater->valuebuf.len;
|
||||
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, NULL, NULL, &nv,
|
||||
ent_flags);
|
||||
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, &nv, ent_flags);
|
||||
if(!static_name && --inflater->ent_name->ref == 0) {
|
||||
fprintf(stderr, "index=%zu, len=%zu\n", inflater->index, inflater->ctx.hd_table.len);
|
||||
nghttp2_hd_entry_free(inflater->ent_name);
|
||||
free(inflater->ent_name);
|
||||
}
|
||||
|
@ -1693,24 +1733,20 @@ int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int nghttp2_hd_emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, size_t index,
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_buf *buf, size_t index,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
int inc_indexing)
|
||||
{
|
||||
return emit_indname_block(buf_ptr, buflen_ptr, offset_ptr,
|
||||
index, value, valuelen, inc_indexing);
|
||||
return emit_indname_block(buf, index, value, valuelen, inc_indexing);
|
||||
}
|
||||
|
||||
int nghttp2_hd_emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, nghttp2_nv *nv,
|
||||
int nghttp2_hd_emit_newname_block(nghttp2_buf *buf, nghttp2_nv *nv,
|
||||
int inc_indexing)
|
||||
{
|
||||
return emit_newname_block(buf_ptr, buflen_ptr, offset_ptr, nv, inc_indexing);
|
||||
return emit_newname_block(buf, nv, inc_indexing);
|
||||
}
|
||||
|
||||
int nghttp2_hd_emit_table_size(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, size_t table_size)
|
||||
int nghttp2_hd_emit_table_size(nghttp2_buf *buf, size_t table_size)
|
||||
{
|
||||
return emit_table_size(buf_ptr, buflen_ptr, offset_ptr, table_size);
|
||||
return emit_table_size(buf, table_size);
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
#include "nghttp2_hd_huffman.h"
|
||||
#include "nghttp2_buffer.h"
|
||||
#include "nghttp2_buf.h"
|
||||
|
||||
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE (1 << 12)
|
||||
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
|
||||
|
@ -295,16 +296,13 @@ 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_ptr| with the length |*buflen_ptr|.
|
||||
* The output starts after |nv_offset| bytes from |*buf_ptr|.
|
||||
* the buffer pointed by the |buf|. The caller must ensure that
|
||||
* nghttp2_buf_len(buf) == 0 holds. Write starts at buf->last.
|
||||
*
|
||||
* This function expands |*buf_ptr| as necessary to store the
|
||||
* result. When expansion occurred, memory previously pointed by
|
||||
* |*buf_ptr| may change. |*buf_ptr| and |*buflen_ptr| are updated
|
||||
* accordingly.
|
||||
* This function expands |buf| as necessary to store the result.
|
||||
*
|
||||
* This function copies necessary data into |*buf_ptr|. After this
|
||||
* function returns, it is safe to delete the |nva|.
|
||||
* This function copies necessary data into |buf|. 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
|
||||
|
@ -319,8 +317,7 @@ int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
|
|||
* Deflation process has failed.
|
||||
*/
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t nv_offset,
|
||||
nghttp2_buf *buf,
|
||||
nghttp2_nv *nva, size_t nvlen);
|
||||
|
||||
typedef enum {
|
||||
|
@ -373,19 +370,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(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, size_t index,
|
||||
int nghttp2_hd_emit_indname_block(nghttp2_buf *buf, size_t index,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
int inc_indexing);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_newname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, nghttp2_nv *nv,
|
||||
int nghttp2_hd_emit_newname_block(nghttp2_buf *buf, nghttp2_nv *nv,
|
||||
int inc_indexing);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_table_size(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, size_t table_size);
|
||||
int nghttp2_hd_emit_table_size(nghttp2_buf *buf, size_t table_size);
|
||||
|
||||
/* For unittesting purpose */
|
||||
nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
|
||||
|
|
|
@ -382,3 +382,10 @@ int nghttp2_check_header_value(const uint8_t *value, size_t len)
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t* nghttp2_cpymem(uint8_t *dest, uint8_t *src, size_t len)
|
||||
{
|
||||
memcpy(dest, src, len);
|
||||
|
||||
return dest + len;
|
||||
}
|
||||
|
|
|
@ -126,4 +126,11 @@ int nghttp2_should_send_window_update(int32_t local_window_size,
|
|||
*/
|
||||
void nghttp2_free(void *ptr);
|
||||
|
||||
/*
|
||||
* Copies the buffer |src| of length |len| to the destination pointed
|
||||
* by the |dest|, assuming that the |dest| is at lest |len| bytes long
|
||||
* . Returns dest + len.
|
||||
*/
|
||||
uint8_t* nghttp2_cpymem(uint8_t *dest, uint8_t *src, size_t len);
|
||||
|
||||
#endif /* NGHTTP2_HELPER_H */
|
||||
|
|
|
@ -211,7 +211,7 @@ static void nghttp2_active_outbound_item_reset
|
|||
nghttp2_outbound_item_free(aob->item);
|
||||
free(aob->item);
|
||||
aob->item = NULL;
|
||||
aob->framebuflen = aob->framebufoff = aob->framebufmark = 0;
|
||||
nghttp2_buf_reset(&aob->framebuf);
|
||||
aob->state = NGHTTP2_OB_POP_ITEM;
|
||||
}
|
||||
|
||||
|
@ -290,13 +290,12 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
|
|||
(*session_ptr)->server = 1;
|
||||
}
|
||||
|
||||
(*session_ptr)->aob.framebuf = malloc
|
||||
(NGHTTP2_INITIAL_OUTBOUND_FRAMEBUF_LENGTH);
|
||||
if((*session_ptr)->aob.framebuf == NULL) {
|
||||
rv = NGHTTP2_ERR_NOMEM;
|
||||
rv = nghttp2_buf_init2(&(*session_ptr)->aob.framebuf,
|
||||
NGHTTP2_INITIAL_OUTBOUND_FRAMEBUF_LENGTH);
|
||||
if(rv != 0) {
|
||||
goto fail_aob_framebuf;
|
||||
}
|
||||
(*session_ptr)->aob.framebufmax = NGHTTP2_INITIAL_OUTBOUND_FRAMEBUF_LENGTH;
|
||||
|
||||
nghttp2_active_outbound_item_reset(&(*session_ptr)->aob);
|
||||
|
||||
memset((*session_ptr)->remote_settings, 0,
|
||||
|
@ -419,7 +418,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);
|
||||
free(session->aob.framebuf);
|
||||
nghttp2_buf_free(&session->aob.framebuf);
|
||||
free(session);
|
||||
}
|
||||
|
||||
|
@ -1125,6 +1124,36 @@ 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. */
|
||||
|
@ -1133,6 +1162,9 @@ static ssize_t session_headers_add_pad(nghttp2_session *session,
|
|||
{
|
||||
int rv;
|
||||
ssize_t padded_payloadlen;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
|
||||
aob = &session->aob;
|
||||
|
||||
padded_payloadlen = session_call_select_padding(session, frame,
|
||||
frame->hd.length + 1024);
|
||||
|
@ -1143,7 +1175,7 @@ static ssize_t session_headers_add_pad(nghttp2_session *session,
|
|||
frame->headers.padlen = padded_payloadlen - frame->hd.length;
|
||||
frame->hd.length = padded_payloadlen;
|
||||
|
||||
DEBUGF(fprintf(stderr, "payloadlen=%zu, padlen=%zu\n",
|
||||
DEBUGF(fprintf(stderr, "padding selected: payloadlen=%zu, padlen=%zu\n",
|
||||
frame->hd.length, frame->headers.padlen));
|
||||
|
||||
if(frame->hd.length > NGHTTP2_MAX_FRAME_LENGTH) {
|
||||
|
@ -1151,49 +1183,59 @@ static ssize_t session_headers_add_pad(nghttp2_session *session,
|
|||
hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
hd.length = NGHTTP2_MAX_FRAME_LENGTH;
|
||||
|
||||
if(NGHTTP2_MAX_FRAME_LENGTH >
|
||||
frame->hd.length - frame->headers.padlen) {
|
||||
size_t padlen = NGHTTP2_MAX_FRAME_LENGTH -
|
||||
if(NGHTTP2_MAX_FRAME_LENGTH > frame->hd.length - frame->headers.padlen) {
|
||||
size_t padlen;
|
||||
|
||||
padlen = NGHTTP2_MAX_FRAME_LENGTH -
|
||||
(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 = nghttp2_frame_add_pad(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->aob.framebufoff,
|
||||
&hd.flags,
|
||||
hd.length - padlen,
|
||||
padlen);
|
||||
rv = session_reserve_pad_trail(session, frame->headers.padlen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
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(). */
|
||||
}
|
||||
nghttp2_frame_pack_frame_hd
|
||||
(session->aob.framebuf + session->aob.framebufoff, &hd);
|
||||
/* At this point, framebuflen > session->aob.framebufmax. But
|
||||
before we access the missing part, we will allocate it in
|
||||
nghttp2_session_after_frame_sent(). */
|
||||
} else if(frame->headers.padlen > 0) {
|
||||
nghttp2_frame_hd hd = frame->hd;
|
||||
rv = nghttp2_frame_add_pad(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->aob.framebufoff,
|
||||
&hd.flags,
|
||||
frame->hd.length - frame->headers.padlen,
|
||||
frame->headers.padlen);
|
||||
DEBUGF(fprintf(stderr,
|
||||
"first HEADERS/PUSH_PROMISE does not have "
|
||||
"padding payloadlen=%zu", hd.length));
|
||||
|
||||
/* 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
|
||||
(session->aob.framebuf + session->aob.framebufoff, &hd);
|
||||
}
|
||||
return session->aob.framebufoff + NGHTTP2_FRAME_HEAD_LENGTH
|
||||
+ frame->hd.length;
|
||||
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);
|
||||
}
|
||||
|
||||
static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
||||
|
@ -1233,13 +1275,16 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
}
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_headers(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->aob.framebufoff,
|
||||
&frame->headers,
|
||||
&session->hd_deflater);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
}
|
||||
|
||||
DEBUGF(fprintf(stderr,
|
||||
"before padding, HEADERS serialized in %zd bytes\n",
|
||||
nghttp2_buf_len(&session->aob.framebuf)));
|
||||
|
||||
framebuflen = session_headers_add_pad(session, frame);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1266,6 +1311,10 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DEBUGF(fprintf(stderr, "HEADERS serialized in %zd bytes\n",
|
||||
nghttp2_buf_len(&session->aob.framebuf)));
|
||||
|
||||
break;
|
||||
}
|
||||
case NGHTTP2_PRIORITY: {
|
||||
|
@ -1275,7 +1324,6 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
return rv;
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_priority(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&frame->priority);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1284,7 +1332,6 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
}
|
||||
case NGHTTP2_RST_STREAM:
|
||||
framebuflen = nghttp2_frame_pack_rst_stream(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&frame->rst_stream);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1296,7 +1343,6 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
return rv;
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_settings(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&frame->settings);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1316,8 +1362,6 @@ static ssize_t 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,
|
||||
&session->aob.framebufmax,
|
||||
&session->aob.framebufoff,
|
||||
&frame->push_promise,
|
||||
&session->hd_deflater);
|
||||
if(framebuflen < 0) {
|
||||
|
@ -1343,7 +1387,6 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
}
|
||||
case NGHTTP2_PING:
|
||||
framebuflen = nghttp2_frame_pack_ping(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&frame->ping);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1356,7 +1399,6 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
return rv;
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_window_update(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&frame->window_update);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1372,7 +1414,6 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
return NGHTTP2_ERR_GOAWAY_ALREADY_SENT;
|
||||
}
|
||||
framebuflen = nghttp2_frame_pack_goaway(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&frame->goaway);
|
||||
if(framebuflen < 0) {
|
||||
return framebuflen;
|
||||
|
@ -1403,8 +1444,6 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
|
|||
}
|
||||
framebuflen = nghttp2_session_pack_data(session,
|
||||
&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->aob.framebufoff,
|
||||
next_readmax,
|
||||
data_frame);
|
||||
if(framebuflen == NGHTTP2_ERR_DEFERRED) {
|
||||
|
@ -1516,13 +1555,8 @@ static int session_call_before_frame_send(nghttp2_session *session,
|
|||
{
|
||||
int rv;
|
||||
if(session->callbacks.before_frame_send_callback) {
|
||||
/* Adjust frame length to deal with CONTINUATION frame */
|
||||
size_t origlen = frame->hd.length;
|
||||
frame->hd.length =
|
||||
session->aob.framebuflen - NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
rv = session->callbacks.before_frame_send_callback(session, frame,
|
||||
session->user_data);
|
||||
frame->hd.length = origlen;
|
||||
if(rv != 0) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
@ -1558,24 +1592,33 @@ static int session_call_on_frame_send(nghttp2_session *session,
|
|||
static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_outbound_item *item = session->aob.item;
|
||||
nghttp2_active_outbound_item *aob = &session->aob;
|
||||
nghttp2_outbound_item *item = aob->item;
|
||||
nghttp2_buf *framebuf = &aob->framebuf;
|
||||
|
||||
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
|
||||
nghttp2_frame *frame;
|
||||
frame = nghttp2_outbound_item_get_ctrl_frame(session->aob.item);
|
||||
|
||||
frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
||||
|
||||
if(frame->hd.type == NGHTTP2_HEADERS ||
|
||||
frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
if(session->aob.framebufmark < session->aob.framebuflen) {
|
||||
|
||||
if(framebuf->mark < framebuf->last) {
|
||||
nghttp2_frame_hd cont_hd;
|
||||
cont_hd.length = nghttp2_min(session->aob.framebuflen -
|
||||
session->aob.framebufmark,
|
||||
|
||||
cont_hd.length = nghttp2_min(framebuf->last - framebuf->mark,
|
||||
NGHTTP2_MAX_FRAME_LENGTH);
|
||||
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 */
|
||||
session->aob.framebufoff -= NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
if(cont_hd.length + session->aob.framebufmark ==
|
||||
session->aob.framebuflen) {
|
||||
framebuf->pos -= NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
|
||||
if(cont_hd.length + framebuf->mark == framebuf->last) {
|
||||
size_t padlen;
|
||||
|
||||
if(cont_hd.length < frame->headers.padlen) {
|
||||
padlen = cont_hd.length;
|
||||
} else {
|
||||
|
@ -1584,34 +1627,41 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
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));
|
||||
|
||||
cont_hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
||||
nghttp2_frame_set_pad(framebuf, &cont_hd.flags, padlen);
|
||||
|
||||
rv = nghttp2_frame_add_pad(&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->aob.framebufoff,
|
||||
&cont_hd.flags,
|
||||
cont_hd.length - padlen,
|
||||
padlen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
/* we reuses previous up to 2 bytes for PAD_HIGH and
|
||||
PAD_LOW. Because of this, session->aob.framebuflen is 1
|
||||
or 2 bytes longer. Re-compute the value here. */
|
||||
session->aob.framebuflen = session->aob.framebufmark =
|
||||
session->aob.framebufoff + NGHTTP2_FRAME_HEAD_LENGTH +
|
||||
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 {
|
||||
cont_hd.flags = NGHTTP2_FLAG_NONE;
|
||||
session->aob.framebufmark += cont_hd.length;
|
||||
/* If no padding, nothing to be done here */
|
||||
}
|
||||
nghttp2_frame_pack_frame_hd(session->aob.framebuf +
|
||||
session->aob.framebufoff,
|
||||
&cont_hd);
|
||||
}
|
||||
|
||||
nghttp2_frame_pack_frame_hd(framebuf->pos, &cont_hd);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1754,7 +1804,7 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
nghttp2_outbound_item* next_item;
|
||||
nghttp2_stream *stream;
|
||||
|
||||
data_frame = nghttp2_outbound_item_get_data_frame(session->aob.item);
|
||||
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
|
||||
stream = nghttp2_session_get_stream(session, data_frame->hd.stream_id);
|
||||
/* We update flow control window after a frame was completely
|
||||
sent. This is possible because we choose payload length not to
|
||||
|
@ -1786,7 +1836,7 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
if(data_frame->eof ||
|
||||
nghttp2_session_predicate_data_send(session,
|
||||
data_frame->hd.stream_id) != 0) {
|
||||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
nghttp2_active_outbound_item_reset(aob);
|
||||
return 0;
|
||||
}
|
||||
/* Assuming stream is not NULL */
|
||||
|
@ -1795,30 +1845,27 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
/* If priority of this stream is higher or equal to other stream
|
||||
waiting at the top of the queue, we continue to send this
|
||||
data. */
|
||||
if(next_item == NULL || session->aob.item->pri < next_item->pri) {
|
||||
if(next_item == NULL || aob->item->pri < next_item->pri) {
|
||||
size_t next_readmax;
|
||||
next_readmax = nghttp2_session_next_data_read(session, stream);
|
||||
if(next_readmax == 0) {
|
||||
nghttp2_stream_defer_data(stream, session->aob.item,
|
||||
nghttp2_stream_defer_data(stream, aob->item,
|
||||
NGHTTP2_DEFERRED_FLOW_CONTROL);
|
||||
session->aob.item = NULL;
|
||||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
aob->item = NULL;
|
||||
nghttp2_active_outbound_item_reset(aob);
|
||||
|
||||
return 0;
|
||||
}
|
||||
rv = nghttp2_session_pack_data(session,
|
||||
&session->aob.framebuf,
|
||||
&session->aob.framebufmax,
|
||||
&session->aob.framebufoff,
|
||||
next_readmax,
|
||||
rv = nghttp2_session_pack_data(session, framebuf, next_readmax,
|
||||
data_frame);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if(rv == NGHTTP2_ERR_DEFERRED) {
|
||||
nghttp2_stream_defer_data(stream, session->aob.item,
|
||||
NGHTTP2_DEFERRED_NONE);
|
||||
session->aob.item = NULL;
|
||||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
nghttp2_stream_defer_data(stream, aob->item, NGHTTP2_DEFERRED_NONE);
|
||||
aob->item = NULL;
|
||||
nghttp2_active_outbound_item_reset(aob);
|
||||
|
||||
return 0;
|
||||
}
|
||||
if(rv == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
|
@ -1828,24 +1875,26 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
rv = nghttp2_session_add_rst_stream(session,
|
||||
data_frame->hd.stream_id,
|
||||
NGHTTP2_INTERNAL_ERROR);
|
||||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
nghttp2_active_outbound_item_reset(aob);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
assert(rv >= 0);
|
||||
session->aob.framebuflen = session->aob.framebufmark = rv;
|
||||
framebuf->mark = framebuf->last;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Update seq to interleave other streams with the same
|
||||
priority. */
|
||||
session->aob.item->seq = session->next_seq++;
|
||||
rv = nghttp2_pq_push(&session->ob_pq, session->aob.item);
|
||||
aob->item->seq = session->next_seq++;
|
||||
rv = nghttp2_pq_push(&session->ob_pq, aob->item);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
session->aob.item = NULL;
|
||||
aob->item = NULL;
|
||||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1857,10 +1906,15 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
|||
const uint8_t **data_ptr)
|
||||
{
|
||||
int rv;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
nghttp2_buf *framebuf;
|
||||
|
||||
aob = &session->aob;
|
||||
framebuf = &aob->framebuf;
|
||||
|
||||
*data_ptr = NULL;
|
||||
for(;;) {
|
||||
switch(session->aob.state) {
|
||||
switch(aob->state) {
|
||||
case NGHTTP2_OB_POP_ITEM: {
|
||||
nghttp2_outbound_item *item;
|
||||
ssize_t framebuflen;
|
||||
|
@ -1895,7 +1949,7 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
|||
}
|
||||
nghttp2_outbound_item_free(item);
|
||||
free(item);
|
||||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
nghttp2_active_outbound_item_reset(aob);
|
||||
|
||||
if(framebuflen == NGHTTP2_ERR_HEADER_COMP) {
|
||||
/* If header compression error occurred, should terminiate
|
||||
|
@ -1908,32 +1962,43 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
|||
}
|
||||
break;
|
||||
}
|
||||
session->aob.item = item;
|
||||
session->aob.framebuflen = framebuflen;
|
||||
aob->item = item;
|
||||
|
||||
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
|
||||
nghttp2_frame *frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
||||
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_FRAME_LENGTH */
|
||||
session->aob.framebufmark =
|
||||
session->aob.framebufoff + NGHTTP2_FRAME_HEAD_LENGTH +
|
||||
nghttp2_get_uint16(session->aob.framebuf + session->aob.framebufoff);
|
||||
frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
||||
|
||||
framebuf->mark = framebuf->pos + NGHTTP2_FRAME_HEAD_LENGTH +
|
||||
nghttp2_get_uint16(framebuf->pos);
|
||||
|
||||
rv = session_call_before_frame_send(session, frame);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
} else {
|
||||
session->aob.framebufmark = session->aob.framebuflen;
|
||||
framebuf->mark = framebuf->last;
|
||||
}
|
||||
session->aob.state = NGHTTP2_OB_SEND_DATA;
|
||||
|
||||
DEBUGF(fprintf(stderr, "start transmitting type %d frame %zd bytes\n",
|
||||
framebuf->pos[2], framebuf->mark - framebuf->pos));
|
||||
|
||||
aob->state = NGHTTP2_OB_SEND_DATA;
|
||||
|
||||
break;
|
||||
}
|
||||
case NGHTTP2_OB_SEND_DATA: {
|
||||
size_t datalen;
|
||||
|
||||
if(session->aob.framebufoff == session->aob.framebufmark) {
|
||||
if(framebuf->pos == framebuf->mark) {
|
||||
DEBUGF(fprintf(stderr, "end transmission of frame, left %zd\n",
|
||||
framebuf->last - framebuf->mark));
|
||||
|
||||
/* Frame has completely sent */
|
||||
rv = nghttp2_session_after_frame_sent(session);
|
||||
if(rv < 0) {
|
||||
|
@ -1945,11 +2010,11 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
|
|||
break;
|
||||
}
|
||||
|
||||
*data_ptr = session->aob.framebuf + session->aob.framebufoff;
|
||||
datalen = session->aob.framebufmark - session->aob.framebufoff;
|
||||
*data_ptr = framebuf->pos;
|
||||
datalen = framebuf->mark - framebuf->pos;
|
||||
/* We increment the offset here. If send_callback does not send
|
||||
everything, we will adjust it. */
|
||||
session->aob.framebufoff += datalen;
|
||||
framebuf->pos += datalen;
|
||||
|
||||
return datalen;
|
||||
}
|
||||
|
@ -1962,6 +2027,9 @@ int nghttp2_session_send(nghttp2_session *session)
|
|||
const uint8_t *data;
|
||||
ssize_t datalen;
|
||||
ssize_t sentlen;
|
||||
nghttp2_buf *framebuf;
|
||||
|
||||
framebuf = &session->aob.framebuf;
|
||||
|
||||
for(;;) {
|
||||
datalen = nghttp2_session_mem_send(session, &data);
|
||||
|
@ -1973,13 +2041,14 @@ int nghttp2_session_send(nghttp2_session *session)
|
|||
if(sentlen < 0) {
|
||||
if(sentlen == NGHTTP2_ERR_WOULDBLOCK) {
|
||||
/* Transmission canceled. Rewind the offset */
|
||||
session->aob.framebufoff -= datalen;
|
||||
framebuf->pos -= datalen;
|
||||
|
||||
return 0;
|
||||
}
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
/* Rewind the offset to the amount of unsent bytes */
|
||||
session->aob.framebufoff -= datalen - sentlen;
|
||||
framebuf->pos -= datalen - sentlen;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -2083,82 +2152,6 @@ static int session_detect_idle_stream(nghttp2_session *session,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inflates header block in the memory pointed by |in| with |inlen|
|
||||
* bytes. If this function returns NGHTTP2_ERR_PAUSE, the caller must
|
||||
* call this function again, until it returns 0 or one of negative
|
||||
* error code. If |call_header_cb| is zero, the on_header_callback
|
||||
* are not invoked and the function never return NGHTTP2_ERR_PAUSE. If
|
||||
* the given |in| is the last chunk of header block, the |final| must
|
||||
* be nonzero. If header block is successfully processed (which is
|
||||
* indicated by the return value 0, NGHTTP2_ERR_PAUSE or
|
||||
* NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE), the number of processed
|
||||
* input bytes is assigned to the |*readlen_ptr|.
|
||||
*
|
||||
* This function return 0 if it succeeds, or one of the negative error
|
||||
* codes:
|
||||
*
|
||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||
* The callback function failed.
|
||||
* NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
|
||||
* The callback returns this error code, indicating that this
|
||||
* stream should be RST_STREAMed.
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_PAUSE
|
||||
* The callback function returned NGHTTP2_ERR_PAUSE
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Header decompression failed
|
||||
*/
|
||||
static ssize_t inflate_header_block(nghttp2_session *session,
|
||||
nghttp2_frame *frame,
|
||||
size_t *readlen_ptr,
|
||||
uint8_t *in, size_t inlen,
|
||||
int final, int call_header_cb)
|
||||
{
|
||||
ssize_t rv;
|
||||
int inflate_flags;
|
||||
nghttp2_nv nv;
|
||||
*readlen_ptr = 0;
|
||||
|
||||
DEBUGF(fprintf(stderr, "processing header block %zu bytes\n", inlen));
|
||||
for(;;) {
|
||||
inflate_flags = 0;
|
||||
rv = nghttp2_hd_inflate_hd(&session->hd_inflater, &nv, &inflate_flags,
|
||||
in, inlen, final);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if(rv < 0) {
|
||||
rv = nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_COMPRESSION_ERROR);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
in += rv;
|
||||
inlen -= rv;
|
||||
*readlen_ptr += rv;
|
||||
if(call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) {
|
||||
rv = session_call_on_header(session, frame, &nv);
|
||||
/* This handles NGHTTP2_ERR_PAUSE and
|
||||
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
|
||||
nghttp2_hd_inflate_end_headers(&session->hd_inflater);
|
||||
break;
|
||||
}
|
||||
if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && inlen == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handles frame size error.
|
||||
*
|
||||
|
@ -2238,6 +2231,87 @@ static int nghttp2_session_inflate_handle_invalid_connection
|
|||
return NGHTTP2_ERR_IGN_HEADER_BLOCK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Inflates header block in the memory pointed by |in| with |inlen|
|
||||
* bytes. If this function returns NGHTTP2_ERR_PAUSE, the caller must
|
||||
* call this function again, until it returns 0 or one of negative
|
||||
* error code. If |call_header_cb| is zero, the on_header_callback
|
||||
* are not invoked and the function never return NGHTTP2_ERR_PAUSE. If
|
||||
* the given |in| is the last chunk of header block, the |final| must
|
||||
* be nonzero. If header block is successfully processed (which is
|
||||
* indicated by the return value 0, NGHTTP2_ERR_PAUSE or
|
||||
* NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE), the number of processed
|
||||
* input bytes is assigned to the |*readlen_ptr|.
|
||||
*
|
||||
* This function return 0 if it succeeds, or one of the negative error
|
||||
* codes:
|
||||
*
|
||||
* NGHTTP2_ERR_CALLBACK_FAILURE
|
||||
* The callback function failed.
|
||||
* NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
|
||||
* The callback returns this error code, indicating that this
|
||||
* stream should be RST_STREAMed.
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
* NGHTTP2_ERR_PAUSE
|
||||
* The callback function returned NGHTTP2_ERR_PAUSE
|
||||
* NGHTTP2_ERR_HEADER_COMP
|
||||
* Header decompression failed
|
||||
*/
|
||||
static ssize_t inflate_header_block(nghttp2_session *session,
|
||||
nghttp2_frame *frame,
|
||||
size_t *readlen_ptr,
|
||||
uint8_t *in, size_t inlen,
|
||||
int final, int call_header_cb)
|
||||
{
|
||||
ssize_t rv;
|
||||
int inflate_flags;
|
||||
nghttp2_nv nv;
|
||||
*readlen_ptr = 0;
|
||||
|
||||
DEBUGF(fprintf(stderr, "processing header block %zu bytes\n", inlen));
|
||||
for(;;) {
|
||||
inflate_flags = 0;
|
||||
rv = nghttp2_hd_inflate_hd(&session->hd_inflater, &nv, &inflate_flags,
|
||||
in, inlen, final);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if(rv < 0) {
|
||||
if(session->iframe.state == NGHTTP2_IB_READ_HEADER_BLOCK) {
|
||||
rv = nghttp2_session_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_COMPRESSION_ERROR);
|
||||
} else {
|
||||
rv = nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_COMPRESSION_ERROR);
|
||||
}
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
in += rv;
|
||||
inlen -= rv;
|
||||
*readlen_ptr += rv;
|
||||
if(call_header_cb && (inflate_flags & NGHTTP2_HD_INFLATE_EMIT)) {
|
||||
rv = session_call_on_header(session, frame, &nv);
|
||||
/* This handles NGHTTP2_ERR_PAUSE and
|
||||
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE as well */
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
|
||||
nghttp2_hd_inflate_end_headers(&session->hd_inflater);
|
||||
break;
|
||||
}
|
||||
if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 && inlen == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Decompress header blocks of incoming request HEADERS and also call
|
||||
* additional callbacks. This function can be called again if this
|
||||
|
@ -4488,48 +4562,53 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
|
|||
}
|
||||
|
||||
ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
||||
uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *bufoff_ptr,
|
||||
nghttp2_buf *buf,
|
||||
size_t datamax,
|
||||
nghttp2_private_data *frame)
|
||||
{
|
||||
size_t payloadoff;
|
||||
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_hd hd;
|
||||
|
||||
/* 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|. */
|
||||
*bufoff_ptr = 2;
|
||||
payloadoff = *bufoff_ptr + NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
framelen = payloadoff + datamax;
|
||||
buf->pos += 2;
|
||||
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, framelen);
|
||||
framelen = NGHTTP2_FRAME_HDLEN + datamax;
|
||||
|
||||
rv = nghttp2_buf_pos_reserve(buf, framelen);
|
||||
if(rv != 0) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
eof_flags = 0;
|
||||
payloadlen = frame->data_prd.read_callback
|
||||
(session, frame->hd.stream_id, (*buf_ptr) + payloadoff, datamax,
|
||||
(session, frame->hd.stream_id, buf->pos + NGHTTP2_FRAME_HDLEN, datamax,
|
||||
&eof_flags, &frame->data_prd.source, session->user_data);
|
||||
|
||||
if(payloadlen == NGHTTP2_ERR_DEFERRED ||
|
||||
payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
|
||||
DEBUGF(fprintf(stderr, "DATA postponed due to %s\n",
|
||||
nghttp2_strerror(payloadlen)));
|
||||
|
||||
return payloadlen;
|
||||
}
|
||||
|
||||
if(payloadlen < 0 || datamax < (size_t)payloadlen) {
|
||||
/* This is the error code when callback is failed. */
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
|
||||
buf->last = buf->pos + NGHTTP2_FRAME_HDLEN + payloadlen;
|
||||
|
||||
/* Clear flags, because this may contain previous flags of previous
|
||||
DATA */
|
||||
frame->hd.flags &= (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT);
|
||||
|
@ -4545,7 +4624,9 @@ 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;
|
||||
|
@ -4556,25 +4637,31 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
|||
if(nghttp2_is_fatal(padded_payloadlen)) {
|
||||
return padded_payloadlen;
|
||||
}
|
||||
rv = nghttp2_frame_add_pad(buf_ptr, buflen_ptr, bufoff_ptr, &flags,
|
||||
payloadlen, padded_payloadlen - payloadlen);
|
||||
|
||||
padlen = padded_payloadlen - payloadlen;
|
||||
|
||||
rv = session_reserve_pad_trail(session, padlen);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
return rv;
|
||||
}
|
||||
frame->padlen = padded_payloadlen - payloadlen;
|
||||
|
||||
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_ptr + *bufoff_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
||||
nghttp2_put_uint16be(&(*buf_ptr)[*bufoff_ptr], frame->hd.length);
|
||||
memset(buf->pos, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
||||
|
||||
(*buf_ptr)[*bufoff_ptr + 3] = flags;
|
||||
nghttp2_put_uint32be(&(*buf_ptr)[*bufoff_ptr + 4], frame->hd.stream_id);
|
||||
hd = frame->hd;
|
||||
hd.flags = flags;
|
||||
|
||||
return frame->hd.length + NGHTTP2_FRAME_HEAD_LENGTH + *bufoff_ptr;
|
||||
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
|
||||
|
||||
return nghttp2_buf_len(buf);
|
||||
}
|
||||
|
||||
void* nghttp2_session_get_stream_user_data(nghttp2_session *session,
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "nghttp2_buffer.h"
|
||||
#include "nghttp2_outbound_item.h"
|
||||
#include "nghttp2_int.h"
|
||||
#include "nghttp2_buf.h"
|
||||
|
||||
/*
|
||||
* Option flags.
|
||||
|
@ -54,27 +55,15 @@ typedef enum {
|
|||
|
||||
typedef struct {
|
||||
nghttp2_outbound_item *item;
|
||||
/* Buffer for outbound frames. Used to pack one frame. The memory
|
||||
pointed by framebuf is initially allocated by
|
||||
nghttp2_session_{client,server}_new() and deallocated by
|
||||
nghttp2_session_del() */
|
||||
uint8_t *framebuf;
|
||||
/* The capacity of framebuf in bytes */
|
||||
size_t framebufmax;
|
||||
/* The length of the frame stored in framebuf */
|
||||
size_t framebuflen;
|
||||
/* The number of bytes has been sent */
|
||||
size_t framebufoff;
|
||||
/* Marks the last position to send. This is used to implement
|
||||
CONTINUATION */
|
||||
size_t framebufmark;
|
||||
|
||||
nghttp2_buf framebuf;
|
||||
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 4096
|
||||
#define NGHTTP2_INITIAL_OUTBOUND_FRAMEBUF_LENGTH 16384
|
||||
|
||||
#define NGHTTP2_INITIAL_NV_BUFFER_LENGTH 4096
|
||||
|
||||
|
@ -538,8 +527,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,
|
||||
uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *bufoff_ptr,
|
||||
nghttp2_buf *buf,
|
||||
size_t datamax,
|
||||
nghttp2_private_data *frame);
|
||||
|
||||
|
|
|
@ -291,8 +291,7 @@ cdef extern from 'nghttp2_hd.h':
|
|||
size_t hd_table_bufsize_max)
|
||||
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_deflater *deflater,
|
||||
uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t nv_offset,
|
||||
nghttp2_buf *buf,
|
||||
nghttp2_nv *nva, size_t nvlen)
|
||||
|
||||
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
|
||||
|
@ -303,3 +302,14 @@ cdef extern from 'nghttp2_hd.h':
|
|||
|
||||
nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
|
||||
size_t index)
|
||||
|
||||
cdef extern from 'nghttp2_buf.h':
|
||||
|
||||
ctypedef struct nghttp2_buf:
|
||||
uint8_t *pos
|
||||
uint8_t *last
|
||||
|
||||
|
||||
void nghttp2_buf_init(nghttp2_buf *buf)
|
||||
|
||||
void nghttp2_buf_free(nghttp2_buf *buf)
|
||||
|
|
|
@ -106,25 +106,36 @@ cdef class HDDeflater:
|
|||
malloc(sizeof(cnghttp2.nghttp2_nv)*\
|
||||
len(headers))
|
||||
cdef cnghttp2.nghttp2_nv *nvap = nva
|
||||
|
||||
for k, v in headers:
|
||||
nvap[0].name = k
|
||||
nvap[0].namelen = len(k)
|
||||
nvap[0].value = v
|
||||
nvap[0].valuelen = len(v)
|
||||
nvap += 1
|
||||
cdef uint8_t *out = NULL
|
||||
|
||||
cdef cnghttp2.nghttp2_buf buf
|
||||
cdef size_t outcap = 0
|
||||
cdef ssize_t rv
|
||||
rv = cnghttp2.nghttp2_hd_deflate_hd(&self._deflater, &out, &outcap,
|
||||
0, nva, len(headers))
|
||||
|
||||
cnghttp2.nghttp2_buf_init(&buf)
|
||||
|
||||
rv = cnghttp2.nghttp2_hd_deflate_hd(&self._deflater, &buf,
|
||||
nva, len(headers))
|
||||
free(nva)
|
||||
|
||||
if rv < 0:
|
||||
cnghttp2.nghttp2_buf_free(&buf);
|
||||
|
||||
raise Exception(_strerror(rv))
|
||||
|
||||
cdef bytes res
|
||||
|
||||
try:
|
||||
res = out[:rv]
|
||||
res = buf.pos[:rv]
|
||||
finally:
|
||||
cnghttp2.nghttp2_free(out)
|
||||
cnghttp2.nghttp2_buf_free(&buf)
|
||||
|
||||
return res
|
||||
|
||||
def set_no_refset(self, no_refset):
|
||||
|
|
|
@ -72,12 +72,15 @@ static void to_hex(char *dest, const uint8_t *src, size_t len)
|
|||
}
|
||||
|
||||
static void output_to_json(nghttp2_hd_deflater *deflater,
|
||||
const uint8_t *buf, size_t len, size_t inputlen,
|
||||
nghttp2_buf *buf, size_t inputlen,
|
||||
nghttp2_nv *nva, size_t nvlen,
|
||||
int seq)
|
||||
{
|
||||
json_t *obj;
|
||||
char *hex = NULL;
|
||||
size_t len;
|
||||
|
||||
len = nghttp2_buf_len(buf);
|
||||
|
||||
if(len > 0) {
|
||||
hex = malloc(len * 2);
|
||||
|
@ -88,7 +91,7 @@ static void output_to_json(nghttp2_hd_deflater *deflater,
|
|||
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, len);
|
||||
to_hex(hex, buf->pos, len);
|
||||
if(len == 0) {
|
||||
json_object_set_new(obj, "wire", json_string(""));
|
||||
} else {
|
||||
|
@ -114,17 +117,21 @@ static void deflate_hd(nghttp2_hd_deflater *deflater,
|
|||
nghttp2_nv *nva, size_t nvlen, size_t inputlen, int seq)
|
||||
{
|
||||
ssize_t rv;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
rv = nghttp2_hd_deflate_hd(deflater, &buf, &buflen, 0, nva, nvlen);
|
||||
nghttp2_buf buf;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
rv = nghttp2_hd_deflate_hd(deflater, &buf, nva, nvlen);
|
||||
if(rv < 0) {
|
||||
fprintf(stderr, "deflate failed with error code %zd at %d\n", rv, seq);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
input_sum += inputlen;
|
||||
output_sum += rv;
|
||||
output_to_json(deflater, buf, rv, inputlen, nva, nvlen, seq);
|
||||
free(buf);
|
||||
|
||||
output_to_json(deflater, &buf, inputlen, nva, nvlen, seq);
|
||||
nghttp2_buf_free(&buf);
|
||||
}
|
||||
|
||||
static int deflate_hd_json(json_t *obj, nghttp2_hd_deflater *deflater, int seq)
|
||||
|
|
|
@ -202,6 +202,12 @@ int main(int argc, char* argv[])
|
|||
test_nghttp2_session_pack_data_with_padding) ||
|
||||
!CU_add_test(pSuite, "session_pack_headers_with_padding",
|
||||
test_nghttp2_session_pack_headers_with_padding) ||
|
||||
!CU_add_test(pSuite, "session_pack_headers_with_padding2",
|
||||
test_nghttp2_session_pack_headers_with_padding2) ||
|
||||
!CU_add_test(pSuite, "session_pack_headers_with_padding3",
|
||||
test_nghttp2_session_pack_headers_with_padding3) ||
|
||||
!CU_add_test(pSuite, "session_pack_headers_with_padding4",
|
||||
test_nghttp2_session_pack_headers_with_padding4) ||
|
||||
!CU_add_test(pSuite, "pack_settings_payload",
|
||||
test_nghttp2_pack_settings_payload) ||
|
||||
!CU_add_test(pSuite, "frame_pack_headers",
|
||||
|
|
|
@ -72,14 +72,14 @@ void test_nghttp2_frame_pack_headers()
|
|||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_headers frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t bufoff;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
nva_out out;
|
||||
ssize_t nv_offset;
|
||||
ssize_t hdblocklen;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_deflate_init(&deflater);
|
||||
|
@ -91,22 +91,22 @@ 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, &buflen, &bufoff, &frame,
|
||||
&deflater);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame, &deflater);
|
||||
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
||||
framelen - bufoff));
|
||||
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
|
||||
check_frame_header(nghttp2_buf_len(&buf) - 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);
|
||||
|
||||
nv_offset = bufoff + NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
CU_ASSERT(framelen - nv_offset ==
|
||||
hdblocklen = nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN;
|
||||
CU_ASSERT(hdblocklen ==
|
||||
inflate_hd(&inflater, &out,
|
||||
buf + nv_offset, framelen - nv_offset));
|
||||
buf.pos + NGHTTP2_FRAME_HDLEN, hdblocklen));
|
||||
|
||||
CU_ASSERT(7 == out.nvlen);
|
||||
CU_ASSERT(nvnameeq("method", &out.nva[0]));
|
||||
|
@ -114,32 +114,33 @@ void test_nghttp2_frame_pack_headers()
|
|||
|
||||
nghttp2_frame_headers_free(&oframe);
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
memset(&oframe, 0, sizeof(oframe));
|
||||
/* Next, include PRIORITY flag */
|
||||
frame.hd.flags |= NGHTTP2_FLAG_PRIORITY;
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &buflen, &bufoff, &frame,
|
||||
&deflater);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame, &deflater);
|
||||
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf + bufoff,
|
||||
framelen - bufoff));
|
||||
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
|
||||
check_frame_header(nghttp2_buf_len(&buf) - 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);
|
||||
|
||||
nv_offset = bufoff + NGHTTP2_FRAME_HEAD_LENGTH + 4;
|
||||
CU_ASSERT(framelen - nv_offset ==
|
||||
hdblocklen = nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN - 4;
|
||||
CU_ASSERT(hdblocklen ==
|
||||
inflate_hd(&inflater, &out,
|
||||
buf + nv_offset, framelen - nv_offset));
|
||||
buf.pos + NGHTTP2_FRAME_HDLEN + 4, hdblocklen));
|
||||
|
||||
nghttp2_nv_array_sort(out.nva, out.nvlen);
|
||||
CU_ASSERT(nvnameeq("method", &out.nva[0]));
|
||||
|
||||
nva_out_reset(&out);
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_headers_free(&oframe);
|
||||
nghttp2_frame_headers_free(&frame);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
|
@ -150,9 +151,7 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
{
|
||||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_headers frame;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t bufoff;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
|
@ -161,6 +160,8 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
size_t big_hdslen = ARRLEN(big_hds);
|
||||
size_t i;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
for(i = 0; i < big_hdslen; ++i) {
|
||||
big_hds[i].name = (uint8_t*)"header";
|
||||
big_hds[i].value = malloc(big_vallen+1);
|
||||
|
@ -176,12 +177,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, &buflen, &bufoff, &frame,
|
||||
&deflater);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame, &deflater);
|
||||
CU_ASSERT_EQUAL(NGHTTP2_ERR_HEADER_COMP, framelen);
|
||||
|
||||
nghttp2_frame_headers_free(&frame);
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
for(i = 0; i < big_hdslen; ++i) {
|
||||
free(big_hds[i].value);
|
||||
}
|
||||
|
@ -191,16 +191,21 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
void test_nghttp2_frame_pack_priority(void)
|
||||
{
|
||||
nghttp2_priority frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nghttp2_frame_priority_init(&frame, 1000000007, 1 << 30);
|
||||
framelen = nghttp2_frame_pack_priority(&buf, &buflen, &frame);
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen));
|
||||
framelen = nghttp2_frame_pack_priority(&buf, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
check_frame_header(4, NGHTTP2_PRIORITY, NGHTTP2_FLAG_NONE, 1000000007,
|
||||
&oframe.hd);
|
||||
CU_ASSERT(1 << 30 == oframe.pri);
|
||||
free(buf);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_priority_free(&oframe);
|
||||
nghttp2_frame_priority_free(&frame);
|
||||
}
|
||||
|
@ -208,16 +213,21 @@ void test_nghttp2_frame_pack_priority(void)
|
|||
void test_nghttp2_frame_pack_rst_stream(void)
|
||||
{
|
||||
nghttp2_rst_stream frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nghttp2_frame_rst_stream_init(&frame, 1000000007, NGHTTP2_PROTOCOL_ERROR);
|
||||
framelen = nghttp2_frame_pack_rst_stream(&buf, &buflen, &frame);
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen));
|
||||
framelen = nghttp2_frame_pack_rst_stream(&buf, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
check_frame_header(4, NGHTTP2_RST_STREAM, NGHTTP2_FLAG_NONE, 1000000007,
|
||||
&oframe.hd);
|
||||
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == oframe.error_code);
|
||||
free(buf);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_rst_stream_free(&oframe);
|
||||
nghttp2_frame_rst_stream_free(&frame);
|
||||
}
|
||||
|
@ -225,24 +235,33 @@ void test_nghttp2_frame_pack_rst_stream(void)
|
|||
void test_nghttp2_frame_pack_settings()
|
||||
{
|
||||
nghttp2_settings frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
int i;
|
||||
nghttp2_settings_entry iv[3];
|
||||
iv[0].settings_id = NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS;
|
||||
iv[0].value = 256;
|
||||
iv[1].settings_id = NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE;
|
||||
iv[1].value = 16384;
|
||||
iv[2].settings_id = NGHTTP2_SETTINGS_HEADER_TABLE_SIZE;
|
||||
iv[2].value = 4096;
|
||||
nghttp2_settings_entry iv[] =
|
||||
{
|
||||
{
|
||||
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 256
|
||||
},
|
||||
{
|
||||
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, 16384
|
||||
},
|
||||
{
|
||||
NGHTTP2_SETTINGS_HEADER_TABLE_SIZE, 4096
|
||||
}
|
||||
};
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nghttp2_frame_settings_init(&frame, NGHTTP2_FLAG_NONE,
|
||||
nghttp2_frame_iv_copy(iv, 3), 3);
|
||||
framelen = nghttp2_frame_pack_settings(&buf, &buflen, &frame);
|
||||
framelen = nghttp2_frame_pack_settings(&buf, &frame);
|
||||
|
||||
CU_ASSERT(NGHTTP2_FRAME_HEAD_LENGTH +
|
||||
3 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH == framelen);
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen));
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
check_frame_header(3 * NGHTTP2_FRAME_SETTINGS_ENTRY_LENGTH,
|
||||
NGHTTP2_SETTINGS, NGHTTP2_FLAG_NONE, 0, &oframe.hd);
|
||||
CU_ASSERT(3 == oframe.niv);
|
||||
|
@ -251,7 +270,7 @@ void test_nghttp2_frame_pack_settings()
|
|||
CU_ASSERT(iv[i].value == oframe.iv[i].value);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_settings_free(&frame);
|
||||
nghttp2_frame_settings_free(&oframe);
|
||||
}
|
||||
|
@ -261,14 +280,14 @@ void test_nghttp2_frame_pack_push_promise()
|
|||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_push_promise frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t bufoff;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
nva_out out;
|
||||
ssize_t nv_offset;
|
||||
ssize_t hdblocklen;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_deflate_init(&deflater);
|
||||
|
@ -278,26 +297,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, &buflen, &bufoff, &frame,
|
||||
&deflater);
|
||||
framelen = nghttp2_frame_pack_push_promise(&buf, &frame, &deflater);
|
||||
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe,
|
||||
buf + bufoff, framelen - bufoff));
|
||||
check_frame_header(framelen - bufoff - NGHTTP2_FRAME_HEAD_LENGTH,
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
|
||||
check_frame_header(nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN,
|
||||
NGHTTP2_PUSH_PROMISE,
|
||||
NGHTTP2_FLAG_END_HEADERS, 1000000007, &oframe.hd);
|
||||
CU_ASSERT((1U << 31) - 1 == oframe.promised_stream_id);
|
||||
|
||||
nv_offset = bufoff + NGHTTP2_FRAME_HEAD_LENGTH + 4;
|
||||
CU_ASSERT(framelen - nv_offset ==
|
||||
inflate_hd(&inflater, &out, buf + nv_offset, framelen - nv_offset));
|
||||
hdblocklen = nghttp2_buf_len(&buf) - NGHTTP2_FRAME_HDLEN - 4;
|
||||
CU_ASSERT(hdblocklen ==
|
||||
inflate_hd(&inflater, &out,
|
||||
buf.pos + NGHTTP2_FRAME_HDLEN + 4, hdblocklen));
|
||||
|
||||
CU_ASSERT(7 == out.nvlen);
|
||||
CU_ASSERT(nvnameeq("method", &out.nva[0]));
|
||||
CU_ASSERT(nvvalueeq("GET", &out.nva[0]));
|
||||
|
||||
nva_out_reset(&out);
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_push_promise_free(&oframe);
|
||||
nghttp2_frame_push_promise_free(&frame);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
|
@ -307,17 +327,22 @@ void test_nghttp2_frame_pack_push_promise()
|
|||
void test_nghttp2_frame_pack_ping(void)
|
||||
{
|
||||
nghttp2_ping frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
const uint8_t opaque_data[] = "01234567";
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nghttp2_frame_ping_init(&frame, NGHTTP2_FLAG_ACK, opaque_data);
|
||||
framelen = nghttp2_frame_pack_ping(&buf, &buflen, &frame);
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen));
|
||||
framelen = nghttp2_frame_pack_ping(&buf, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
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);
|
||||
free(buf);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_ping_free(&oframe);
|
||||
nghttp2_frame_ping_free(&frame);
|
||||
}
|
||||
|
@ -325,17 +350,20 @@ void test_nghttp2_frame_pack_ping(void)
|
|||
void test_nghttp2_frame_pack_goaway()
|
||||
{
|
||||
nghttp2_goaway frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
size_t opaque_data_len = 16;
|
||||
uint8_t *opaque_data = malloc(opaque_data_len);
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
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, &buflen, &frame);
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen));
|
||||
framelen = nghttp2_frame_pack_goaway(&buf, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
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);
|
||||
|
@ -344,7 +372,8 @@ void test_nghttp2_frame_pack_goaway()
|
|||
CU_ASSERT(NULL == oframe.opaque_data);
|
||||
/* CU_ASSERT(opaque_data_len == oframe.opaque_data_len); */
|
||||
/* CU_ASSERT(memcmp(opaque_data, oframe.opaque_data, opaque_data_len) == 0); */
|
||||
free(buf);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_goaway_free(&oframe);
|
||||
nghttp2_frame_goaway_free(&frame);
|
||||
}
|
||||
|
@ -352,19 +381,22 @@ void test_nghttp2_frame_pack_goaway()
|
|||
void test_nghttp2_frame_pack_window_update(void)
|
||||
{
|
||||
nghttp2_window_update frame, oframe;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nghttp2_frame_window_update_init(&frame, NGHTTP2_FLAG_NONE,
|
||||
1000000007, 4096);
|
||||
framelen = nghttp2_frame_pack_window_update(&buf, &buflen,
|
||||
&frame);
|
||||
CU_ASSERT(0 == unpack_frame((nghttp2_frame*)&oframe, buf, framelen));
|
||||
framelen = nghttp2_frame_pack_window_update(&buf, &frame);
|
||||
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(0 == unpack_framebuf((nghttp2_frame*)&oframe, &buf));
|
||||
check_frame_header(4, NGHTTP2_WINDOW_UPDATE, NGHTTP2_FLAG_NONE,
|
||||
1000000007, &oframe.hd);
|
||||
CU_ASSERT(4096 == oframe.window_size_increment);
|
||||
free(buf);
|
||||
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_window_update_free(&oframe);
|
||||
nghttp2_frame_window_update_free(&frame);
|
||||
}
|
||||
|
|
|
@ -52,77 +52,83 @@ void test_nghttp2_hd_deflate(void)
|
|||
MAKE_NV("cookie", "k1=v1")};
|
||||
nghttp2_nv nva5[] = {MAKE_NV(":path", "/style.css"),
|
||||
MAKE_NV("x-nghttp2", "")};
|
||||
size_t nv_offset = 12;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
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, &buflen, nv_offset, nva1,
|
||||
sizeof(nva1)/sizeof(nghttp2_nv));
|
||||
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva1, ARRLEN(nva1));
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen ==
|
||||
inflate_hd(&inflater, &out, buf + nv_offset, blocklen));
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(3 == out.nvlen);
|
||||
assert_nv_equal(nva1, out.nva, 3);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* Second headers */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, nv_offset, nva2,
|
||||
sizeof(nva2)/sizeof(nghttp2_nv));
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva2, ARRLEN(nva2));
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen ==
|
||||
inflate_hd(&inflater, &out, buf + nv_offset, blocklen));
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(2 == out.nvlen);
|
||||
assert_nv_equal(nva2, out.nva, 2);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* Third headers, including same header field name, but value is not
|
||||
the same. */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, nv_offset, nva3,
|
||||
sizeof(nva3)/sizeof(nghttp2_nv));
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva3, ARRLEN(nva3));
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen ==
|
||||
inflate_hd(&inflater, &out, buf + nv_offset, blocklen));
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(3 == out.nvlen);
|
||||
assert_nv_equal(nva3, out.nva, 3);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* Fourth headers, including duplicate header fields. */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, nv_offset, nva4,
|
||||
sizeof(nva4)/sizeof(nghttp2_nv));
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva4, ARRLEN(nva4));
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen ==
|
||||
inflate_hd(&inflater, &out, buf + nv_offset, blocklen));
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(3 == out.nvlen);
|
||||
assert_nv_equal(nva4, out.nva, 3);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* Fifth headers includes empty value */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, nv_offset, nva5,
|
||||
sizeof(nva5)/sizeof(nghttp2_nv));
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva5, ARRLEN(nva5));
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen ==
|
||||
inflate_hd(&inflater, &out, buf + nv_offset, blocklen));
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(2 == out.nvlen);
|
||||
assert_nv_equal(nva5, out.nva, 2);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* Cleanup */
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -136,41 +142,46 @@ void test_nghttp2_hd_deflate_same_indexed_repr(void)
|
|||
nghttp2_nv nva2[] = {MAKE_NV("cookie", "alpha"),
|
||||
MAKE_NV("cookie", "alpha"),
|
||||
MAKE_NV("cookie", "alpha")};
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater));
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater));
|
||||
|
||||
/* 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, &buflen, 0, nva1,
|
||||
sizeof(nva1)/sizeof(nghttp2_nv));
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva1, ARRLEN(nva1));
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf, blocklen));
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(2 == out.nvlen);
|
||||
assert_nv_equal(nva1, out.nva, 2);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* 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, &buflen, 0, nva2,
|
||||
sizeof(nva2)/sizeof(nghttp2_nv));
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva2, ARRLEN(nva2));
|
||||
|
||||
CU_ASSERT(blocklen == 6);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf, blocklen));
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(3 == out.nvlen);
|
||||
assert_nv_equal(nva2, out.nva, 3);
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* Cleanup */
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -181,8 +192,7 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
|
|||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_nv nva[] = {MAKE_NV("h1", ""),
|
||||
MAKE_NV("h2", "")};
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
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
|
||||
|
@ -191,6 +201,8 @@ void test_nghttp2_hd_deflate_common_header_eviction(void)
|
|||
nva_out out;
|
||||
size_t i;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
memset(value, '0', sizeof(value));
|
||||
for(i = 0; i < 2; ++i) {
|
||||
|
@ -203,35 +215,42 @@ 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, &buflen, 0, nva, 1);
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 1);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf, blocklen));
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
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);
|
||||
|
||||
/* Encode with second header */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, 0, nva, 2);
|
||||
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
|
||||
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, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
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);
|
||||
|
||||
CU_ASSERT(1 == deflater.ctx.hd_table.len);
|
||||
CU_ASSERT(1 == inflater.ctx.hd_table.len);
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -240,8 +259,7 @@ void test_nghttp2_hd_deflate_clear_refset(void)
|
|||
{
|
||||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_hd_inflater inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv[] = {
|
||||
MAKE_NV(":path", "/"),
|
||||
|
@ -250,6 +268,8 @@ void test_nghttp2_hd_deflate_clear_refset(void)
|
|||
size_t i;
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_deflate_init2(&deflater,
|
||||
NGHTTP2_HD_DEFAULT_MAX_DEFLATE_BUFFER_SIZE);
|
||||
|
@ -257,18 +277,18 @@ 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, &buflen, 0,
|
||||
nv, ARRLEN(nv));
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, nv, ARRLEN(nv));
|
||||
CU_ASSERT(blocklen > 1);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf, blocklen));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(ARRLEN(nv) == out.nvlen);
|
||||
assert_nv_equal(nv, out.nva, ARRLEN(nv));
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -276,9 +296,8 @@ void test_nghttp2_hd_deflate_clear_refset(void)
|
|||
void test_nghttp2_hd_inflate_indname_noinc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv[] = {
|
||||
/* Huffman */
|
||||
MAKE_NV("user-agent", "nghttp2"),
|
||||
|
@ -288,42 +307,53 @@ void test_nghttp2_hd_inflate_indname_noinc(void)
|
|||
size_t i;
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
for(i = 0; i < ARRLEN(nv); ++i) {
|
||||
offset = 0;
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 56,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 56,
|
||||
nv[i].value, nv[i].valuelen,
|
||||
0));
|
||||
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_inc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2");
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 56,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 56,
|
||||
nv.value, nv.valuelen, 1));
|
||||
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv, out.nva, 1);
|
||||
|
@ -333,33 +363,38 @@ void test_nghttp2_hd_inflate_indname_inc(void)
|
|||
inflater.ctx.hd_table.len-1)->nv, 1);
|
||||
|
||||
nva_out_reset(&out);
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_inc_eviction(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
uint8_t value[1024];
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
memset(value, '0', sizeof(value));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 13,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 13,
|
||||
value, sizeof(value), 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 14,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 14,
|
||||
value, sizeof(value), 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 15,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 15,
|
||||
value, sizeof(value), 1));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset, 16,
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, 16,
|
||||
value, sizeof(value), 1));
|
||||
|
||||
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(4 == out.nvlen);
|
||||
CU_ASSERT(14 == out.nva[0].namelen);
|
||||
|
@ -367,20 +402,20 @@ 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);
|
||||
|
||||
CU_ASSERT(3 == inflater.ctx.hd_table.len);
|
||||
CU_ASSERT(GET_TABLE_ENT(&inflater.ctx, 0)->flags & NGHTTP2_HD_FLAG_REFSET);
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_newname_noinc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv[] = {
|
||||
/* Expecting huffman for both */
|
||||
MAKE_NV("my-long-content-length", "nghttp2"),
|
||||
|
@ -394,40 +429,49 @@ void test_nghttp2_hd_inflate_newname_noinc(void)
|
|||
size_t i;
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
for(i = 0; i < ARRLEN(nv); ++i) {
|
||||
offset = 0;
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
|
||||
&nv[i], 0));
|
||||
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &nv[i], 0));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_newname_inc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2");
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
|
||||
&nv, 1));
|
||||
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &nv, 1));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv, out.nva, 1);
|
||||
|
@ -437,20 +481,21 @@ void test_nghttp2_hd_inflate_newname_inc(void)
|
|||
inflater.ctx.hd_table.len-1)->nv, 1);
|
||||
|
||||
nva_out_reset(&out);
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_clearall_inc(void)
|
||||
{
|
||||
nghttp2_hd_inflater inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nghttp2_nv nv;
|
||||
uint8_t value[4060];
|
||||
nva_out out;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
/* Total 4097 bytes space required to hold this entry */
|
||||
nv.name = (uint8_t*)"alpha";
|
||||
|
@ -461,18 +506,22 @@ void test_nghttp2_hd_inflate_clearall_inc(void)
|
|||
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
|
||||
&nv, 1));
|
||||
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &nv, 1));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
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((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(1 == out.nvlen);
|
||||
assert_nv_equal(&nv, out.nva, 1);
|
||||
|
@ -484,18 +533,21 @@ void test_nghttp2_hd_inflate_clearall_inc(void)
|
|||
header table */
|
||||
nv.valuelen = sizeof(value) - 1;
|
||||
|
||||
offset = 0;
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &buflen, &offset,
|
||||
&nv, 1));
|
||||
CU_ASSERT((ssize_t)offset == inflate_hd(&inflater, &out, buf, offset));
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&buf, &nv, 1));
|
||||
|
||||
blocklen = nghttp2_buf_len(&buf);
|
||||
|
||||
CU_ASSERT(blocklen > 0);
|
||||
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, buf.pos, blocklen));
|
||||
|
||||
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);
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
|
@ -531,11 +583,11 @@ void test_nghttp2_hd_change_table_size(void)
|
|||
nghttp2_hd_inflater inflater;
|
||||
nghttp2_nv nva[] = { MAKE_NV(":method", "GET"),
|
||||
MAKE_NV(":path", "/") };
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t rv;
|
||||
nva_out out;
|
||||
size_t offset;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nva_out_init(&out);
|
||||
|
||||
|
@ -554,17 +606,19 @@ 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, &buflen, 0, nva, 2);
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv > 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
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, rv));
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
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);
|
||||
|
||||
/* inflater changes header table size to 1024 */
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 1024));
|
||||
|
@ -577,17 +631,19 @@ 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, &buflen, 0, nva, 2);
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv >= 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
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, rv));
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
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);
|
||||
|
||||
/* inflater changes header table size to 0 */
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 0));
|
||||
|
@ -602,25 +658,27 @@ 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, &buflen, 0, nva, 2);
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv >= 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
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, rv));
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
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);
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
|
||||
/* Check table buffer is expanded */
|
||||
buf = NULL;
|
||||
buflen = 0;
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
nghttp2_hd_deflate_init2(&deflater, 8192);
|
||||
nghttp2_hd_inflate_init(&inflater);
|
||||
|
||||
|
@ -635,17 +693,19 @@ 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, &buflen, 0, nva, 2);
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv > 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
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, rv));
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
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);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_change_table_size(&inflater, 16383));
|
||||
CU_ASSERT(0 == nghttp2_hd_deflate_change_table_size(&deflater, 16383));
|
||||
|
@ -657,26 +717,29 @@ 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, &buflen, 0, nva, 2);
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv >= 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
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, rv));
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
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);
|
||||
|
||||
/* Lastly, check the error condition */
|
||||
offset = 0;
|
||||
rv = nghttp2_hd_emit_table_size(&buf, &buflen, &offset, 25600);
|
||||
|
||||
rv = nghttp2_hd_emit_table_size(&buf, 25600);
|
||||
CU_ASSERT(rv == 0);
|
||||
CU_ASSERT(NGHTTP2_ERR_HEADER_COMP ==
|
||||
inflate_hd(&inflater, &out, buf, offset));
|
||||
inflate_hd(&inflater, &out, buf.pos, nghttp2_buf_len(&buf)));
|
||||
|
||||
nva_out_reset(&out);
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
|
@ -690,19 +753,21 @@ 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, &buflen, 0, nva, 2);
|
||||
rv = nghttp2_hd_deflate_hd(&deflater, &buf, nva, 2);
|
||||
CU_ASSERT(rv > 0);
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
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, rv));
|
||||
CU_ASSERT(rv == inflate_hd(&inflater, &out, buf.pos, rv));
|
||||
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);
|
||||
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
@ -711,22 +776,25 @@ static void check_deflate_inflate(nghttp2_hd_deflater *deflater,
|
|||
nghttp2_hd_inflater *inflater,
|
||||
nghttp2_nv *nva, size_t nvlen)
|
||||
{
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_buf buf;
|
||||
ssize_t blocklen;
|
||||
nva_out out;
|
||||
|
||||
nva_out_init(&out);
|
||||
blocklen = nghttp2_hd_deflate_hd(deflater, &buf, &buflen, 0, nva, nvlen);
|
||||
assert(blocklen >= 0);
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
CU_ASSERT(blocklen == inflate_hd(inflater, &out, buf, blocklen));
|
||||
nva_out_init(&out);
|
||||
blocklen = nghttp2_hd_deflate_hd(deflater, &buf, nva, nvlen);
|
||||
|
||||
CU_ASSERT(blocklen >= 0);
|
||||
CU_ASSERT(blocklen == nghttp2_buf_len(&buf));
|
||||
|
||||
CU_ASSERT(blocklen == inflate_hd(inflater, &out, buf.pos, blocklen));
|
||||
|
||||
CU_ASSERT(nvlen == out.nvlen);
|
||||
assert_nv_equal(nva, out.nva, nvlen);
|
||||
|
||||
nva_out_reset(&out);
|
||||
free(buf);
|
||||
nghttp2_buf_free(&buf);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_deflate_inflate(void)
|
||||
|
|
|
@ -346,37 +346,39 @@ void test_nghttp2_session_recv(void)
|
|||
const nghttp2_nv nv[] = {
|
||||
MAKE_NV("url", "/")
|
||||
};
|
||||
uint8_t *framedata = NULL;
|
||||
size_t framedatalen = 0;
|
||||
size_t bufoff;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_frame frame;
|
||||
size_t i;
|
||||
ssize_t i;
|
||||
nghttp2_outbound_item *item;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
nghttp2_hd_deflater deflater;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
callbacks.recv_callback = scripted_recv_callback;
|
||||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||
|
||||
user_data.df = &df;
|
||||
|
||||
nghttp2_session_server_new(&session, &callbacks, &user_data);
|
||||
nghttp2_hd_deflate_init(&deflater);
|
||||
|
||||
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(&framedata, &framedatalen, &bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
|
||||
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
||||
/* Send 1 byte per each read */
|
||||
for(i = 0; i < framelen - bufoff; ++i) {
|
||||
for(i = 0; i < nghttp2_buf_len(&buf); ++i) {
|
||||
df.feedseq[i] = 1;
|
||||
}
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
|
@ -385,16 +387,16 @@ void test_nghttp2_session_recv(void)
|
|||
}
|
||||
CU_ASSERT(1 == user_data.frame_recv_cb_called);
|
||||
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* 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(&framedata, &framedatalen, &bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(1 == user_data.frame_recv_cb_called);
|
||||
|
@ -405,15 +407,21 @@ void test_nghttp2_session_recv(void)
|
|||
/* Some tests for frame too large */
|
||||
nghttp2_session_server_new(&session, &callbacks, &user_data);
|
||||
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
/* Receive PING with too large payload */
|
||||
nghttp2_frame_ping_init(&frame.ping, NGHTTP2_FLAG_NONE, NULL);
|
||||
nghttp2_reserve_buffer(&framedata, &framedatalen, 77);
|
||||
framelen = nghttp2_frame_pack_ping(&framedata, &framedatalen, &frame.ping);
|
||||
|
||||
framelen = nghttp2_frame_pack_ping(&buf, &frame.ping);
|
||||
|
||||
/* 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_frame_ping_free(&frame.ping);
|
||||
|
||||
nghttp2_put_uint16be(&framedata[0],
|
||||
framedatalen - NGHTTP2_FRAME_HEAD_LENGTH);
|
||||
scripted_data_feed_init(&df, framedata, framedatalen);
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(0 == user_data.frame_recv_cb_called);
|
||||
|
@ -422,7 +430,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));
|
||||
|
||||
free(framedata);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
|
@ -432,13 +440,13 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
|
|||
nghttp2_session_callbacks callbacks;
|
||||
scripted_data_feed df;
|
||||
my_user_data user_data;
|
||||
uint8_t *framedata = NULL;
|
||||
size_t framedatalen = 0;
|
||||
size_t bufoff;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_hd_deflater deflater;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.recv_callback = scripted_recv_callback;
|
||||
callbacks.on_invalid_frame_recv_callback = on_invalid_frame_recv_callback;
|
||||
|
@ -450,17 +458,17 @@ 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(&framedata, &framedatalen, &bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
|
||||
|
||||
free(framedata);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -474,15 +482,15 @@ void test_nghttp2_session_recv_invalid_frame(void)
|
|||
const nghttp2_nv nv[] = {
|
||||
MAKE_NV("url", "/")
|
||||
};
|
||||
uint8_t *framedata = NULL;
|
||||
size_t framedatalen = 0;
|
||||
size_t bufoff;
|
||||
nghttp2_buf buf;
|
||||
ssize_t framelen;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
nghttp2_hd_deflater deflater;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.recv_callback = scripted_recv_callback;
|
||||
callbacks.send_callback = null_send_callback;
|
||||
|
@ -495,11 +503,11 @@ 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(&framedata, &framedatalen, &bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
framelen = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
scripted_data_feed_init(&df, framedata + bufoff, framelen - bufoff);
|
||||
CU_ASSERT(framelen == nghttp2_buf_len(&buf));
|
||||
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
|
@ -507,13 +515,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, framedata + bufoff, framelen - bufoff);
|
||||
scripted_data_feed_init(&df, buf.pos, nghttp2_buf_len(&buf));
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_recv(session));
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
CU_ASSERT(0 == user_data.frame_send_cb_called);
|
||||
|
||||
free(framedata);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
|
@ -672,11 +680,7 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
nghttp2_nv *nva;
|
||||
size_t nvlen;
|
||||
nghttp2_frame frame;
|
||||
uint8_t *framedata = NULL;
|
||||
size_t framedatacap = 0;
|
||||
size_t framedatalen;
|
||||
size_t bufoff;
|
||||
size_t framedataoff;
|
||||
nghttp2_buf buf;
|
||||
ssize_t rv;
|
||||
my_user_data ud;
|
||||
nghttp2_hd_deflater deflater;
|
||||
|
@ -684,6 +688,8 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
size_t datalen;
|
||||
nghttp2_frame_hd cont_hd;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.on_header_callback = on_header_callback;
|
||||
callbacks.on_begin_headers_callback = on_begin_headers_callback;
|
||||
|
@ -696,15 +702,16 @@ 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);
|
||||
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap,
|
||||
&bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
memcpy(data, framedata + bufoff, 9);
|
||||
/* HEADERS's payload is 1 byte */
|
||||
memcpy(data, buf.pos, 9);
|
||||
datalen = 9;
|
||||
framedataoff = bufoff + NGHTTP2_FRAME_HEAD_LENGTH + 1;
|
||||
buf.pos += 9;
|
||||
|
||||
nghttp2_put_uint16be(data, 1);
|
||||
|
||||
|
@ -715,25 +722,25 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
cont_hd.stream_id = 1;
|
||||
|
||||
nghttp2_frame_pack_frame_hd(data + datalen, &cont_hd);
|
||||
datalen += NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
datalen += NGHTTP2_FRAME_HDLEN;
|
||||
|
||||
memcpy(data + datalen, framedata + framedataoff, cont_hd.length);
|
||||
memcpy(data + datalen, buf.pos, cont_hd.length);
|
||||
datalen += cont_hd.length;
|
||||
framedataoff += cont_hd.length;
|
||||
buf.pos += cont_hd.length;
|
||||
|
||||
/* Second CONTINUATION, rest of the bytes */
|
||||
cont_hd.length = framedatalen - framedataoff;
|
||||
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_HEAD_LENGTH;
|
||||
|
||||
memcpy(data + datalen, framedata + framedataoff, cont_hd.length);
|
||||
memcpy(data + datalen, buf.pos, cont_hd.length);
|
||||
datalen += cont_hd.length;
|
||||
framedataoff += cont_hd.length;
|
||||
buf.pos += cont_hd.length;
|
||||
|
||||
assert(framedataoff == framedatalen);
|
||||
CU_ASSERT(0 == nghttp2_buf_len(&buf));
|
||||
|
||||
ud.header_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, data, datalen);
|
||||
|
@ -752,19 +759,25 @@ 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);
|
||||
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap, &bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
nghttp2_buf_reset(&buf);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
memcpy(data, framedata + bufoff, framedatalen - bufoff);
|
||||
datalen = framedatalen - bufoff;
|
||||
memcpy(data, buf.pos, nghttp2_buf_len(&buf));
|
||||
datalen = nghttp2_buf_len(&buf);
|
||||
|
||||
/* Followed by PRIORITY */
|
||||
nghttp2_frame_priority_init(&frame.priority, 1, 0);
|
||||
framedatalen = nghttp2_frame_pack_priority(&framedata, &framedatacap,
|
||||
&frame.priority);
|
||||
memcpy(data + datalen, framedata, framedatalen);
|
||||
datalen += framedatalen;
|
||||
nghttp2_buf_reset(&buf);
|
||||
|
||||
rv = nghttp2_frame_pack_priority(&buf, &frame.priority);
|
||||
|
||||
CU_ASSERT(rv == 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);
|
||||
|
@ -774,7 +787,7 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
CU_ASSERT(NGHTTP2_GOAWAY ==
|
||||
OB_CTRL_TYPE(nghttp2_session_get_next_ob_item(session)));
|
||||
|
||||
free(framedata);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -790,14 +803,13 @@ void test_nghttp2_session_recv_premature_headers(void)
|
|||
nghttp2_nv *nva;
|
||||
size_t nvlen;
|
||||
nghttp2_frame frame;
|
||||
uint8_t *framedata = NULL;
|
||||
size_t framedatacap = 0;
|
||||
size_t framedatalen;
|
||||
nghttp2_buf buf;
|
||||
ssize_t rv;
|
||||
my_user_data ud;
|
||||
nghttp2_hd_deflater deflater;
|
||||
nghttp2_outbound_item *item;
|
||||
size_t bufoff = 0;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
|
||||
|
@ -808,24 +820,24 @@ 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);
|
||||
framedatalen = nghttp2_frame_pack_headers(&framedata, &framedatacap,
|
||||
&bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
/* Intentionally feed payload cutting last 1 byte off */
|
||||
nghttp2_put_uint16be(framedata + bufoff, frame.hd.length - 1);
|
||||
rv = nghttp2_session_mem_recv(session, framedata + bufoff,
|
||||
framedatalen - bufoff - 1);
|
||||
CU_ASSERT((ssize_t)(framedatalen - bufoff - 1) == rv);
|
||||
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);
|
||||
|
||||
free(framedata);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -843,14 +855,11 @@ void test_nghttp2_session_continue(void)
|
|||
MAKE_NV("user-agent", "nghttp2/1.0.0"),
|
||||
MAKE_NV("alpha", "bravo")
|
||||
};
|
||||
uint8_t *framedata = NULL;
|
||||
size_t framedatalen = 0;
|
||||
ssize_t framelen1, framelen2;
|
||||
nghttp2_buf buf;
|
||||
size_t framelen1, framelen2;
|
||||
ssize_t rv;
|
||||
uint8_t buffer[4096];
|
||||
uint8_t *bufp = buffer;
|
||||
size_t buflen;
|
||||
size_t bufoff;
|
||||
nghttp2_buf databuf;
|
||||
nghttp2_frame frame;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
|
@ -858,6 +867,9 @@ void test_nghttp2_session_continue(void)
|
|||
nghttp2_frame_hd data_hd;
|
||||
nghttp2_hd_deflater deflater;
|
||||
|
||||
nghttp2_buf_init(&buf);
|
||||
nghttp2_buf_wrap_init(&databuf, buffer, sizeof(buffer));
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||
|
@ -873,38 +885,40 @@ 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);
|
||||
framelen1 = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
memcpy(buffer, framedata + bufoff, framelen1 - bufoff);
|
||||
framelen1 -= bufoff;
|
||||
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);
|
||||
framelen2 = nghttp2_frame_pack_headers(&framedata, &framedatalen, &bufoff,
|
||||
&frame.headers,
|
||||
&deflater);
|
||||
nghttp2_buf_reset(&buf);
|
||||
rv = nghttp2_frame_pack_headers(&buf, &frame.headers, &deflater);
|
||||
|
||||
CU_ASSERT(rv == nghttp2_buf_len(&buf));
|
||||
|
||||
nghttp2_frame_headers_free(&frame.headers);
|
||||
|
||||
memcpy(buffer + framelen1, framedata + bufoff, framelen2 - bufoff);
|
||||
framelen2 -= bufoff;
|
||||
buflen = framelen1 + framelen2;
|
||||
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;
|
||||
user_data.header_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, bufp, buflen);
|
||||
rv = nghttp2_session_mem_recv(session,
|
||||
databuf.pos, nghttp2_buf_len(&databuf));
|
||||
|
||||
bufp += rv;
|
||||
buflen -= rv;
|
||||
CU_ASSERT(rv >= 0);
|
||||
databuf.pos += rv;
|
||||
|
||||
recv_frame = user_data.frame;
|
||||
CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
|
||||
CU_ASSERT((size_t)framelen1 - NGHTTP2_FRAME_HEAD_LENGTH ==
|
||||
recv_frame->hd.length);
|
||||
CU_ASSERT(framelen1 - NGHTTP2_FRAME_HEAD_LENGTH == recv_frame->hd.length);
|
||||
|
||||
CU_ASSERT(1 == user_data.begin_headers_cb_called);
|
||||
CU_ASSERT(1 == user_data.header_cb_called);
|
||||
|
@ -914,10 +928,11 @@ void test_nghttp2_session_continue(void)
|
|||
/* get 2nd header field */
|
||||
user_data.begin_headers_cb_called = 0;
|
||||
user_data.header_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, bufp, buflen);
|
||||
rv = nghttp2_session_mem_recv(session,
|
||||
databuf.pos, nghttp2_buf_len(&databuf));
|
||||
|
||||
bufp += rv;
|
||||
buflen -= rv;
|
||||
CU_ASSERT(rv >= 0);
|
||||
databuf.pos += rv;
|
||||
|
||||
CU_ASSERT(0 == user_data.begin_headers_cb_called);
|
||||
CU_ASSERT(1 == user_data.header_cb_called);
|
||||
|
@ -927,15 +942,15 @@ void test_nghttp2_session_continue(void)
|
|||
/* will call end_headers_callback and receive 2nd HEADERS and pause */
|
||||
user_data.begin_headers_cb_called = 0;
|
||||
user_data.header_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, bufp, buflen);
|
||||
rv = nghttp2_session_mem_recv(session,
|
||||
databuf.pos, nghttp2_buf_len(&databuf));
|
||||
|
||||
bufp += rv;
|
||||
buflen -= rv;
|
||||
CU_ASSERT(rv >= 0);
|
||||
databuf.pos += rv;
|
||||
|
||||
recv_frame = user_data.frame;
|
||||
CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
|
||||
CU_ASSERT((size_t)framelen2 - NGHTTP2_FRAME_HEAD_LENGTH ==
|
||||
recv_frame->hd.length);
|
||||
CU_ASSERT(framelen2 - NGHTTP2_FRAME_HEAD_LENGTH == recv_frame->hd.length);
|
||||
|
||||
CU_ASSERT(1 == user_data.begin_headers_cb_called);
|
||||
CU_ASSERT(1 == user_data.header_cb_called);
|
||||
|
@ -945,10 +960,11 @@ void test_nghttp2_session_continue(void)
|
|||
/* get 2nd header field */
|
||||
user_data.begin_headers_cb_called = 0;
|
||||
user_data.header_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, bufp, buflen);
|
||||
rv = nghttp2_session_mem_recv(session,
|
||||
databuf.pos, nghttp2_buf_len(&databuf));
|
||||
|
||||
bufp += rv;
|
||||
buflen -= rv;
|
||||
CU_ASSERT(rv >= 0);
|
||||
databuf.pos += rv;
|
||||
|
||||
CU_ASSERT(0 == user_data.begin_headers_cb_called);
|
||||
CU_ASSERT(1 == user_data.header_cb_called);
|
||||
|
@ -959,10 +975,11 @@ void test_nghttp2_session_continue(void)
|
|||
user_data.begin_headers_cb_called = 0;
|
||||
user_data.header_cb_called = 0;
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, bufp, buflen);
|
||||
rv = nghttp2_session_mem_recv(session,
|
||||
databuf.pos, nghttp2_buf_len(&databuf));
|
||||
|
||||
bufp += rv;
|
||||
buflen -= rv;
|
||||
CU_ASSERT(rv >= 0);
|
||||
databuf.pos += rv;
|
||||
|
||||
CU_ASSERT(0 == user_data.begin_headers_cb_called);
|
||||
CU_ASSERT(0 == user_data.header_cb_called);
|
||||
|
@ -973,13 +990,18 @@ void test_nghttp2_session_continue(void)
|
|||
data_hd.type = NGHTTP2_DATA;
|
||||
data_hd.flags = NGHTTP2_FLAG_NONE;
|
||||
data_hd.stream_id = 1;
|
||||
nghttp2_frame_pack_frame_hd(buffer, &data_hd);
|
||||
bufp = buffer;
|
||||
buflen = sizeof(buffer);
|
||||
|
||||
nghttp2_buf_reset(&databuf);
|
||||
nghttp2_frame_pack_frame_hd(databuf.pos, &data_hd);
|
||||
|
||||
/* Intentionally specify larger buffer size to see pause is kicked
|
||||
in. */
|
||||
databuf.last = databuf.end;
|
||||
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, buffer, sizeof(buffer));
|
||||
rv = nghttp2_session_mem_recv(session,
|
||||
databuf.pos, nghttp2_buf_len(&databuf));
|
||||
|
||||
CU_ASSERT(16 + NGHTTP2_FRAME_HEAD_LENGTH == rv);
|
||||
CU_ASSERT(0 == user_data.frame_recv_cb_called);
|
||||
|
||||
|
@ -987,7 +1009,8 @@ void test_nghttp2_session_continue(void)
|
|||
pause again in on_data_chunk_recv_callback since we pass same
|
||||
DATA frame. */
|
||||
user_data.frame_recv_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, buffer, sizeof(buffer));
|
||||
rv = nghttp2_session_mem_recv(session,
|
||||
databuf.pos, nghttp2_buf_len(&databuf));
|
||||
CU_ASSERT(16 + NGHTTP2_FRAME_HEAD_LENGTH == rv);
|
||||
CU_ASSERT(1 == user_data.frame_recv_cb_called);
|
||||
|
||||
|
@ -997,7 +1020,7 @@ void test_nghttp2_session_continue(void)
|
|||
CU_ASSERT(0 == rv);
|
||||
CU_ASSERT(1 == user_data.frame_recv_cb_called);
|
||||
|
||||
free(framedata);
|
||||
nghttp2_buf_free(&buf);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
@ -1022,13 +1045,16 @@ void test_nghttp2_session_add_frame(void)
|
|||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = accumulator_send_callback;
|
||||
|
||||
memset(aux_data, 0, sizeof(nghttp2_headers_aux_data));
|
||||
acc.length = 0;
|
||||
user_data.acc = &acc;
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &user_data));
|
||||
|
||||
frame = malloc(sizeof(nghttp2_frame));
|
||||
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
|
||||
|
||||
nghttp2_frame_headers_init(&frame->headers,
|
||||
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
|
||||
-1, NGHTTP2_PRI_DEFAULT, nva, nvlen);
|
||||
|
@ -2239,6 +2265,8 @@ void test_nghttp2_submit_data(void)
|
|||
my_user_data ud;
|
||||
nghttp2_private_data *data_frame;
|
||||
nghttp2_frame_hd hd;
|
||||
nghttp2_active_outbound_item *aob;
|
||||
nghttp2_buf *framebuf;
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = block_count_send_callback;
|
||||
|
@ -2246,6 +2274,8 @@ void test_nghttp2_submit_data(void)
|
|||
data_prd.read_callback = fixed_length_data_source_read_callback;
|
||||
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;
|
||||
|
||||
nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
|
||||
NGHTTP2_PRI_DEFAULT, NGHTTP2_STREAM_OPENING,
|
||||
|
@ -2253,12 +2283,12 @@ void test_nghttp2_submit_data(void)
|
|||
CU_ASSERT(0 == nghttp2_submit_data(session,
|
||||
NGHTTP2_FLAG_END_STREAM |
|
||||
NGHTTP2_FLAG_END_SEGMENT, 1, &data_prd));
|
||||
|
||||
ud.block_count = 0;
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
data_frame = nghttp2_outbound_item_get_data_frame(session->aob.item);
|
||||
nghttp2_frame_unpack_frame_hd(&hd,
|
||||
session->aob.framebuf +
|
||||
session->aob.framebufoff);
|
||||
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
|
||||
nghttp2_frame_unpack_frame_hd(&hd, framebuf->pos);
|
||||
|
||||
CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
|
||||
/* frame->hd.flags has these flags */
|
||||
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT) ==
|
||||
|
@ -2266,10 +2296,9 @@ 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(session->aob.item);
|
||||
nghttp2_frame_unpack_frame_hd(&hd,
|
||||
session->aob.framebuf +
|
||||
session->aob.framebufoff);
|
||||
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
|
||||
nghttp2_frame_unpack_frame_hd(&hd, framebuf->pos);
|
||||
|
||||
/* This is the last frame, so we must have following flags */
|
||||
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_SEGMENT) == hd.flags);
|
||||
/* frame->hd.flags has these flags */
|
||||
|
@ -4100,8 +4129,8 @@ void test_nghttp2_session_pack_data_with_padding(void)
|
|||
|
||||
/* Check reception of this DATA frame */
|
||||
check_session_recv_data_with_padding
|
||||
(session->aob.framebuf + session->aob.framebufoff,
|
||||
session->aob.framebufmark - session->aob.framebufoff,
|
||||
(session->aob.framebuf.pos,
|
||||
session->aob.framebuf.mark - session->aob.framebuf.pos,
|
||||
datalen);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
@ -4126,8 +4155,8 @@ void test_nghttp2_session_pack_data_with_padding(void)
|
|||
|
||||
/* Check reception of this DATA frame */
|
||||
check_session_recv_data_with_padding
|
||||
(session->aob.framebuf + session->aob.framebufoff,
|
||||
session->aob.framebufmark - session->aob.framebufoff,
|
||||
(session->aob.framebuf.pos,
|
||||
session->aob.framebuf.mark - session->aob.framebuf.pos,
|
||||
datalen);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
|
@ -4158,6 +4187,8 @@ void test_nghttp2_session_pack_headers_with_padding(void)
|
|||
acc.length = 0;
|
||||
ud.acc = &acc;
|
||||
|
||||
/* In this test, padding is laid out across 2 frames: HEADERS and
|
||||
CONTINUATION frames */
|
||||
nghttp2_session_client_new(&session, &callbacks, &ud);
|
||||
nghttp2_session_server_new(&sv_session, &callbacks, &ud);
|
||||
|
||||
|
@ -4193,6 +4224,147 @@ void test_nghttp2_session_pack_headers_with_padding(void)
|
|||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_pack_headers_with_padding2(void)
|
||||
{
|
||||
nghttp2_session *session, *sv_session;
|
||||
accumulator acc;
|
||||
my_user_data ud;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_nv nva[16382];
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < ARRLEN(nva); ++i) {
|
||||
nva[i].name = (uint8_t*)":path";
|
||||
nva[i].namelen = 5;
|
||||
nva[i].value = (uint8_t*)"/";
|
||||
nva[i].valuelen = 1;
|
||||
}
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.send_callback = accumulator_send_callback;
|
||||
callbacks.on_frame_send_callback = on_frame_send_callback;
|
||||
callbacks.select_padding_callback = select_padding_callback;
|
||||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||
|
||||
acc.length = 0;
|
||||
ud.acc = &acc;
|
||||
|
||||
/* In this test, padding is laid out across 2 frames: HEADERS and
|
||||
CONTINUATION frames */
|
||||
nghttp2_session_client_new(&session, &callbacks, &ud);
|
||||
nghttp2_session_server_new(&sv_session, &callbacks, &ud);
|
||||
|
||||
ud.padding_boundary = 16385;
|
||||
|
||||
CU_ASSERT(0 ==
|
||||
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT,
|
||||
nva, ARRLEN(nva), NULL, NULL));
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
|
||||
CU_ASSERT(acc.length > NGHTTP2_MAX_FRAME_LENGTH);
|
||||
|
||||
ud.frame_recv_cb_called = 0;
|
||||
CU_ASSERT((ssize_t)acc.length ==
|
||||
nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
|
||||
CU_ASSERT(1 == ud.frame_recv_cb_called);
|
||||
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
|
||||
|
||||
nghttp2_session_del(sv_session);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_pack_headers_with_padding3(void)
|
||||
{
|
||||
nghttp2_session *session, *sv_session;
|
||||
accumulator acc;
|
||||
my_user_data ud;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_nv nva[8192];
|
||||
size_t i;
|
||||
|
||||
for(i = 0; i < ARRLEN(nva); ++i) {
|
||||
nva[i].name = (uint8_t*)":path";
|
||||
nva[i].namelen = 5;
|
||||
nva[i].value = (uint8_t*)"/";
|
||||
nva[i].valuelen = 1;
|
||||
}
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.send_callback = accumulator_send_callback;
|
||||
callbacks.on_frame_send_callback = on_frame_send_callback;
|
||||
callbacks.select_padding_callback = select_padding_callback;
|
||||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||
|
||||
acc.length = 0;
|
||||
ud.acc = &acc;
|
||||
|
||||
/* In this test, padding is included in the last CONTINUATION
|
||||
frame */
|
||||
nghttp2_session_client_new(&session, &callbacks, &ud);
|
||||
nghttp2_session_server_new(&sv_session, &callbacks, &ud);
|
||||
|
||||
ud.padding_boundary = 16385;
|
||||
|
||||
CU_ASSERT(0 ==
|
||||
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT,
|
||||
nva, ARRLEN(nva), NULL, NULL));
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
|
||||
CU_ASSERT(acc.length > NGHTTP2_MAX_FRAME_LENGTH);
|
||||
ud.frame_recv_cb_called = 0;
|
||||
CU_ASSERT((ssize_t)acc.length ==
|
||||
nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
|
||||
CU_ASSERT(1 == ud.frame_recv_cb_called);
|
||||
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
|
||||
|
||||
nghttp2_session_del(sv_session);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_session_pack_headers_with_padding4(void)
|
||||
{
|
||||
nghttp2_session *session, *sv_session;
|
||||
accumulator acc;
|
||||
my_user_data ud;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_nv nva[1];
|
||||
|
||||
nva[0].name = (uint8_t*)":path";
|
||||
nva[0].namelen = 5;
|
||||
nva[0].value = (uint8_t*)"/";
|
||||
nva[0].valuelen = 1;
|
||||
|
||||
memset(&callbacks, 0, sizeof(callbacks));
|
||||
callbacks.send_callback = accumulator_send_callback;
|
||||
callbacks.on_frame_send_callback = on_frame_send_callback;
|
||||
callbacks.select_padding_callback = select_padding_callback;
|
||||
callbacks.on_frame_recv_callback = on_frame_recv_callback;
|
||||
|
||||
acc.length = 0;
|
||||
ud.acc = &acc;
|
||||
|
||||
/* In this test, padding is included in the first HEADERS frame */
|
||||
nghttp2_session_client_new(&session, &callbacks, &ud);
|
||||
nghttp2_session_server_new(&sv_session, &callbacks, &ud);
|
||||
|
||||
ud.padding_boundary = 16385;
|
||||
|
||||
CU_ASSERT(0 ==
|
||||
nghttp2_submit_request(session, NGHTTP2_PRI_DEFAULT,
|
||||
nva, ARRLEN(nva), NULL, NULL));
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
|
||||
CU_ASSERT(acc.length < NGHTTP2_MAX_FRAME_LENGTH);
|
||||
ud.frame_recv_cb_called = 0;
|
||||
CU_ASSERT((ssize_t)acc.length ==
|
||||
nghttp2_session_mem_recv(sv_session, acc.buf, acc.length));
|
||||
CU_ASSERT(1 == ud.frame_recv_cb_called);
|
||||
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
|
||||
|
||||
nghttp2_session_del(sv_session);
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_pack_settings_payload(void)
|
||||
{
|
||||
nghttp2_settings_entry iv[2];
|
||||
|
|
|
@ -92,6 +92,9 @@ void test_nghttp2_session_set_option(void);
|
|||
void test_nghttp2_session_data_backoff_by_high_pri_frame(void);
|
||||
void test_nghttp2_session_pack_data_with_padding(void);
|
||||
void test_nghttp2_session_pack_headers_with_padding(void);
|
||||
void test_nghttp2_session_pack_headers_with_padding2(void);
|
||||
void test_nghttp2_session_pack_headers_with_padding3(void);
|
||||
void test_nghttp2_session_pack_headers_with_padding4(void);
|
||||
void test_nghttp2_pack_settings_payload(void);
|
||||
|
||||
#endif /* NGHTTP2_SESSION_TEST_H */
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
int unpack_framebuf(nghttp2_frame *frame, nghttp2_buf *buf)
|
||||
{
|
||||
return unpack_frame(frame, buf->pos, nghttp2_buf_len(buf));
|
||||
}
|
||||
|
||||
int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len)
|
||||
{
|
||||
ssize_t rv = 0;
|
||||
|
|
|
@ -54,6 +54,8 @@
|
|||
free(a); \
|
||||
} while(0);
|
||||
|
||||
int unpack_framebuf(nghttp2_frame *frame, nghttp2_buf *buf);
|
||||
|
||||
int unpack_frame(nghttp2_frame *frame, const uint8_t *in, size_t len);
|
||||
|
||||
int strmemeq(const char *a, const uint8_t *b, size_t bn);
|
||||
|
|
Loading…
Reference in New Issue