Support transmission of CONTINUATION, change nghttp2_frame_hd
The maximum frame size including header block is still limited to NGHTTP2_HD_MAX_BUFFER_LENGTH, which is 32KB.
This commit is contained in:
parent
91401cfe26
commit
9314e30987
|
@ -504,7 +504,11 @@ typedef struct {
|
|||
/**
|
||||
* The length field of this frame, excluding frame header.
|
||||
*/
|
||||
uint16_t length;
|
||||
size_t length;
|
||||
/**
|
||||
* The stream identifier (aka, stream ID)
|
||||
*/
|
||||
int32_t stream_id;
|
||||
/**
|
||||
* The type of this frame. See `nghttp2_frame`.
|
||||
*/
|
||||
|
@ -513,10 +517,6 @@ typedef struct {
|
|||
* The flags.
|
||||
*/
|
||||
uint8_t flags;
|
||||
/**
|
||||
* The stream identifier (aka, stream ID)
|
||||
*/
|
||||
int32_t stream_id;
|
||||
} nghttp2_frame_hd;
|
||||
|
||||
|
||||
|
|
|
@ -230,7 +230,12 @@ ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
|
|||
return rv;
|
||||
}
|
||||
framelen = rv + nv_offset;
|
||||
frame->hd.length = framelen - NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
if(NGHTTP2_FRAME_HEAD_LENGTH + NGHTTP2_MAX_FRAME_LENGTH < rv + nv_offset) {
|
||||
frame->hd.length = NGHTTP2_MAX_FRAME_LENGTH;
|
||||
frame->hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
} else {
|
||||
frame->hd.length = framelen - NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
}
|
||||
/* If frame->nvlen == 0, *buflen_ptr may be smaller than
|
||||
nv_offset */
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset);
|
||||
|
@ -387,7 +392,12 @@ ssize_t nghttp2_frame_pack_push_promise(uint8_t **buf_ptr,
|
|||
return rv;
|
||||
}
|
||||
framelen = rv + nv_offset;
|
||||
frame->hd.length = framelen - NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
if(NGHTTP2_FRAME_HEAD_LENGTH + NGHTTP2_MAX_FRAME_LENGTH < rv + nv_offset) {
|
||||
frame->hd.length = NGHTTP2_MAX_FRAME_LENGTH;
|
||||
frame->hd.flags &= ~NGHTTP2_FLAG_END_HEADERS;
|
||||
} else {
|
||||
frame->hd.length = framelen - NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
}
|
||||
/* If frame->nvlen == 0, *buflen_ptr may be smaller than
|
||||
nv_offset */
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, nv_offset);
|
||||
|
@ -562,8 +572,8 @@ ssize_t nghttp2_nv_array_copy(nghttp2_nv **nva_ptr,
|
|||
size_t buflen = 0;
|
||||
nghttp2_nv *p;
|
||||
for(i = 0; i < nvlen; ++i) {
|
||||
if(nva[i].namelen > NGHTTP2_MAX_HD_VALUE_LENGTH ||
|
||||
nva[i].valuelen > NGHTTP2_MAX_HD_VALUE_LENGTH) {
|
||||
if(nva[i].namelen > NGHTTP2_HD_MAX_NAME ||
|
||||
nva[i].valuelen > NGHTTP2_HD_MAX_VALUE) {
|
||||
return NGHTTP2_ERR_INVALID_ARGUMENT;
|
||||
}
|
||||
buflen += nva[i].namelen + nva[i].valuelen;
|
||||
|
|
|
@ -33,10 +33,6 @@
|
|||
#include "nghttp2_hd.h"
|
||||
#include "nghttp2_buffer.h"
|
||||
|
||||
/* The maximum value length of name/value pair. This is not specified
|
||||
by the spec. We just chose the arbitrary size */
|
||||
#define NGHTTP2_MAX_HD_VALUE_LENGTH ((1 << 13) - 1)
|
||||
|
||||
#define NGHTTP2_FRAME_LENGTH_MASK ((1 << 14) - 1)
|
||||
#define NGHTTP2_STREAM_ID_MASK ((1u << 31) - 1)
|
||||
#define NGHTTP2_PRIORITY_MASK ((1u << 31) - 1)
|
||||
|
@ -99,7 +95,10 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
|
|||
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
|
||||
*
|
||||
* frame->hd.length is assigned after length is determined during
|
||||
* packing process.
|
||||
* packing process. If payload length is strictly larger than
|
||||
* NGHTTP2_MAX_FRAME_LENGTH, payload data is still serialized as is,
|
||||
* 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 if it succeeds, or
|
||||
* returns one of the following negative error codes:
|
||||
|
@ -242,7 +241,10 @@ int nghttp2_frame_unpack_settings_payload2(nghttp2_settings_entry **iv_ptr,
|
|||
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
|
||||
*
|
||||
* frame->hd.length is assigned after length is determined during
|
||||
* packing process.
|
||||
* packing process. If payload length is strictly larger than
|
||||
* NGHTTP2_MAX_FRAME_LENGTH, payload data is still serialized as is,
|
||||
* 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 if it succeeds, or
|
||||
* returns one of the following negative error codes:
|
||||
|
|
|
@ -443,9 +443,7 @@ static int ensure_write_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
|
|||
size_t offset, size_t need)
|
||||
{
|
||||
int rv;
|
||||
/* TODO Remove this limitation when header continuation is
|
||||
implemented. */
|
||||
if(need + offset > NGHTTP2_MAX_FRAME_LENGTH) {
|
||||
if(need + offset > NGHTTP2_HD_MAX_BUFFER_LENGTH) {
|
||||
return NGHTTP2_ERR_HEADER_COMP;
|
||||
}
|
||||
rv = nghttp2_reserve_buffer(buf_ptr, buflen_ptr, offset + need);
|
||||
|
|
|
@ -37,8 +37,11 @@
|
|||
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE (1 << 12)
|
||||
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
|
||||
|
||||
/* The maximum value length of name/value pair. This is not specified
|
||||
by the spec. We just chose the arbitrary size */
|
||||
#define NGHTTP2_HD_MAX_NAME 256
|
||||
#define NGHTTP2_HD_MAX_VALUE 4096
|
||||
#define NGHTTP2_HD_MAX_BUFFER_LENGTH (1 << 15)
|
||||
|
||||
/* Default size of maximum table buffer size for encoder. Even if
|
||||
remote decoder notifies larger buffer size for its decoding,
|
||||
|
|
|
@ -384,7 +384,7 @@ static void nghttp2_active_outbound_item_reset
|
|||
nghttp2_outbound_item_free(aob->item);
|
||||
free(aob->item);
|
||||
aob->item = NULL;
|
||||
aob->framebuflen = aob->framebufoff = 0;
|
||||
aob->framebuflen = aob->framebufoff = aob->framebufmark = 0;
|
||||
}
|
||||
|
||||
void nghttp2_session_del(nghttp2_session *session)
|
||||
|
@ -1405,6 +1405,32 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
int r;
|
||||
nghttp2_frame *frame;
|
||||
frame = nghttp2_outbound_item_get_ctrl_frame(session->aob.item);
|
||||
if(frame->hd.type == NGHTTP2_HEADERS ||
|
||||
frame->hd.type == NGHTTP2_PUSH_PROMISE) {
|
||||
if(session->aob.framebufmark < session->aob.framebuflen) {
|
||||
nghttp2_frame_hd cont_hd;
|
||||
cont_hd.length = nghttp2_min(session->aob.framebuflen -
|
||||
session->aob.framebufmark,
|
||||
NGHTTP2_MAX_FRAME_LENGTH);
|
||||
cont_hd.type = NGHTTP2_CONTINUATION;
|
||||
if(cont_hd.length < NGHTTP2_MAX_FRAME_LENGTH) {
|
||||
cont_hd.flags = NGHTTP2_FLAG_END_HEADERS;
|
||||
} else {
|
||||
cont_hd.flags = NGHTTP2_FLAG_NONE;
|
||||
}
|
||||
cont_hd.stream_id = frame->hd.stream_id;
|
||||
nghttp2_frame_pack_frame_hd(session->aob.framebuf +
|
||||
session->aob.framebufmark -
|
||||
NGHTTP2_FRAME_HEAD_LENGTH,
|
||||
&cont_hd);
|
||||
session->aob.framebufmark += cont_hd.length;
|
||||
session->aob.framebufoff -= NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
return 0;
|
||||
}
|
||||
/* Update frame payload length to include data sent in
|
||||
CONTINUATION frame. */
|
||||
frame->hd.length = session->aob.framebuflen - NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
}
|
||||
if(session->callbacks.on_frame_send_callback) {
|
||||
if(session->callbacks.on_frame_send_callback(session, frame,
|
||||
session->user_data) != 0) {
|
||||
|
@ -1623,7 +1649,7 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
|
|||
nghttp2_active_outbound_item_reset(&session->aob);
|
||||
return r;
|
||||
} else {
|
||||
session->aob.framebuflen = r;
|
||||
session->aob.framebuflen = session->aob.framebufmark = r;
|
||||
session->aob.framebufoff = 0;
|
||||
}
|
||||
} else {
|
||||
|
@ -1666,7 +1692,8 @@ int nghttp2_session_send(nghttp2_session *session)
|
|||
framebuflen = nghttp2_session_prep_frame(session, item);
|
||||
if(framebuflen == NGHTTP2_ERR_DEFERRED) {
|
||||
continue;
|
||||
} else if(framebuflen < 0) {
|
||||
}
|
||||
if(framebuflen < 0) {
|
||||
/* TODO If the error comes from compressor, the connection
|
||||
must be closed. */
|
||||
if(item->frame_cat == NGHTTP2_CAT_CTRL &&
|
||||
|
@ -1700,19 +1727,31 @@ int nghttp2_session_send(nghttp2_session *session)
|
|||
}
|
||||
session->aob.item = item;
|
||||
session->aob.framebuflen = framebuflen;
|
||||
/* Call before_send callback */
|
||||
if(item->frame_cat == NGHTTP2_CAT_CTRL &&
|
||||
session->callbacks.before_frame_send_callback) {
|
||||
if(session->callbacks.before_frame_send_callback
|
||||
(session,
|
||||
nghttp2_outbound_item_get_ctrl_frame(item),
|
||||
session->user_data) != 0) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
|
||||
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
|
||||
nghttp2_frame *frame = nghttp2_outbound_item_get_ctrl_frame(item);
|
||||
session->aob.framebufmark =
|
||||
frame->hd.length + NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
/* Call before_send callback */
|
||||
if(session->callbacks.before_frame_send_callback) {
|
||||
size_t origlen = frame->hd.length;
|
||||
frame->hd.length =
|
||||
session->aob.framebuflen - NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
r = session->callbacks.before_frame_send_callback
|
||||
(session, frame, session->user_data);
|
||||
frame->hd.length = origlen;
|
||||
if(r != 0) {
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
session->aob.framebufmark =
|
||||
nghttp2_outbound_item_get_data_frame
|
||||
(session->aob.item)->hd.length + NGHTTP2_FRAME_HEAD_LENGTH;
|
||||
}
|
||||
}
|
||||
data = session->aob.framebuf + session->aob.framebufoff;
|
||||
datalen = session->aob.framebuflen - session->aob.framebufoff;
|
||||
datalen = session->aob.framebufmark - session->aob.framebufoff;
|
||||
sentlen = session->callbacks.send_callback(session, data, datalen, 0,
|
||||
session->user_data);
|
||||
if(sentlen < 0) {
|
||||
|
@ -1742,7 +1781,7 @@ int nghttp2_session_send(nghttp2_session *session)
|
|||
}
|
||||
}
|
||||
session->aob.framebufoff += sentlen;
|
||||
if(session->aob.framebufoff == session->aob.framebuflen) {
|
||||
if(session->aob.framebufoff == session->aob.framebufmark) {
|
||||
/* Frame has completely sent */
|
||||
r = nghttp2_session_after_frame_sent(session);
|
||||
if(r < 0) {
|
||||
|
@ -1823,6 +1862,8 @@ static int session_call_on_end_headers
|
|||
(nghttp2_session *session, nghttp2_frame *frame, nghttp2_error_code error_code)
|
||||
{
|
||||
int rv;
|
||||
DEBUGF(fprintf(stderr, "Call on_end_headers callback stream_id=%d\n",
|
||||
frame->hd.stream_id));
|
||||
if(session->callbacks.on_end_headers_callback) {
|
||||
rv = session->callbacks.on_end_headers_callback(session, frame, error_code,
|
||||
session->user_data);
|
||||
|
@ -2167,11 +2208,6 @@ int nghttp2_session_on_request_headers_received(nghttp2_session *session,
|
|||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
/* Connection error if header continuation is employed for now */
|
||||
if((frame->hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
|
||||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_INTERNAL_ERROR);
|
||||
}
|
||||
if(session->goaway_flags) {
|
||||
/* We don't accept new stream after GOAWAY is sent or received. */
|
||||
return NGHTTP2_ERR_IGN_HEADER_BLOCK;
|
||||
|
@ -2222,11 +2258,6 @@ int nghttp2_session_on_response_headers_received(nghttp2_session *session,
|
|||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
/* Connection error if header continuation is employed for now */
|
||||
if((frame->hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
|
||||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_INTERNAL_ERROR);
|
||||
}
|
||||
if(stream->shut_flags & NGHTTP2_SHUT_RD) {
|
||||
/* half closed (remote): from the spec:
|
||||
|
||||
|
@ -2255,11 +2286,6 @@ int nghttp2_session_on_push_response_headers_received(nghttp2_session *session,
|
|||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
/* Connection error if header continuation is employed for now */
|
||||
if((frame->hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
|
||||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_INTERNAL_ERROR);
|
||||
}
|
||||
if(session->goaway_flags) {
|
||||
/* We don't accept new stream after GOAWAY is sent or received. */
|
||||
return NGHTTP2_ERR_IGN_HEADER_BLOCK;
|
||||
|
@ -2286,11 +2312,6 @@ int nghttp2_session_on_headers_received(nghttp2_session *session,
|
|||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
/* Connection error if header continuation is employed for now */
|
||||
if((frame->hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
|
||||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_INTERNAL_ERROR);
|
||||
}
|
||||
if(stream->state == NGHTTP2_STREAM_RESERVED) {
|
||||
/* reserved. The valid push response HEADERS is processed by
|
||||
nghttp2_session_on_push_response_headers_received(). This
|
||||
|
@ -2848,11 +2869,6 @@ int nghttp2_session_on_push_promise_received(nghttp2_session *session,
|
|||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
||||
}
|
||||
/* Connection error if header continuation is employed for now */
|
||||
if((frame->hd.flags & NGHTTP2_FLAG_END_PUSH_PROMISE) == 0) {
|
||||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_INTERNAL_ERROR);
|
||||
}
|
||||
if(session->local_settings[NGHTTP2_SETTINGS_ENABLE_PUSH] == 0) {
|
||||
return nghttp2_session_inflate_handle_invalid_connection
|
||||
(session, frame, NGHTTP2_PROTOCOL_ERROR);
|
||||
|
@ -3601,6 +3617,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
readlen = inbound_frame_payload_readlen(iframe, in, last);
|
||||
DEBUGF(fprintf(stderr, "readlen=%zu, payloadleft=%zu\n",
|
||||
readlen, iframe->payloadleft));
|
||||
DEBUGF(fprintf(stderr, "block final=%d\n",
|
||||
(iframe->frame.hd.flags &
|
||||
NGHTTP2_FLAG_END_HEADERS) &&
|
||||
iframe->payloadleft == readlen));
|
||||
rv = inflate_header_block(session, &iframe->frame, &readlen,
|
||||
(uint8_t*)in, readlen,
|
||||
(iframe->frame.hd.flags &
|
||||
|
@ -3730,6 +3750,10 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
|
|||
iframe->payloadleft = cont_hd.length;
|
||||
if(cont_hd.type != NGHTTP2_CONTINUATION ||
|
||||
cont_hd.stream_id != iframe->frame.hd.stream_id) {
|
||||
DEBUGF(fprintf(stderr, "expected stream_id=%d, type=%d, but "
|
||||
"got stream_id=%d, type=%d\n",
|
||||
iframe->frame.hd.stream_id, NGHTTP2_CONTINUATION,
|
||||
cont_hd.stream_id, cont_hd.type));
|
||||
rv = nghttp2_session_terminate_session(session,
|
||||
NGHTTP2_PROTOCOL_ERROR);
|
||||
if(nghttp2_is_fatal(rv)) {
|
||||
|
@ -4024,6 +4048,7 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
|
|||
/* This is the error code when callback is failed. */
|
||||
return NGHTTP2_ERR_CALLBACK_FAILURE;
|
||||
}
|
||||
frame->hd.length = r;
|
||||
memset(*buf_ptr, 0, NGHTTP2_FRAME_HEAD_LENGTH);
|
||||
nghttp2_put_uint16be(&(*buf_ptr)[0], r);
|
||||
flags = 0;
|
||||
|
|
|
@ -60,6 +60,9 @@ typedef struct {
|
|||
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_active_outbound_item;
|
||||
|
||||
/* Buffer length for inbound raw byte stream. */
|
||||
|
|
|
@ -438,7 +438,7 @@ void print_data_frame(print_type ptype, uint16_t length, uint8_t flags,
|
|||
{
|
||||
printf("%sDATA%s frame ",
|
||||
frame_name_ansi_esc(ptype), ansi_escend());
|
||||
nghttp2_frame_hd hd = {length, NGHTTP2_DATA, flags, stream_id};
|
||||
nghttp2_frame_hd hd = {length, stream_id, NGHTTP2_DATA, flags};
|
||||
print_frame_hd(hd);
|
||||
if(flags) {
|
||||
print_frame_attr_indent();
|
||||
|
|
|
@ -144,6 +144,8 @@ int main(int argc, char* argv[])
|
|||
!CU_add_test(pSuite, "submit_headers_push_reply",
|
||||
test_nghttp2_submit_headers_push_reply) ||
|
||||
!CU_add_test(pSuite, "submit_headers", test_nghttp2_submit_headers) ||
|
||||
!CU_add_test(pSuite, "submit_headers_continuation",
|
||||
test_nghttp2_submit_headers_continuation) ||
|
||||
!CU_add_test(pSuite, "submit_priority", test_nghttp2_submit_priority) ||
|
||||
!CU_add_test(pSuite, "session_submit_settings",
|
||||
test_nghttp2_submit_settings) ||
|
||||
|
|
|
@ -143,8 +143,8 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
|
|||
ssize_t framelen;
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
size_t big_vallen = NGHTTP2_MAX_HD_VALUE_LENGTH;
|
||||
nghttp2_nv big_hds[8];
|
||||
size_t big_vallen = NGHTTP2_HD_MAX_VALUE;
|
||||
nghttp2_nv big_hds[16];
|
||||
size_t big_hdslen = ARRLEN(big_hds);
|
||||
size_t i;
|
||||
|
||||
|
|
|
@ -734,7 +734,7 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
|
||||
ud.header_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, data, datalen);
|
||||
CU_ASSERT(rv == datalen);
|
||||
CU_ASSERT((ssize_t)datalen == rv);
|
||||
CU_ASSERT(2 == ud.header_cb_called);
|
||||
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
|
@ -765,7 +765,7 @@ void test_nghttp2_session_recv_continuation(void)
|
|||
|
||||
ud.end_headers_cb_called = 0;
|
||||
rv = nghttp2_session_mem_recv(session, data, datalen);
|
||||
CU_ASSERT(datalen == rv);
|
||||
CU_ASSERT((ssize_t)datalen == rv);
|
||||
|
||||
CU_ASSERT(1 == ud.end_headers_cb_called);
|
||||
CU_ASSERT(NGHTTP2_GOAWAY ==
|
||||
|
@ -847,7 +847,8 @@ void test_nghttp2_session_continue(void)
|
|||
|
||||
recv_frame = user_data.frame;
|
||||
CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
|
||||
CU_ASSERT(framelen1 - NGHTTP2_FRAME_HEAD_LENGTH == recv_frame->hd.length);
|
||||
CU_ASSERT((size_t)framelen1 - NGHTTP2_FRAME_HEAD_LENGTH ==
|
||||
recv_frame->hd.length);
|
||||
|
||||
CU_ASSERT(1 == user_data.header_cb_called);
|
||||
CU_ASSERT(0 == user_data.end_headers_cb_called);
|
||||
|
@ -877,7 +878,8 @@ void test_nghttp2_session_continue(void)
|
|||
|
||||
recv_frame = user_data.frame;
|
||||
CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
|
||||
CU_ASSERT(framelen2 - NGHTTP2_FRAME_HEAD_LENGTH == recv_frame->hd.length);
|
||||
CU_ASSERT((size_t)framelen2 - NGHTTP2_FRAME_HEAD_LENGTH ==
|
||||
recv_frame->hd.length);
|
||||
|
||||
CU_ASSERT(1 == user_data.header_cb_called);
|
||||
CU_ASSERT(1 == user_data.end_headers_cb_called);
|
||||
|
@ -1801,7 +1803,6 @@ void test_nghttp2_session_send_headers_reply(void)
|
|||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
/* TODO Rewrite this test when header continuation is supported */
|
||||
void test_nghttp2_session_send_headers_header_comp_error(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
|
@ -1809,8 +1810,8 @@ void test_nghttp2_session_send_headers_header_comp_error(void)
|
|||
nghttp2_frame *frame = malloc(sizeof(nghttp2_frame));
|
||||
nghttp2_nv *nva;
|
||||
ssize_t nvlen;
|
||||
size_t vallen = NGHTTP2_MAX_HD_VALUE_LENGTH;
|
||||
nghttp2_nv nv[8];
|
||||
size_t vallen = NGHTTP2_HD_MAX_VALUE;
|
||||
nghttp2_nv nv[16];
|
||||
size_t nnv = ARRLEN(nv);
|
||||
size_t i;
|
||||
|
||||
|
@ -2455,6 +2456,52 @@ void test_nghttp2_submit_headers(void)
|
|||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_submit_headers_continuation(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
nghttp2_session_callbacks callbacks;
|
||||
nghttp2_nv nv[] = {
|
||||
MAKE_NV("h1", ""),
|
||||
MAKE_NV("h1", ""),
|
||||
MAKE_NV("h1", ""),
|
||||
MAKE_NV("h1", ""),
|
||||
MAKE_NV("h1", ""),
|
||||
MAKE_NV("h1", ""),
|
||||
MAKE_NV("h1", ""),
|
||||
};
|
||||
nghttp2_outbound_item *item;
|
||||
uint8_t data[4096];
|
||||
size_t i;
|
||||
my_user_data ud;
|
||||
|
||||
memset(data, '0', sizeof(data));
|
||||
for(i = 0; i < ARRLEN(nv); ++i) {
|
||||
nv[i].valuelen = sizeof(data);
|
||||
nv[i].value = data;
|
||||
}
|
||||
|
||||
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
|
||||
callbacks.send_callback = null_send_callback;
|
||||
callbacks.on_frame_send_callback = on_frame_send_callback;
|
||||
|
||||
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
|
||||
CU_ASSERT(0 == nghttp2_submit_headers(session,
|
||||
NGHTTP2_FLAG_END_STREAM,
|
||||
-1, NGHTTP2_PRI_DEFAULT,
|
||||
nv, ARRLEN(nv), NULL));
|
||||
item = nghttp2_session_get_next_ob_item(session);
|
||||
CU_ASSERT(NGHTTP2_HEADERS == OB_CTRL_TYPE(item));
|
||||
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
|
||||
OB_CTRL(item)->hd.flags);
|
||||
CU_ASSERT(NGHTTP2_PRI_DEFAULT == OB_CTRL(item)->headers.pri);
|
||||
|
||||
ud.frame_send_cb_called = 0;
|
||||
CU_ASSERT(0 == nghttp2_session_send(session));
|
||||
CU_ASSERT(1 == ud.frame_send_cb_called);
|
||||
|
||||
nghttp2_session_del(session);
|
||||
}
|
||||
|
||||
void test_nghttp2_submit_priority(void)
|
||||
{
|
||||
nghttp2_session *session;
|
||||
|
|
|
@ -62,6 +62,7 @@ void test_nghttp2_submit_headers_start_stream(void);
|
|||
void test_nghttp2_submit_headers_reply(void);
|
||||
void test_nghttp2_submit_headers_push_reply(void);
|
||||
void test_nghttp2_submit_headers(void);
|
||||
void test_nghttp2_submit_headers_continuation(void);
|
||||
void test_nghttp2_submit_priority(void);
|
||||
void test_nghttp2_submit_settings(void);
|
||||
void test_nghttp2_submit_settings_update_local_window_size(void);
|
||||
|
|
Loading…
Reference in New Issue