nghttp2_sesson_mem_recv: Process incoming data in streaming fashion

Now incoming data is processed in very small buffer (up to 8 bytes)
using state machine. GOAWAY debug data can get to 16K - 1, and we
don't have callback for it. Since we don't want to buffer that
amount of data just for debugging, we currently discard it.
This change also makes parse_error callback not function.
It probably be removed from API.
This commit is contained in:
Tatsuhiro Tsujikawa 2014-01-26 15:44:43 +09:00
parent 8317559090
commit dba2406aba
6 changed files with 932 additions and 695 deletions

View File

@ -270,6 +270,25 @@ int nghttp2_frame_unpack_headers_without_nv(nghttp2_headers *frame,
return 0;
}
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
const uint8_t *payload,
size_t payloadlen)
{
/* TODO Return error if header continuation is used for now */
if((frame->hd.flags & NGHTTP2_FLAG_END_HEADERS) == 0) {
return NGHTTP2_ERR_PROTO;
}
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
assert(payloadlen == 4);
frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK;
} else {
frame->pri = NGHTTP2_PRI_DEFAULT;
}
frame->nva = NULL;
frame->nvlen = 0;
return 0;
}
ssize_t nghttp2_frame_pack_priority(uint8_t **buf_ptr, size_t *buflen_ptr,
nghttp2_priority *frame)
{
@ -295,7 +314,13 @@ int nghttp2_frame_unpack_priority(nghttp2_priority *frame,
nghttp2_frame_unpack_frame_hd(&frame->hd, head);
frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK;
return 0;
}
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
const uint8_t *payload,
size_t payloadlen)
{
frame->pri = nghttp2_get_uint32(payload) & NGHTTP2_PRIORITY_MASK;
}
ssize_t nghttp2_frame_pack_rst_stream(uint8_t **buf_ptr, size_t *buflen_ptr,
@ -325,6 +350,13 @@ int nghttp2_frame_unpack_rst_stream(nghttp2_rst_stream *frame,
return 0;
}
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
const uint8_t *payload,
size_t payloadlen)
{
frame->error_code = nghttp2_get_uint32(payload);
}
ssize_t nghttp2_frame_pack_settings(uint8_t **buf_ptr, size_t *buflen_ptr,
nghttp2_settings *frame)
{
@ -371,6 +403,29 @@ int nghttp2_frame_unpack_settings(nghttp2_settings *frame,
return 0;
}
int nghttp2_frame_unpack_settings_payload2(nghttp2_settings *frame,
nghttp2_settings_entry *iv,
size_t niv)
{
size_t payloadlen = niv * sizeof(nghttp2_settings_entry);
frame->iv = malloc(payloadlen);
if(frame->iv == NULL) {
return NGHTTP2_ERR_NOMEM;
}
memcpy(frame->iv, iv, payloadlen);
frame->niv = niv;
return 0;
}
void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
const uint8_t *payload)
{
iv->settings_id = nghttp2_get_uint32(&payload[0]) &
NGHTTP2_SETTINGS_ID_MASK;
iv->value = nghttp2_get_uint32(&payload[4]);
}
int nghttp2_frame_unpack_settings_payload(nghttp2_settings_entry **iv_ptr,
size_t *niv_ptr,
const uint8_t *payload,
@ -384,9 +439,7 @@ int nghttp2_frame_unpack_settings_payload(nghttp2_settings_entry **iv_ptr,
}
for(i = 0; i < *niv_ptr; ++i) {
size_t off = i*8;
(*iv_ptr)[i].settings_id = nghttp2_get_uint32(&payload[off]) &
NGHTTP2_SETTINGS_ID_MASK;
(*iv_ptr)[i].value = nghttp2_get_uint32(&payload[4+off]);
nghttp2_frame_unpack_settings_entry(&(*iv_ptr)[i], &payload[off]);
}
return 0;
}
@ -440,6 +493,21 @@ int nghttp2_frame_unpack_push_promise_without_nv(nghttp2_push_promise *frame,
return 0;
}
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
const uint8_t *payload,
size_t payloadlen)
{
/* TODO Return error if header continuation is used for now */
if((frame->hd.flags & NGHTTP2_FLAG_END_PUSH_PROMISE) == 0) {
return NGHTTP2_ERR_PROTO;
}
frame->promised_stream_id = nghttp2_get_uint32(payload) &
NGHTTP2_STREAM_ID_MASK;
frame->nva = NULL;
frame->nvlen = 0;
return 0;
}
ssize_t nghttp2_frame_pack_ping(uint8_t **buf_ptr, size_t *buflen_ptr,
nghttp2_ping *frame)
{
@ -467,6 +535,12 @@ int nghttp2_frame_unpack_ping(nghttp2_ping *frame,
return 0;
}
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
const uint8_t *payload,
size_t payloadlen)
{
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)
@ -508,6 +582,17 @@ int nghttp2_frame_unpack_goaway(nghttp2_goaway *frame,
return 0;
}
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
const uint8_t *payload,
size_t payloadlen)
{
frame->last_stream_id = nghttp2_get_uint32(payload) & NGHTTP2_STREAM_ID_MASK;
frame->error_code = nghttp2_get_uint32(payload+4);
/* TODO Currently we don't buffer debug data */
frame->opaque_data = NULL;
frame->opaque_data_len = 0;
}
ssize_t nghttp2_frame_pack_window_update(uint8_t **buf_ptr, size_t *buflen_ptr,
nghttp2_window_update *frame)
{
@ -537,6 +622,14 @@ int nghttp2_frame_unpack_window_update(nghttp2_window_update *frame,
return 0;
}
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
const uint8_t *payload,
size_t payloadlen)
{
frame->window_size_increment = nghttp2_get_uint32(payload) &
NGHTTP2_WINDOW_SIZE_INCREMENT_MASK;
}
nghttp2_settings_entry* nghttp2_frame_iv_copy(const nghttp2_settings_entry *iv,
size_t niv)
{

View File

@ -161,6 +161,10 @@ int nghttp2_frame_unpack_headers_without_nv(nghttp2_headers *frame,
const uint8_t *payload,
size_t payloadlen);
int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
const uint8_t *payload,
size_t payloadlen);
/*
* Packs PRIORITY frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
@ -189,6 +193,10 @@ int nghttp2_frame_unpack_priority(nghttp2_priority *frame,
const uint8_t *head, size_t headlen,
const uint8_t *payload, size_t payloadlen);
void nghttp2_frame_unpack_priority_payload(nghttp2_priority *frame,
const uint8_t *payload,
size_t payloadlen);
/*
* Packs RST_STREAM frame |frame| in wire frame format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
@ -218,6 +226,10 @@ int nghttp2_frame_unpack_rst_stream(nghttp2_rst_stream *frame,
const uint8_t *head, size_t headlen,
const uint8_t *payload, size_t payloadlen);
void nghttp2_frame_unpack_rst_stream_payload(nghttp2_rst_stream *frame,
const uint8_t *payload,
size_t payloadlen);
/*
* Packs SETTINGS frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
@ -259,6 +271,13 @@ int nghttp2_frame_unpack_settings(nghttp2_settings *frame,
const uint8_t *payload, size_t payloadlen);
void nghttp2_frame_unpack_settings_entry(nghttp2_settings_entry *iv,
const uint8_t *payload);
int nghttp2_frame_unpack_settings_payload2(nghttp2_settings *frame,
nghttp2_settings_entry *iv,
size_t niv);
/*
* Unpacks SETTINGS payload into |*iv_ptr|. The number of entries are
* assigned to the |*niv_ptr|. This function allocates enough memory
@ -347,6 +366,10 @@ int nghttp2_frame_unpack_push_promise_without_nv(nghttp2_push_promise *frame,
const uint8_t *payload,
size_t payloadlen);
int nghttp2_frame_unpack_push_promise_payload(nghttp2_push_promise *frame,
const uint8_t *payload,
size_t payloadlen);
/*
* Packs PING frame |frame| in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
@ -375,6 +398,10 @@ int nghttp2_frame_unpack_ping(nghttp2_ping *frame,
const uint8_t *head, size_t headlen,
const uint8_t *payload, size_t payloadlen);
void nghttp2_frame_unpack_ping_payload(nghttp2_ping *frame,
const uint8_t *payload,
size_t payloadlen);
/*
* Packs GOAWAY frame |frame | in wire format and store it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
@ -405,6 +432,10 @@ int nghttp2_frame_unpack_goaway(nghttp2_goaway *frame,
const uint8_t *head, size_t headlen,
const uint8_t *payload, size_t payloadlen);
void nghttp2_frame_unpack_goaway_payload(nghttp2_goaway *frame,
const uint8_t *payload,
size_t payloadlen);
/*
* Packs WINDOW_UPDATE frame |frame| in wire frame format and store it
* in |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
@ -434,6 +465,10 @@ int nghttp2_frame_unpack_window_update(nghttp2_window_update *frame,
const uint8_t *payload,
size_t payloadlen);
void nghttp2_frame_unpack_window_update_payload(nghttp2_window_update *frame,
const uint8_t *payload,
size_t payloadlen);
/*
* Initializes HEADERS frame |frame| with given values. |frame| takes
* ownership of |nva|, so caller must not free it. If |stream_id| is

View File

@ -45,7 +45,9 @@ typedef int (*nghttp2_compar)(const void *lhs, const void *rhs);
inclusive. */
typedef enum {
NGHTTP2_ERR_CREDENTIAL_PENDING = -101,
NGHTTP2_ERR_BUFFER_ERROR = - 102
NGHTTP2_ERR_BUFFER_ERROR = -102,
NGHTTP2_ERR_IGN_HEADER_BLOCK = -103,
NGHTTP2_ERR_IGN_PAYLOAD = -104,
} nghttp2_internal_error;
#endif /* NGHTTP2_INT_H */

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,7 @@
#include "nghttp2_stream.h"
#include "nghttp2_buffer.h"
#include "nghttp2_outbound_item.h"
#include "nghttp2_int.h"
/*
* Option flags.
@ -72,39 +73,36 @@ typedef struct {
/* Internal state when receiving incoming frame */
typedef enum {
/* Receiving frame header */
NGHTTP2_RECV_HEAD,
/* Receiving frame payload (comes after length field) */
NGHTTP2_RECV_PAYLOAD,
/* Receiving frame payload, but the received bytes are discarded. */
NGHTTP2_RECV_PAYLOAD_IGN
NGHTTP2_IB_READ_HEAD,
NGHTTP2_IB_READ_NBYTE,
NGHTTP2_IB_READ_HEADER_BLOCK,
NGHTTP2_IB_IGN_HEADER_BLOCK,
NGHTTP2_IB_IGN_PAYLOAD,
NGHTTP2_IB_FRAME_SIZE_ERROR,
NGHTTP2_IB_READ_SETTINGS,
NGHTTP2_IB_READ_GOAWAY_DEBUG,
NGHTTP2_IB_READ_DATA,
NGHTTP2_IB_IGN_DATA
} nghttp2_inbound_state;
typedef struct {
nghttp2_frame frame;
/* Payload for non-DATA frames. */
uint8_t *buf;
/* How many bytes are filled in headbuf */
size_t headbufoff;
/* Capacity of buf */
size_t bufmax;
/* For frames without name/value header block, this is how many
bytes are going to filled in buf. For frames with the block, buf
only contains bytes that come before ther block, but this value
includes the length of the block. buflen <= bufmax must be
fulfilled. */
size_t buflen;
/* length in Length field */
size_t payloadlen;
/* How many bytes are received for this frame. off <= payloadlen
must be fulfilled. */
size_t off;
/* How many bytes are decompressed inside |buf|. This is used for
header decompression. */
size_t inflate_offset;
/* The received SETTINGS entry. The protocol says that we only cares
about the defined settings ID. If unknown ID is received, it is
subject to connection error */
nghttp2_settings_entry iv[5];
/* The number of entry filled in |iv| */
size_t niv;
/* How many bytes we still need to receive in the |buf| */
size_t left;
/* How many bytes we still need to receive for current frame */
size_t payloadleft;
nghttp2_inbound_state state;
/* Error code */
/* TODO, remove this. Error code */
int error_code;
uint8_t headbuf[NGHTTP2_FRAME_HEAD_LENGTH];
uint8_t buf[8];
/* How many bytes have been written to |buf| */
uint8_t buflen;
} nghttp2_inbound_frame;
typedef enum {
@ -131,9 +129,6 @@ struct nghttp2_session {
/* Sequence number of outbound frame to maintain the order of
enqueue if priority is equal. */
int64_t next_seq;
/* Buffer used to store inflated name/value pairs in wire format
temporarily on pack/unpack. */
uint8_t *nvbuf;
void *user_data;
/* In-flight SETTINGS values. NULL does not necessarily mean there
is no in-flight SETTINGS. */
@ -358,6 +353,15 @@ int nghttp2_session_close_stream_if_shut_rdwr(nghttp2_session *session,
nghttp2_stream *stream);
int nghttp2_session_end_request_headers_received(nghttp2_session *session,
nghttp2_frame *frame);
int nghttp2_session_end_response_headers_received(nghttp2_session *session,
nghttp2_frame *frame);
int nghttp2_session_end_headers_received(nghttp2_session *session,
nghttp2_frame *frame);
int nghttp2_session_on_request_headers_received(nghttp2_session *session,
nghttp2_frame *frame);

View File

@ -565,8 +565,8 @@ void test_nghttp2_session_recv_data(void)
hd.stream_id = 1;
nghttp2_frame_pack_frame_hd(data, &hd);
/* stream 1 is not opened, so it must be responded with RST_STREAM,
well actually, this is not mandated by the spec */
/* stream 1 is not opened, so it must be responded with connection
error. This is not mandated by the spec */
ud.data_chunk_recv_cb_called = 0;
ud.data_recv_cb_called = 0;
rv = nghttp2_session_mem_recv(session, data, 8+4096);
@ -575,11 +575,7 @@ void test_nghttp2_session_recv_data(void)
CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
CU_ASSERT(0 == ud.data_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session);
/* DATA against nonexistent stream is ignored for now */
CU_ASSERT(NULL == item);
/* CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(item)); */
/* CU_ASSERT(0 == nghttp2_session_send(session)); */
/* Create stream 1 with CLOSING state. DATA is ignored. */
stream = nghttp2_session_open_stream(session, 1,
@ -729,9 +725,9 @@ void test_nghttp2_session_continue(void)
user_data.header_cb_called = 0;
user_data.end_headers_cb_called = 0;
rv = nghttp2_session_mem_recv(session, bufp, buflen);
CU_ASSERT(rv == framelen1);
bufp += framelen1;
buflen -= framelen1;
bufp += rv;
buflen -= rv;
recv_frame = user_data.frame;
CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
@ -746,7 +742,9 @@ void test_nghttp2_session_continue(void)
user_data.header_cb_called = 0;
user_data.end_headers_cb_called = 0;
rv = nghttp2_session_mem_recv(session, bufp, buflen);
CU_ASSERT(0 == rv);
bufp += rv;
buflen -= rv;
CU_ASSERT(1 == user_data.header_cb_called);
CU_ASSERT(0 == user_data.end_headers_cb_called);
@ -757,9 +755,9 @@ void test_nghttp2_session_continue(void)
user_data.header_cb_called = 0;
user_data.end_headers_cb_called = 0;
rv = nghttp2_session_mem_recv(session, bufp, buflen);
CU_ASSERT(rv == framelen2);
bufp += framelen2;
buflen -= framelen2;
bufp += rv;
buflen -= rv;
recv_frame = user_data.frame;
CU_ASSERT(NGHTTP2_HEADERS == recv_frame->hd.type);
@ -774,7 +772,9 @@ void test_nghttp2_session_continue(void)
user_data.header_cb_called = 0;
user_data.end_headers_cb_called = 0;
rv = nghttp2_session_mem_recv(session, bufp, buflen);
CU_ASSERT(0 == rv);
bufp += rv;
buflen -= rv;
CU_ASSERT(1 == user_data.header_cb_called);
CU_ASSERT(0 == user_data.end_headers_cb_called);
@ -785,7 +785,9 @@ void test_nghttp2_session_continue(void)
user_data.header_cb_called = 0;
user_data.end_headers_cb_called = 0;
rv = nghttp2_session_mem_recv(session, bufp, buflen);
CU_ASSERT(0 == rv);
bufp += rv;
buflen -= rv;
CU_ASSERT(0 == user_data.header_cb_called);
CU_ASSERT(1 == user_data.end_headers_cb_called);
@ -906,7 +908,8 @@ void test_nghttp2_session_on_request_headers_received(void)
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3, NGHTTP2_PRI_DEFAULT, NULL, 0);
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
CU_ASSERT(0 == (session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND));
@ -920,7 +923,8 @@ void test_nghttp2_session_on_request_headers_received(void)
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3, NGHTTP2_PRI_DEFAULT, NULL, 0);
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
CU_ASSERT(session->goaway_flags & NGHTTP2_GOAWAY_FAIL_ON_SEND);
@ -1008,7 +1012,6 @@ void test_nghttp2_session_on_headers_received(void)
CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
CU_ASSERT(2 == user_data.frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
/* Check to see when NGHTTP2_STREAM_CLOSING, incoming HEADERS is
discarded. */
@ -1017,7 +1020,8 @@ void test_nghttp2_session_on_headers_received(void)
NGHTTP2_STREAM_CLOSING, NULL);
frame.hd.stream_id = 3;
frame.hd.flags = NGHTTP2_FLAG_END_HEADERS;
CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_headers_received(session, &frame, stream));
/* See no counters are updated */
CU_ASSERT(2 == user_data.frame_recv_cb_called);
CU_ASSERT(0 == user_data.invalid_frame_recv_cb_called);
@ -1034,9 +1038,12 @@ void test_nghttp2_session_on_headers_received(void)
CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
CU_ASSERT(3 == user_data.frame_recv_cb_called);
CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
CU_ASSERT(stream->shut_flags & NGHTTP2_SHUT_RD);
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_RD);
/* Further reception of HEADERS is subject to stream error */
CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_headers_received(session, &frame, stream));
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
nghttp2_frame_headers_free(&frame.headers);
@ -1080,7 +1087,8 @@ void test_nghttp2_session_on_push_response_headers_received(void)
NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_RESERVED, NULL);
frame.hd.stream_id = 4;
CU_ASSERT(0 == nghttp2_session_on_push_response_headers_received
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_push_response_headers_received
(session, &frame, stream));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(item));
@ -1320,7 +1328,8 @@ void test_nghttp2_session_on_push_promise_received(void)
user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(0 == user_data.frame_recv_cb_called);
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
@ -1339,7 +1348,8 @@ void test_nghttp2_session_on_push_promise_received(void)
user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(0 == user_data.frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 6));
@ -1355,7 +1365,8 @@ void test_nghttp2_session_on_push_promise_received(void)
user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(0 == user_data.frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
@ -1370,7 +1381,8 @@ void test_nghttp2_session_on_push_promise_received(void)
user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(0 == user_data.frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
@ -1384,7 +1396,8 @@ void test_nghttp2_session_on_push_promise_received(void)
user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(0 == user_data.frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 10));
@ -1406,7 +1419,8 @@ void test_nghttp2_session_on_push_promise_received(void)
user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(0 == user_data.frame_recv_cb_called);
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
@ -1430,7 +1444,8 @@ void test_nghttp2_session_on_push_promise_received(void)
user_data.frame_recv_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_push_promise_received(session, &frame));
CU_ASSERT(0 == user_data.frame_recv_cb_called);
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
@ -1619,17 +1634,6 @@ void test_nghttp2_session_on_data_received(void)
/* CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(top)); */
/* CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(top)->rst_stream.error_code); */
/* Receiving DATA against the reserved stream is subject to
connection error */
stream = nghttp2_session_open_stream(session, 6, NGHTTP2_STREAM_FLAG_NONE,
NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_RESERVED, NULL);
CU_ASSERT(0 == nghttp2_session_on_data_received(session, 4096,
NGHTTP2_FLAG_NONE, 6));
top = nghttp2_session_get_ob_pq_top(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(top));
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(top)->goaway.error_code);
nghttp2_session_del(session);
}
@ -2990,7 +2994,8 @@ void test_nghttp2_session_max_concurrent_streams(void)
NGHTTP2_PRI_DEFAULT, NULL, 0);
session->local_settings[NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS] = 1;
CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_request_headers_received(session, &frame));
item = nghttp2_session_get_ob_pq_top(session);
CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(item));
@ -3466,7 +3471,6 @@ void test_nghttp2_session_on_request_recv_callback(void)
nghttp2_session_callbacks callbacks;
my_user_data user_data;
nghttp2_frame frame;
nghttp2_stream *stream;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_request_recv_callback = on_request_recv_callback;
@ -3475,31 +3479,35 @@ void test_nghttp2_session_on_request_recv_callback(void)
nghttp2_session_server_new(&session, &callbacks, &user_data);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
1, NGHTTP2_PRI_DEFAULT, NULL, 0);
CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(0 == nghttp2_session_end_request_headers_received(session, &frame));
CU_ASSERT(0 == user_data.stream_id);
/* nghttp2_session_end_* does not open stream, so we do it here */
nghttp2_session_open_stream(session, 3, NGHTTP2_STREAM_FLAG_NONE,
NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_OPENING, NULL);
frame.hd.stream_id = 3;
frame.hd.flags |= NGHTTP2_FLAG_END_STREAM;
CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
CU_ASSERT(0 == nghttp2_session_end_request_headers_received(session, &frame));
CU_ASSERT(3 == user_data.stream_id);
nghttp2_frame_headers_free(&frame.headers);
user_data.stream_id = 0;
stream = nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
nghttp2_session_open_stream(session, 5, NGHTTP2_STREAM_FLAG_NONE,
NGHTTP2_PRI_DEFAULT,
NGHTTP2_STREAM_OPENING, NULL);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
5, NGHTTP2_PRI_DEFAULT, NULL, 0);
CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
CU_ASSERT(0 == nghttp2_session_end_headers_received(session, &frame));
CU_ASSERT(0 == user_data.stream_id);
frame.headers.hd.flags |= NGHTTP2_FLAG_END_STREAM;
CU_ASSERT(0 == nghttp2_session_on_headers_received(session, &frame, stream));
CU_ASSERT(0 == nghttp2_session_end_headers_received(session, &frame));
CU_ASSERT(5 == user_data.stream_id);
nghttp2_frame_headers_free(&frame.headers);