Unify DATA and other frames in nghttp2_outbound_item and save malloc()

This commit is contained in:
Tatsuhiro Tsujikawa 2014-10-03 00:59:44 +09:00
parent 7e6019aef1
commit 1d138accb9
10 changed files with 521 additions and 482 deletions

View File

@ -2636,6 +2636,8 @@ int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
* DATA has been already submitted and not fully processed yet.
* :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`
* The |stream_id| is 0.
* :enum:`NGHTTP2_ERR_STREAM_CLOSED`
* The stream was alreay closed; or the |stream_id| is invalid.
*/
int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
int32_t stream_id,

View File

@ -33,11 +33,6 @@
#include "nghttp2_net.h"
#include "nghttp2_priority_spec.h"
int nghttp2_frame_is_data_frame(uint8_t *head)
{
return head[2] == 0;
}
void nghttp2_frame_pack_frame_hd(uint8_t* buf, const nghttp2_frame_hd *hd)
{
nghttp2_put_uint32be(&buf[0], (uint32_t)(hd->length << 8));
@ -234,35 +229,20 @@ void nghttp2_frame_altsvc_free(nghttp2_extension *frame)
free(altsvc->protocol_id);
}
void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata)
{
frame->hd = pdata->hd;
frame->padlen = pdata->padlen;
/* flags may have NGHTTP2_FLAG_END_STREAM even if the sent chunk is
not the end of the stream */
if(!pdata->eof) {
frame->hd.flags &= ~NGHTTP2_FLAG_END_STREAM;
}
}
size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen)
{
return padlen - ((frame->hd.flags & NGHTTP2_FLAG_PADDED) > 0);
}
void nghttp2_frame_private_data_init(nghttp2_private_data *frame,
uint8_t flags,
int32_t stream_id,
const nghttp2_data_provider *data_prd)
void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
int32_t stream_id)
{
/* At this moment, the length of DATA frame is unknown */
nghttp2_frame_hd_init(&frame->hd, 0, NGHTTP2_DATA, flags, stream_id);
frame->data_prd = *data_prd;
frame->padlen = 0;
frame->eof = 0;
}
void nghttp2_frame_private_data_free(nghttp2_private_data *frame)
void nghttp2_frame_data_free(nghttp2_data *frame)
{}
size_t nghttp2_frame_priority_len(uint8_t flags)

View File

@ -83,46 +83,11 @@
/* Maximum length of padding in bytes. */
#define NGHTTP2_MAX_PADLEN 256
/* Category of frames. */
typedef enum {
/* non-DATA frame */
NGHTTP2_CAT_CTRL,
/* DATA frame */
NGHTTP2_CAT_DATA
} nghttp2_frame_category;
/* Union of extension frame payload */
typedef union {
nghttp2_ext_altsvc altsvc;
} nghttp2_ext_frame_payload;
/**
* @struct
*
* The DATA frame used in the library privately. It has the following
* members:
*/
typedef struct {
nghttp2_frame_hd hd;
/**
* The data to be sent for this DATA frame.
*/
nghttp2_data_provider data_prd;
/**
* The number of bytes added as padding. This includes Pad Length
* field (1 byte).
*/
size_t padlen;
/**
* The flag to indicate whether EOF was reached or not. Initially
* |eof| is 0. It becomes 1 after all data were read. This is used
* exclusively by nghttp2 library and not in the spec.
*/
uint8_t eof;
} nghttp2_private_data;
int nghttp2_frame_is_data_frame(uint8_t *head);
void nghttp2_frame_pack_frame_hd(uint8_t *buf, const nghttp2_frame_hd *hd);
void nghttp2_frame_unpack_frame_hd(nghttp2_frame_hd *hd, const uint8_t* buf);
@ -559,8 +524,6 @@ void nghttp2_frame_altsvc_init(nghttp2_extension *frame, int32_t stream_id,
*/
void nghttp2_frame_altsvc_free(nghttp2_extension *frame);
void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata);
/*
* Returns the number of padding bytes after payload. The total
* padding length is given in the |padlen|. The returned value does
@ -568,12 +531,10 @@ void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata);
*/
size_t nghttp2_frame_trail_padlen(nghttp2_frame *frame, size_t padlen);
void nghttp2_frame_private_data_init(nghttp2_private_data *frame,
uint8_t flags,
int32_t stream_id,
const nghttp2_data_provider *data_prd);
void nghttp2_frame_data_init(nghttp2_data *frame, uint8_t flags,
int32_t stream_id);
void nghttp2_frame_private_data_free(nghttp2_private_data *frame);
void nghttp2_frame_data_free(nghttp2_data *frame);
/*
* Makes copy of |iv| and return the copy. The |niv| is the number of

View File

@ -28,13 +28,18 @@
void nghttp2_outbound_item_free(nghttp2_outbound_item *item)
{
nghttp2_frame *frame;
if(item == NULL) {
return;
}
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
nghttp2_frame *frame;
frame = nghttp2_outbound_item_get_ctrl_frame(item);
frame = &item->frame;
switch(frame->hd.type) {
case NGHTTP2_DATA:
nghttp2_frame_data_free(&frame->data);
break;
case NGHTTP2_HEADERS:
nghttp2_frame_headers_free(&frame->headers);
break;
@ -64,13 +69,4 @@ void nghttp2_outbound_item_free(nghttp2_outbound_item *item)
free(frame->ext.payload);
break;
}
} else if(item->frame_cat == NGHTTP2_CAT_DATA) {
nghttp2_private_data *data_frame;
data_frame = nghttp2_outbound_item_get_data_frame(item);
nghttp2_frame_private_data_free(data_frame);
} else {
/* Unreachable */
assert(0);
}
free(item->frame);
}

View File

@ -45,21 +45,40 @@ typedef struct {
void *stream_user_data;
} nghttp2_headers_aux_data;
/* struct used for DATA frame */
typedef struct {
/**
* The data to be sent for this DATA frame.
*/
nghttp2_data_provider data_prd;
/**
* The flags of DATA frame. We use separate flags here and
* nghttp2_data frame. The latter contains flags actually sent to
* peer. This |flags| may contain NGHTTP2_FLAG_END_STREAM and only
* when |eof| becomes nonzero, flags in nghttp2_data has
* NGHTTP2_FLAG_END_STREAM set.
*/
uint8_t flags;
/**
* The flag to indicate whether EOF was reached or not. Initially
* |eof| is 0. It becomes 1 after all data were read.
*/
uint8_t eof;
} nghttp2_data_aux_data;
/* Additional data which cannot be stored in nghttp2_frame struct */
typedef union {
nghttp2_data_aux_data data;
nghttp2_headers_aux_data headers;
} nghttp2_aux_data;
typedef struct {
nghttp2_frame frame;
nghttp2_aux_data aux_data;
int64_t seq;
/* Reset count of weight. See comment for last_cycle in
nghttp2_session.h */
uint64_t cycle;
void *frame;
/* Type of |frame|. NGHTTP2_CTRL: nghttp2_frame*, NGHTTP2_DATA:
nghttp2_private_data* */
nghttp2_frame_category frame_cat;
/* The priority used in priority comparion. Larger is served
ealier. */
int32_t weight;
@ -73,11 +92,4 @@ typedef struct {
*/
void nghttp2_outbound_item_free(nghttp2_outbound_item *item);
/* Macros to cast nghttp2_outbound_item.frame to the proper type. */
#define nghttp2_outbound_item_get_ctrl_frame(ITEM) ((nghttp2_frame*)ITEM->frame)
#define nghttp2_outbound_item_get_ctrl_frame_type(ITEM) \
(((nghttp2_frame*)ITEM->frame)->hd.type)
#define nghttp2_outbound_item_get_data_frame(ITEM) \
((nghttp2_private_data*)ITEM->frame)
#endif /* NGHTTP2_OUTBOUND_ITEM_H */

View File

@ -637,43 +637,32 @@ int nghttp2_session_reprioritize_stream
return 0;
}
int nghttp2_session_add_frame(nghttp2_session *session,
nghttp2_frame_category frame_cat,
void *abs_frame,
nghttp2_aux_data *aux_data)
void nghttp2_session_outbound_item_init(nghttp2_session* session,
nghttp2_outbound_item *item)
{
item->seq = session->next_seq++;
/* We use cycle for DATA only */
item->cycle = 0;
item->weight = NGHTTP2_OB_EX_WEIGHT;
item->queued = 0;
memset(&item->aux_data, 0, sizeof(nghttp2_aux_data));
}
int nghttp2_session_add_item(nghttp2_session *session,
nghttp2_outbound_item *item)
{
/* TODO Return error if stream is not found for the frame requiring
stream presence. */
int rv = 0;
nghttp2_outbound_item *item;
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
item->frame_cat = frame_cat;
item->frame = abs_frame;
if(aux_data) {
item->aux_data = *aux_data;
} else {
memset(&item->aux_data, 0, sizeof(item->aux_data));
}
item->seq = session->next_seq++;
/* We use cycle for DATA only */
item->cycle = 0;
item->weight = NGHTTP2_OB_EX_WEIGHT;
item->queued = 0;
if(frame_cat == NGHTTP2_CAT_CTRL) {
nghttp2_frame *frame = (nghttp2_frame*)abs_frame;
nghttp2_stream *stream;
nghttp2_frame *frame;
frame = &item->frame;
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(frame->hd.type != NGHTTP2_DATA) {
switch(frame->hd.type) {
case NGHTTP2_RST_STREAM:
if(stream) {
@ -714,32 +703,30 @@ int nghttp2_session_add_frame(nghttp2_session *session,
rv = nghttp2_pq_push(&session->ob_pq, item);
}
if(rv != 0) {
return rv;
}
item->queued = 1;
} else if(frame_cat == NGHTTP2_CAT_DATA) {
nghttp2_private_data *data_frame = (nghttp2_private_data*)abs_frame;
nghttp2_stream *stream;
return 0;
}
if(!stream) {
return NGHTTP2_ERR_STREAM_CLOSED;
}
stream = nghttp2_session_get_stream(session, data_frame->hd.stream_id);
if(stream) {
if(stream->data_item) {
rv = NGHTTP2_ERR_DATA_EXIST;
} else {
return NGHTTP2_ERR_DATA_EXIST;
}
item->weight = stream->effective_weight;
item->cycle = session->last_cycle;
rv = nghttp2_stream_attach_data(stream, item, &session->ob_da_pq,
session->last_cycle);
}
}
} else {
/* Unreachable */
assert(0);
}
if(rv != 0) {
free(item);
return rv;
}
@ -751,6 +738,7 @@ int nghttp2_session_add_rst_stream(nghttp2_session *session,
uint32_t error_code)
{
int rv;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_stream *stream;
@ -759,15 +747,20 @@ int nghttp2_session_add_rst_stream(nghttp2_session *session,
return 0;
}
frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) {
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_rst_stream_init(&frame->rst_stream, stream_id, error_code);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_rst_stream_free(&frame->rst_stream);
free(frame);
free(item);
return rv;
}
return 0;
@ -1543,10 +1536,11 @@ static int session_prep_frame(nghttp2_session *session,
{
int framerv = 0;
int rv;
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
nghttp2_frame *frame;
frame = nghttp2_outbound_item_get_ctrl_frame(item);
frame = &item->frame;
if(frame->hd.type != NGHTTP2_DATA) {
switch(frame->hd.type) {
case NGHTTP2_HEADERS: {
nghttp2_headers_aux_data *aux_data;
@ -1770,19 +1764,17 @@ static int session_prep_frame(nghttp2_session *session,
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
return 0;
} else if(item->frame_cat == NGHTTP2_CAT_DATA) {
} else {
size_t next_readmax;
nghttp2_stream *stream;
nghttp2_private_data *data_frame;
data_frame = nghttp2_outbound_item_get_data_frame(item);
stream = nghttp2_session_get_stream(session, data_frame->hd.stream_id);
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(stream) {
assert(stream->data_item == item);
}
rv = nghttp2_session_predicate_data_send(session, data_frame->hd.stream_id);
rv = nghttp2_session_predicate_data_send(session, frame->hd.stream_id);
if(rv != 0) {
int rv2;
@ -1819,10 +1811,12 @@ static int session_prep_frame(nghttp2_session *session,
active_outbound_item_reset(&session->aob);
return NGHTTP2_ERR_DEFERRED;
}
framerv = nghttp2_session_pack_data(session,
&session->aob.framebufs,
next_readmax,
data_frame);
frame,
&item->aux_data.data);
if(framerv == NGHTTP2_ERR_DEFERRED) {
rv = nghttp2_stream_defer_data(stream, NGHTTP2_STREAM_FLAG_DEFERRED_USER,
&session->ob_da_pq, session->last_cycle);
@ -1843,7 +1837,7 @@ static int session_prep_frame(nghttp2_session *session,
return rv;
}
rv = nghttp2_session_add_rst_stream(session, data_frame->hd.stream_id,
rv = nghttp2_session_add_rst_stream(session, frame->hd.stream_id,
NGHTTP2_INTERNAL_ERROR);
if(rv != 0) {
return rv;
@ -1861,10 +1855,6 @@ static int session_prep_frame(nghttp2_session *session,
return framerv;
}
return 0;
} else {
/* Unreachable */
assert(0);
return 0;
}
}
@ -2058,11 +2048,11 @@ static int session_after_frame_sent(nghttp2_session *session)
nghttp2_active_outbound_item *aob = &session->aob;
nghttp2_outbound_item *item = aob->item;
nghttp2_bufs *framebufs = &aob->framebufs;
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
nghttp2_frame *frame;
frame = nghttp2_outbound_item_get_ctrl_frame(item);
frame = &item->frame;
if(frame->hd.type != NGHTTP2_DATA) {
if(frame->hd.type == NGHTTP2_HEADERS ||
frame->hd.type == NGHTTP2_PUSH_PROMISE) {
@ -2178,22 +2168,23 @@ static int session_after_frame_sent(nghttp2_session *session)
}
active_outbound_item_reset(&session->aob);
return 0;
} else if(item->frame_cat == NGHTTP2_CAT_DATA) {
nghttp2_private_data *data_frame;
} else {
nghttp2_outbound_item* next_item;
nghttp2_stream *stream;
nghttp2_data_aux_data *aux_data;
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
stream = nghttp2_session_get_stream(session, data_frame->hd.stream_id);
aux_data = &item->aux_data.data;
stream = nghttp2_session_get_stream(session, 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
exceed the window */
session->remote_window_size -= data_frame->hd.length;
session->remote_window_size -= frame->hd.length;
if(stream) {
stream->remote_window_size -= data_frame->hd.length;
stream->remote_window_size -= frame->hd.length;
}
if(stream && data_frame->eof) {
if(stream && aux_data->eof) {
rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle);
@ -2205,15 +2196,14 @@ static int session_after_frame_sent(nghttp2_session *session)
nghttp2_stream_detach_data(), so that application can issue
nghttp2_submit_data() in the callback. */
if(session->callbacks.on_frame_send_callback) {
nghttp2_frame public_data_frame;
nghttp2_frame_data_init(&public_data_frame.data, data_frame);
rv = session_call_on_frame_send(session, &public_data_frame);
rv = session_call_on_frame_send(session, frame);
if(nghttp2_is_fatal(rv)) {
return rv;
}
}
if(data_frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
int stream_closed;
stream_closed =
@ -2231,9 +2221,8 @@ static int session_after_frame_sent(nghttp2_session *session)
}
}
} else if(session->callbacks.on_frame_send_callback) {
nghttp2_frame public_data_frame;
nghttp2_frame_data_init(&public_data_frame.data, data_frame);
rv = session_call_on_frame_send(session, &public_data_frame);
rv = session_call_on_frame_send(session, frame);
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -2244,7 +2233,7 @@ static int session_after_frame_sent(nghttp2_session *session)
application may issue nghttp2_submit_data() in
on_frame_send_callback, which attach data to stream. We don't
want to detach it. */
if(data_frame->eof) {
if(aux_data->eof) {
active_outbound_item_reset(aob);
return 0;
@ -2253,7 +2242,7 @@ static int session_after_frame_sent(nghttp2_session *session)
/* If session is closed or RST_STREAM was queued, we won't send
further data. */
if(nghttp2_session_predicate_data_send(session,
data_frame->hd.stream_id) != 0) {
frame->hd.stream_id) != 0) {
if(stream) {
rv = nghttp2_stream_detach_data(stream, &session->ob_da_pq,
session->last_cycle);
@ -2318,7 +2307,7 @@ static int session_after_frame_sent(nghttp2_session *session)
nghttp2_bufs_reset(framebufs);
rv = nghttp2_session_pack_data(session, framebufs, next_readmax,
data_frame);
frame, aux_data);
if(nghttp2_is_fatal(rv)) {
return rv;
}
@ -2341,7 +2330,7 @@ static int session_after_frame_sent(nghttp2_session *session)
stream. We don't return
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE intentionally. */
rv = nghttp2_session_add_rst_stream(session,
data_frame->hd.stream_id,
frame->hd.stream_id,
NGHTTP2_INTERNAL_ERROR);
if(nghttp2_is_fatal(rv)) {
@ -2404,13 +2393,12 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
return 0;
}
if(item->frame_cat == NGHTTP2_CAT_DATA) {
nghttp2_private_data *data;
if(item->frame.hd.type == NGHTTP2_DATA) {
nghttp2_frame *frame;
nghttp2_stream *stream;
data = nghttp2_outbound_item_get_data_frame(item);
stream = nghttp2_session_get_stream(session, data->hd.stream_id);
frame = &item->frame;
stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
if(stream && stream->dpri != NGHTTP2_STREAM_DPRI_TOP) {
/* We have DATA with higher priority in queue within the
@ -2429,13 +2417,13 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
nghttp2_strerror(rv)));
/* TODO If the error comes from compressor, the connection
must be closed. */
if(item->frame_cat == NGHTTP2_CAT_CTRL &&
if(item->frame.hd.type != NGHTTP2_DATA &&
session->callbacks.on_frame_not_send_callback &&
is_non_fatal(rv)) {
nghttp2_frame *frame = &item->frame;
/* The library is responsible for the transmission of
WINDOW_UPDATE frame, so we don't call error callback for
it. */
nghttp2_frame *frame = nghttp2_outbound_item_get_ctrl_frame(item);
if(frame->hd.type != NGHTTP2_WINDOW_UPDATE) {
if(session->callbacks.on_frame_not_send_callback
(session, frame, rv, session->user_data) != 0) {
@ -2467,10 +2455,10 @@ ssize_t nghttp2_session_mem_send(nghttp2_session *session,
nghttp2_bufs_rewind(framebufs);
if(item->frame_cat == NGHTTP2_CAT_CTRL) {
if(item->frame.hd.type != NGHTTP2_DATA) {
nghttp2_frame *frame;
frame = nghttp2_outbound_item_get_ctrl_frame(item);
frame = &item->frame;
DEBUGF(fprintf(stderr,
"send: next frame: payloadlen=%zu, type=%u, "
@ -5548,16 +5536,25 @@ int nghttp2_session_add_ping(nghttp2_session *session, uint8_t flags,
const uint8_t *opaque_data)
{
int rv;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) {
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_ping_init(&frame->ping, flags, opaque_data);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_ping_free(&frame->ping);
free(frame);
free(item);
return rv;
}
return 0;
@ -5570,8 +5567,10 @@ int nghttp2_session_add_goaway(nghttp2_session *session,
size_t opaque_data_len)
{
int rv;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
uint8_t *opaque_data_copy = NULL;
if(opaque_data_len) {
if(opaque_data_len + 8 > NGHTTP2_MAX_PAYLOADLEN) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
@ -5582,17 +5581,24 @@ int nghttp2_session_add_goaway(nghttp2_session *session,
}
memcpy(opaque_data_copy, opaque_data, opaque_data_len);
}
frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) {
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
free(opaque_data_copy);
return NGHTTP2_ERR_NOMEM;
}
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_goaway_init(&frame->goaway, last_stream_id, error_code,
opaque_data_copy, opaque_data_len);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_goaway_free(&frame->goaway);
free(frame);
free(item);
return rv;
}
return 0;
@ -5603,17 +5609,26 @@ int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags,
int32_t window_size_increment)
{
int rv;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) {
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_window_update_init(&frame->window_update, flags,
stream_id, window_size_increment);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_window_update_free(&frame->window_update);
free(frame);
free(item);
return rv;
}
return 0;
@ -5622,6 +5637,7 @@ int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags,
int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
const nghttp2_settings_entry *iv, size_t niv)
{
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_settings_entry *iv_copy;
size_t i;
@ -5638,15 +5654,16 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
if(!nghttp2_iv_check(iv, niv)) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) {
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
if(niv > 0) {
iv_copy = nghttp2_frame_iv_copy(iv, niv);
if(iv_copy == NULL) {
free(frame);
free(item);
return NGHTTP2_ERR_NOMEM;
}
} else {
@ -5659,7 +5676,7 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
if(session->inflight_iv == NULL) {
free(iv_copy);
free(frame);
free(item);
return NGHTTP2_ERR_NOMEM;
}
} else {
@ -5669,8 +5686,12 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
session->inflight_niv = niv;
}
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_settings_init(&frame->settings, flags, iv_copy, niv);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
/* The only expected error is fatal one */
assert(nghttp2_is_fatal(rv));
@ -5682,7 +5703,7 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
}
nghttp2_frame_settings_free(&frame->settings);
free(frame);
free(item);
return rv;
}
@ -5702,16 +5723,13 @@ int nghttp2_session_add_settings(nghttp2_session *session, uint8_t flags,
int nghttp2_session_pack_data(nghttp2_session *session,
nghttp2_bufs *bufs,
size_t datamax,
nghttp2_private_data *frame)
nghttp2_frame *frame,
nghttp2_data_aux_data *aux_data)
{
int rv;
uint32_t data_flags;
uint8_t flags;
ssize_t payloadlen;
ssize_t padded_payloadlen;
size_t padlen;
nghttp2_frame data_frame;
nghttp2_frame_hd hd;
nghttp2_buf *buf;
size_t max_payloadlen;
@ -5772,9 +5790,9 @@ int nghttp2_session_pack_data(nghttp2_session *session,
assert(nghttp2_buf_avail(buf) >= (ssize_t)datamax);
data_flags = NGHTTP2_DATA_FLAG_NONE;
payloadlen = frame->data_prd.read_callback
payloadlen = aux_data->data_prd.read_callback
(session, frame->hd.stream_id, buf->pos, datamax,
&data_flags, &frame->data_prd.source, session->user_data);
&data_flags, &aux_data->data_prd.source, session->user_data);
if(payloadlen == NGHTTP2_ERR_DEFERRED ||
payloadlen == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
@ -5794,48 +5812,36 @@ int nghttp2_session_pack_data(nghttp2_session *session,
/* Clear flags, because this may contain previous flags of previous
DATA */
frame->hd.flags &= NGHTTP2_FLAG_END_STREAM;
flags = NGHTTP2_FLAG_NONE;
frame->hd.flags = NGHTTP2_FLAG_NONE;
if(data_flags & NGHTTP2_DATA_FLAG_EOF) {
frame->eof = 1;
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
flags |= NGHTTP2_FLAG_END_STREAM;
aux_data->eof = 1;
if(aux_data->flags & NGHTTP2_FLAG_END_STREAM) {
frame->hd.flags |= NGHTTP2_FLAG_END_STREAM;
}
}
/* The primary reason of data_frame is pass to the user callback */
nghttp2_frame_hd_init(&data_frame.hd, payloadlen, NGHTTP2_DATA, flags,
frame->hd.stream_id);
data_frame.data.padlen = 0;
frame->hd.length = payloadlen;
frame->data.padlen = 0;
max_payloadlen = nghttp2_min(datamax,
data_frame.hd.length + NGHTTP2_MAX_PADLEN);
max_payloadlen = nghttp2_min(datamax, frame->hd.length + NGHTTP2_MAX_PADLEN);
padded_payloadlen = session_call_select_padding(session, &data_frame,
max_payloadlen);
padded_payloadlen = session_call_select_padding
(session, frame, max_payloadlen);
if(nghttp2_is_fatal((int)padded_payloadlen)) {
return (int)padded_payloadlen;
}
padlen = padded_payloadlen - payloadlen;
frame->data.padlen = padded_payloadlen - payloadlen;
hd = frame->hd;
hd.length = payloadlen;
hd.flags = flags;
nghttp2_frame_pack_frame_hd(buf->pos, &frame->hd);
nghttp2_frame_pack_frame_hd(buf->pos, &hd);
rv = nghttp2_frame_add_pad(bufs, &hd, padlen);
rv = nghttp2_frame_add_pad(bufs, &frame->hd, frame->data.padlen);
if(rv != 0) {
return rv;
}
frame->hd.length = hd.length;
frame->hd.flags |= hd.flags;
frame->padlen = padlen;
return 0;
}

View File

@ -259,26 +259,28 @@ int nghttp2_session_is_my_stream_id(nghttp2_session *session,
int32_t stream_id);
/*
* Adds frame |frame| to the outbound queue in |session|. The
* |frame_cat| must be either NGHTTP2_CTRL or NGHTTP2_DATA. If the
* |frame_cat| is NGHTTP2_CTRL, the |frame| must be a pointer to
* nghttp2_frame. If the |frame_cat| is NGHTTP2_DATA, it must be a
* pointer to nghttp2_private_data. |aux_data| specifies additional
* data. Which union member is filled depends on the type of the
* frame. Currently, HEADERS and PUSH_PROMISE frames use headers
* member. When this function succeeds, it takes ownership of
* |frame|. So caller must not free it on success. The content of
* |aux_data| is just copied.
* Initializes |item|. No memory allocation is done in this function.
* Don't call nghttp2_outbound_item_free() until frame member is
* initialized.
*/
void nghttp2_session_outbound_item_init(nghttp2_session* session,
nghttp2_outbound_item *item);
/*
* Adds |item| to the outbound queue in |session|. When this function
* succeeds, it takes ownership of |item|. So caller must not free it
* on success.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
* NGHTTP2_ERR_STREAM_CLOSED
* Stream already closed (DATA frame only)
*/
int nghttp2_session_add_frame(nghttp2_session *session,
nghttp2_frame_category frame_cat,
void *abs_frame, nghttp2_aux_data *aux_data);
int nghttp2_session_add_item(nghttp2_session *session,
nghttp2_outbound_item *item);
/*
* Adds RST_STREAM frame for the stream |stream_id| with the error
@ -648,13 +650,8 @@ nghttp2_stream* nghttp2_session_get_stream_raw(nghttp2_session *session,
/*
* Packs DATA frame |frame| in wire frame format and stores it in
* |*buf_ptr|. The capacity of |*buf_ptr| is |*buflen_ptr|
* length. This function expands |*buf_ptr| as necessary to store
* given |frame|. It packs header in first 8 bytes starting
* |*bufoff_ptr| offset. The |*bufoff_ptr| is calculated based on
* usage of padding. Remaining bytes are the DATA apyload and are
* filled using |frame->data_prd|. The length of payload is at most
* |datamax| bytes.
* |bufs|. Payload will be read using |aux_data->data_prd|. The
* length of payload is at most |datamax| bytes.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
@ -671,7 +668,8 @@ nghttp2_stream* nghttp2_session_get_stream_raw(nghttp2_session *session,
int nghttp2_session_pack_data(nghttp2_session *session,
nghttp2_bufs *bufs,
size_t datamax,
nghttp2_private_data *frame);
nghttp2_frame *frame,
nghttp2_data_aux_data *aux_data);
/*
* Returns top of outbound frame queue. This function returns NULL if

View File

@ -47,8 +47,8 @@ static int32_t submit_headers_shared
{
int rv;
uint8_t flags_copy;
nghttp2_outbound_item *item = NULL;
nghttp2_frame *frame = NULL;
nghttp2_aux_data aux_data = {{{{0}, 0}, 0}};
nghttp2_headers_category hcat;
if(stream_id == 0) {
@ -56,18 +56,20 @@ static int32_t submit_headers_shared
goto fail;
}
if(data_prd != NULL && data_prd->read_callback != NULL) {
aux_data.headers.data_prd = *data_prd;
}
aux_data.headers.stream_user_data = stream_user_data;
frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) {
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto fail;
}
nghttp2_session_outbound_item_init(session, item);
if(data_prd != NULL && data_prd->read_callback != NULL) {
item->aux_data.headers.data_prd = *data_prd;
}
item->aux_data.headers.stream_user_data = stream_user_data;
flags_copy =
(flags & (NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_PRIORITY)) |
NGHTTP2_FLAG_END_HEADERS;
@ -87,11 +89,12 @@ static int32_t submit_headers_shared
hcat = NGHTTP2_HCAT_HEADERS;
}
frame = &item->frame;
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id,
hcat, pri_spec, nva_copy, nvlen);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, &aux_data);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_headers_free(&frame->headers);
@ -108,7 +111,7 @@ static int32_t submit_headers_shared
/* nghttp2_frame_headers_init() takes ownership of nva_copy. */
nghttp2_nv_array_del(nva_copy);
fail2:
free(frame);
free(item);
return rv;
}
@ -183,6 +186,7 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
const nghttp2_priority_spec *pri_spec)
{
int rv;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_priority_spec copy_pri_spec;
@ -198,19 +202,23 @@ int nghttp2_submit_priority(nghttp2_session *session, uint8_t flags,
adjust_priority_spec_weight(&copy_pri_spec);
frame = malloc(sizeof(nghttp2_frame));
item = malloc(sizeof(nghttp2_outbound_item));
if(frame == NULL) {
if(item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_priority_init(&frame->priority, stream_id, &copy_pri_spec);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_priority_free(&frame->priority);
free(frame);
free(item);
return rv;
}
@ -249,10 +257,10 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
const nghttp2_nv *nva, size_t nvlen,
void *promised_stream_user_data)
{
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_nv *nva_copy;
uint8_t flags_copy;
nghttp2_aux_data aux_data = {{{{0}, 0}, 0}};
int32_t promised_stream_id;
int rv;
@ -264,28 +272,30 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
return NGHTTP2_ERR_PROTO;
}
frame = malloc(sizeof(nghttp2_frame));
if(frame == NULL) {
/* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) {
return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
}
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
aux_data.headers.stream_user_data = promised_stream_user_data;
nghttp2_session_outbound_item_init(session, item);
item->aux_data.headers.stream_user_data = promised_stream_user_data;
frame = &item->frame;
rv = nghttp2_nv_array_copy(&nva_copy, nva, nvlen);
if(rv < 0) {
free(frame);
free(item);
return rv;
}
flags_copy = NGHTTP2_FLAG_END_HEADERS;
/* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) {
free(frame);
return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
}
promised_stream_id = session->next_stream_id;
session->next_stream_id += 2;
@ -293,11 +303,11 @@ int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
stream_id, promised_stream_id,
nva_copy, nvlen);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, &aux_data);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_push_promise_free(&frame->push_promise);
free(frame);
free(item);
return rv;
}
@ -363,6 +373,7 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
int rv;
size_t varlen;
uint8_t *var, *varp;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_ext_altsvc *altsvc;
uint8_t *copy_protocol_id, *copy_host, *copy_origin;
@ -417,25 +428,28 @@ int nghttp2_submit_altsvc(nghttp2_session *session, uint8_t flags,
copy_origin = varp;
}
frame = malloc(sizeof(nghttp2_frame));
item = malloc(sizeof(nghttp2_outbound_item));
if(frame == NULL) {
if(item == NULL) {
rv = NGHTTP2_ERR_NOMEM;
goto frame_alloc_fail;
}
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
frame->ext.payload = altsvc;
nghttp2_frame_altsvc_init(&frame->ext, stream_id, max_age, port,
copy_protocol_id, protocol_id_len,
copy_host, host_len, copy_origin, origin_len);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_altsvc_free(&frame->ext);
free(frame);
free(item);
free(altsvc);
return rv;
@ -512,22 +526,35 @@ int nghttp2_submit_data(nghttp2_session *session, uint8_t flags,
const nghttp2_data_provider *data_prd)
{
int rv;
nghttp2_private_data *data_frame;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_data_aux_data *aux_data;
uint8_t nflags = flags & NGHTTP2_FLAG_END_STREAM;
if(stream_id == 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
data_frame = malloc(sizeof(nghttp2_private_data));
if(data_frame == NULL) {
item = malloc(sizeof(nghttp2_outbound_item));
if(item == NULL) {
return NGHTTP2_ERR_NOMEM;
}
nghttp2_frame_private_data_init(data_frame, nflags, stream_id, data_prd);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_DATA, data_frame, NULL);
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
aux_data = &item->aux_data.data;
aux_data->data_prd = *data_prd;
aux_data->eof = 0;
aux_data->flags = nflags;
/* flags are sent on transmission */
nghttp2_frame_data_init(&frame->data, NGHTTP2_FLAG_NONE, stream_id);
rv = nghttp2_session_add_item(session, item);
if(rv != 0) {
nghttp2_frame_private_data_free(data_frame);
free(data_frame);
nghttp2_frame_data_free(&frame->data);
free(item);
return rv;
}
return 0;

View File

@ -528,8 +528,8 @@ void test_nghttp2_session_recv(void)
CU_ASSERT(0 == user_data.begin_frame_cb_called);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
CU_ASSERT(0 == nghttp2_session_send(session));
nghttp2_bufs_free(&bufs);
@ -685,7 +685,7 @@ void test_nghttp2_session_recv_data(void)
CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
CU_ASSERT(0 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_session_del(session);
@ -733,8 +733,8 @@ void test_nghttp2_session_recv_data(void)
CU_ASSERT(1 == ud.data_chunk_recv_cb_called);
CU_ASSERT(1 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(1 == OB_CTRL(item)->window_update.hd.stream_id);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(1 == item->frame.window_update.hd.stream_id);
CU_ASSERT(0 == nghttp2_session_send(session));
/* Set initial window size to 1MiB, so that we can check connection
@ -749,8 +749,8 @@ void test_nghttp2_session_recv_data(void)
CU_ASSERT(NGHTTP2_FRAME_HDLEN + 4096 == rv);
}
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(0 == OB_CTRL(item)->window_update.hd.stream_id);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(0 == item->frame.window_update.hd.stream_id);
CU_ASSERT(0 == nghttp2_session_send(session));
/* Reception of DATA with stream ID = 0 causes connection error */
@ -768,8 +768,8 @@ void test_nghttp2_session_recv_data(void)
CU_ASSERT(0 == ud.data_chunk_recv_cb_called);
CU_ASSERT(0 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
nghttp2_session_del(session);
}
@ -909,7 +909,7 @@ void test_nghttp2_session_recv_continuation(void)
CU_ASSERT(1 == ud.begin_headers_cb_called);
CU_ASSERT(NGHTTP2_GOAWAY ==
OB_CTRL_TYPE(nghttp2_session_get_next_ob_item(session)));
nghttp2_session_get_next_ob_item(session)->frame.hd.type);
nghttp2_bufs_free(&bufs);
nghttp2_hd_deflate_free(&deflater);
@ -1017,8 +1017,8 @@ void test_nghttp2_session_recv_headers_with_priority(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NULL != item);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(NGHTTP2_FRAME_SIZE_ERROR == item->frame.goaway.error_code);
nghttp2_bufs_reset(&bufs);
@ -1062,8 +1062,8 @@ void test_nghttp2_session_recv_headers_with_priority(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NULL != item);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
nghttp2_bufs_reset(&bufs);
@ -1121,8 +1121,8 @@ void test_nghttp2_session_recv_premature_headers(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NULL != item);
CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == OB_CTRL(item)->rst_stream.error_code);
CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
CU_ASSERT(NGHTTP2_COMPRESSION_ERROR == item->frame.rst_stream.error_code);
nghttp2_bufs_free(&bufs);
nghttp2_hd_deflate_free(&deflater);
@ -1194,7 +1194,7 @@ void test_nghttp2_session_recv_altsvc(void)
CU_ASSERT(0 == ud.frame_recv_cb_called);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_session_del(session);
@ -1220,7 +1220,7 @@ void test_nghttp2_session_recv_altsvc(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_bufs_free(&bufs);
nghttp2_session_del(session);
@ -1292,7 +1292,7 @@ void test_nghttp2_session_recv_unexpected_continuation(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_session_del(session);
}
@ -1497,7 +1497,7 @@ void test_nghttp2_session_recv_too_large_frame_length(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(item != NULL);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_session_del(session);
}
@ -1704,21 +1704,25 @@ void test_nghttp2_session_add_frame(void)
MAKE_NV("url", "/"),
MAKE_NV("version", "HTTP/1.1")
};
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_aux_data aux_data;
nghttp2_nv *nva;
ssize_t nvlen;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = accumulator_send_callback;
memset(&aux_data, 0, sizeof(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));
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nvlen = ARRLEN(nv);
nghttp2_nv_array_copy(&nva, nv, nvlen);
@ -1729,8 +1733,7 @@ void test_nghttp2_session_add_frame(void)
session->next_stream_id += 2;
CU_ASSERT(0 == nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame,
&aux_data));
CU_ASSERT(0 == nghttp2_session_add_item(session, item));
CU_ASSERT(0 == nghttp2_pq_empty(&session->ob_ss_pq));
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(NGHTTP2_HEADERS == acc.buf[3]);
@ -1976,8 +1979,8 @@ void test_nghttp2_session_on_push_response_headers_received(void)
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));
CU_ASSERT(NGHTTP2_REFUSED_STREAM == OB_CTRL(item)->rst_stream.error_code);
CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
CU_ASSERT(1 == session->num_incoming_streams);
CU_ASSERT(0 == nghttp2_session_send(session));
@ -1996,8 +1999,8 @@ void test_nghttp2_session_on_push_response_headers_received(void)
nghttp2_session_on_push_response_headers_received
(session, &frame, stream));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_ENHANCE_YOUR_CALM == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(NGHTTP2_ENHANCE_YOUR_CALM == item->frame.goaway.error_code);
CU_ASSERT(1 == session->num_incoming_streams);
nghttp2_frame_headers_free(&frame.headers);
@ -2098,7 +2101,7 @@ void test_nghttp2_session_on_priority_received(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_frame_priority_free(&frame.priority);
nghttp2_session_del(session);
@ -2210,7 +2213,7 @@ void test_nghttp2_session_on_settings_received(void)
CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(item != NULL);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
session->inflight_iv = NULL;
session->inflight_niv = -1;
@ -2225,7 +2228,7 @@ void test_nghttp2_session_on_settings_received(void)
CU_ASSERT(0 == nghttp2_session_on_settings_received(session, &frame, 0));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(item != NULL);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_frame_settings_free(&frame.settings);
nghttp2_session_del(session);
@ -2272,7 +2275,7 @@ void test_nghttp2_session_on_settings_received(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(item != NULL);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
nghttp2_frame_settings_free(&frame.settings);
nghttp2_session_del(session);
@ -2327,9 +2330,9 @@ void test_nghttp2_session_on_push_promise_received(void)
CU_ASSERT(1 == user_data.invalid_frame_recv_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 4));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(4 == OB_CTRL(item)->hd.stream_id);
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->rst_stream.error_code);
CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
CU_ASSERT(4 == item->frame.hd.stream_id);
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.rst_stream.error_code);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(4 == session->last_recv_stream_id);
@ -2346,9 +2349,9 @@ void test_nghttp2_session_on_push_promise_received(void)
CU_ASSERT(0 == user_data.begin_headers_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 6));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(6 == OB_CTRL(item)->hd.stream_id);
CU_ASSERT(NGHTTP2_REFUSED_STREAM == OB_CTRL(item)->rst_stream.error_code);
CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
CU_ASSERT(6 == item->frame.hd.stream_id);
CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
CU_ASSERT(0 == nghttp2_session_send(session));
/* Attempt to PUSH_PROMISE against non-existent stream */
@ -2363,9 +2366,9 @@ void test_nghttp2_session_on_push_promise_received(void)
CU_ASSERT(0 == user_data.begin_headers_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(0 == OB_CTRL(item)->hd.stream_id);
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(0 == item->frame.hd.stream_id);
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
CU_ASSERT(0 == nghttp2_session_send(session));
nghttp2_session_del(session);
@ -2387,8 +2390,8 @@ void test_nghttp2_session_on_push_promise_received(void)
CU_ASSERT(0 == user_data.begin_headers_cb_called);
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 8));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == item->frame.goaway.error_code);
CU_ASSERT(0 == nghttp2_session_send(session));
/* After GOAWAY, PUSH_PROMISE will be discarded */
@ -2505,9 +2508,9 @@ void test_nghttp2_session_on_ping_received(void)
CU_ASSERT(0 == nghttp2_session_on_ping_received(session, &frame));
CU_ASSERT(2 == user_data.frame_recv_cb_called);
top = nghttp2_session_get_ob_pq_top(session);
CU_ASSERT(NGHTTP2_PING == OB_CTRL_TYPE(top));
CU_ASSERT(NGHTTP2_FLAG_ACK == OB_CTRL(top)->hd.flags);
CU_ASSERT(memcmp(opaque_data, OB_CTRL(top)->ping.opaque_data, 8) == 0);
CU_ASSERT(NGHTTP2_PING == top->frame.hd.type);
CU_ASSERT(NGHTTP2_FLAG_ACK == top->frame.hd.flags);
CU_ASSERT(memcmp(opaque_data, top->frame.ping.opaque_data, 8) == 0);
nghttp2_frame_ping_free(&frame.ping);
nghttp2_session_del(session);
@ -2557,9 +2560,7 @@ void test_nghttp2_session_on_window_update_received(void)
&pri_spec_default,
NGHTTP2_STREAM_OPENED, NULL);
data_item = malloc(sizeof(nghttp2_outbound_item));
memset(data_item, 0, sizeof(nghttp2_outbound_item));
data_item->frame_cat = NGHTTP2_CAT_DATA;
data_item = create_data_ob_item();
CU_ASSERT(0 == nghttp2_stream_attach_data(stream, data_item,
&session->ob_da_pq,
@ -2647,8 +2648,8 @@ void test_nghttp2_session_on_data_received(void)
top = nghttp2_session_get_ob_pq_top(session);
/* DATA against nonexistent stream is just ignored for now */
CU_ASSERT(top == NULL);
/* CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(top)); */
/* CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == OB_CTRL(top)->rst_stream.error_code); */
/* CU_ASSERT(NGHTTP2_RST_STREAM == top->frame.hd.type); */
/* CU_ASSERT(NGHTTP2_PROTOCOL_ERROR == top->frame.rst_stream.error_code); */
nghttp2_session_del(session);
}
@ -2657,22 +2658,27 @@ void test_nghttp2_session_send_headers_start_stream(void)
{
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_frame *frame = malloc(sizeof(nghttp2_frame));
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_stream *stream;
nghttp2_aux_data aux_data;
memset(&aux_data, 0, sizeof(aux_data));
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback;
nghttp2_session_client_new(&session, &callbacks, NULL);
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
session->next_stream_id,
NGHTTP2_HCAT_REQUEST, NULL, NULL, 0);
session->next_stream_id += 2;
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, &aux_data);
nghttp2_session_add_item(session, item);
CU_ASSERT(0 == nghttp2_session_send(session));
stream = nghttp2_session_get_stream(session, 1);
CU_ASSERT(NGHTTP2_STREAM_OPENING == stream->state);
@ -2684,7 +2690,8 @@ void test_nghttp2_session_send_headers_reply(void)
{
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_frame *frame = malloc(sizeof(nghttp2_frame));
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_stream *stream;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
@ -2694,9 +2701,16 @@ void test_nghttp2_session_send_headers_reply(void)
nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default,
NGHTTP2_STREAM_OPENING, NULL);
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
nghttp2_session_add_item(session, item);
CU_ASSERT(0 == nghttp2_session_send(session));
stream = nghttp2_session_get_stream(session, 2);
CU_ASSERT(NGHTTP2_STREAM_OPENED == stream->state);
@ -2708,7 +2722,8 @@ void test_nghttp2_session_send_headers_frame_size_error(void)
{
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_frame *frame = malloc(sizeof(nghttp2_frame));
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_nv *nva;
ssize_t nvlen;
size_t vallen = NGHTTP2_HD_MAX_NV;
@ -2735,13 +2750,19 @@ void test_nghttp2_session_send_headers_frame_size_error(void)
nvlen = nnv;
nghttp2_nv_array_copy(&nva, nv, nvlen);
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
session->next_stream_id,
NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
session->next_stream_id += 2;
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
nghttp2_session_add_item(session, item);
ud.frame_not_send_cb_called = 0;
@ -2761,7 +2782,8 @@ void test_nghttp2_session_send_headers_push_reply(void)
{
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_frame *frame = malloc(sizeof(nghttp2_frame));
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_stream *stream;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
@ -2771,9 +2793,16 @@ void test_nghttp2_session_send_headers_push_reply(void)
nghttp2_session_open_stream(session, 2, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default,
NGHTTP2_STREAM_RESERVED, NULL);
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
nghttp2_session_add_item(session, item);
CU_ASSERT(0 == session->num_outgoing_streams);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(1 == session->num_outgoing_streams);
@ -2788,7 +2817,9 @@ void test_nghttp2_session_send_rst_stream(void)
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
my_user_data user_data;
nghttp2_outbound_item *item;
nghttp2_frame *frame;
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.send_callback = null_send_callback;
nghttp2_session_client_new(&session, &callbacks, &user_data);
@ -2796,9 +2827,14 @@ void test_nghttp2_session_send_rst_stream(void)
&pri_spec_default,
NGHTTP2_STREAM_OPENING, NULL);
frame = malloc(sizeof(nghttp2_frame));
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_rst_stream_init(&frame->rst_stream, 1, NGHTTP2_PROTOCOL_ERROR);
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
nghttp2_session_add_item(session, item);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 1));
@ -2810,7 +2846,8 @@ void test_nghttp2_session_send_push_promise(void)
{
nghttp2_session *session;
nghttp2_session_callbacks callbacks;
nghttp2_frame *frame = malloc(sizeof(nghttp2_frame));
nghttp2_outbound_item *item;
nghttp2_frame *frame;
nghttp2_stream *stream;
nghttp2_settings_entry iv;
my_user_data ud;
@ -2823,6 +2860,13 @@ void test_nghttp2_session_send_push_promise(void)
nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default, NGHTTP2_STREAM_OPENING,
NULL);
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_push_promise_init(&frame->push_promise,
NGHTTP2_FLAG_END_HEADERS, 1,
session->next_stream_id,
@ -2830,7 +2874,7 @@ void test_nghttp2_session_send_push_promise(void)
session->next_stream_id += 2;
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
nghttp2_session_add_item(session, item);
CU_ASSERT(0 == nghttp2_session_send(session));
stream = nghttp2_session_get_stream(session, 2);
@ -2846,11 +2890,17 @@ void test_nghttp2_session_send_push_promise(void)
nghttp2_frame_settings_free(&frame->settings);
free(frame);
frame = malloc(sizeof(nghttp2_frame));
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_push_promise_init(&frame->push_promise,
NGHTTP2_FLAG_END_HEADERS, 1, -1,
NULL, 0);
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
nghttp2_session_add_item(session, item);
ud.frame_not_send_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_send(session));
@ -2865,11 +2915,16 @@ void test_nghttp2_session_send_push_promise(void)
nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default, NGHTTP2_STREAM_OPENING,
NULL);
frame = malloc(sizeof(nghttp2_frame));
item = malloc(sizeof(nghttp2_outbound_item));
nghttp2_session_outbound_item_init(session, item);
frame = &item->frame;
nghttp2_frame_push_promise_init(&frame->push_promise,
NGHTTP2_FLAG_END_HEADERS, 1, -1,
NULL, 0);
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
nghttp2_session_add_item(session, item);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(NULL == nghttp2_session_get_stream(session, 3));
@ -2928,14 +2983,14 @@ void test_nghttp2_session_upgrade(void)
CU_ASSERT(&callbacks == stream->stream_user_data);
CU_ASSERT(NGHTTP2_SHUT_WR == stream->shut_flags);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_SETTINGS == OB_CTRL_TYPE(item));
CU_ASSERT(2 == OB_CTRL(item)->settings.niv);
CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
CU_ASSERT(2 == item->frame.settings.niv);
CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
OB_CTRL(item)->settings.iv[0].settings_id);
CU_ASSERT(1 == OB_CTRL(item)->settings.iv[0].value);
item->frame.settings.iv[0].settings_id);
CU_ASSERT(1 == item->frame.settings.iv[0].value);
CU_ASSERT(NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE ==
OB_CTRL(item)->settings.iv[1].settings_id);
CU_ASSERT(4095 == OB_CTRL(item)->settings.iv[1].value);
item->frame.settings.iv[1].settings_id);
CU_ASSERT(4095 == item->frame.settings.iv[1].value);
/* Call nghttp2_session_upgrade() again is error */
CU_ASSERT(NGHTTP2_ERR_PROTO == nghttp2_session_upgrade(session,
@ -3032,7 +3087,7 @@ void test_nghttp2_submit_data(void)
nghttp2_session_callbacks callbacks;
nghttp2_data_provider data_prd;
my_user_data ud;
nghttp2_private_data *data_frame;
nghttp2_frame *frame;
nghttp2_frame_hd hd;
nghttp2_active_outbound_item *aob;
nghttp2_bufs *framebufs;
@ -3055,14 +3110,15 @@ void test_nghttp2_submit_data(void)
ud.block_count = 0;
CU_ASSERT(0 == nghttp2_session_send(session));
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
frame = &aob->item->frame;
buf = &framebufs->head->buf;
nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
/* frame->hd.flags has these flags */
CU_ASSERT(NGHTTP2_FLAG_END_STREAM == data_frame->hd.flags);
CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
/* aux_data.data.flags has these flags */
CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
nghttp2_session_del(session);
}
@ -3073,7 +3129,7 @@ void test_nghttp2_submit_data_read_length_too_large(void)
nghttp2_session_callbacks callbacks;
nghttp2_data_provider data_prd;
my_user_data ud;
nghttp2_private_data *data_frame;
nghttp2_frame *frame;
nghttp2_frame_hd hd;
nghttp2_active_outbound_item *aob;
nghttp2_bufs *framebufs;
@ -3098,15 +3154,16 @@ void test_nghttp2_submit_data_read_length_too_large(void)
ud.block_count = 0;
CU_ASSERT(0 == nghttp2_session_send(session));
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
frame = &aob->item->frame;
buf = &framebufs->head->buf;
nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
CU_ASSERT(16384 == hd.length)
/* frame->hd.flags has these flags */
CU_ASSERT(NGHTTP2_FLAG_END_STREAM == data_frame->hd.flags);
/* aux_data.data.flags has these flags */
CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
nghttp2_session_del(session);
@ -3128,7 +3185,7 @@ void test_nghttp2_submit_data_read_length_too_large(void)
aob = &session->aob;
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
frame = &aob->item->frame;
framebufs = &aob->framebufs;
@ -3141,9 +3198,10 @@ void test_nghttp2_submit_data_read_length_too_large(void)
CU_ASSERT(NGHTTP2_FRAME_HDLEN + 1 + payloadlen ==
(size_t)nghttp2_buf_cap(buf));
CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
CU_ASSERT(payloadlen == hd.length);
/* frame->hd.flags has these flags */
CU_ASSERT(NGHTTP2_FLAG_END_STREAM == data_frame->hd.flags);
/* aux_data.data.flags has these flags */
CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
nghttp2_session_del(session);
}
@ -3154,7 +3212,7 @@ void test_nghttp2_submit_data_read_length_smallest(void)
nghttp2_session_callbacks callbacks;
nghttp2_data_provider data_prd;
my_user_data ud;
nghttp2_private_data *data_frame;
nghttp2_frame *frame;
nghttp2_frame_hd hd;
nghttp2_active_outbound_item *aob;
nghttp2_bufs *framebufs;
@ -3178,15 +3236,16 @@ void test_nghttp2_submit_data_read_length_smallest(void)
ud.block_count = 0;
CU_ASSERT(0 == nghttp2_session_send(session));
data_frame = nghttp2_outbound_item_get_data_frame(aob->item);
frame = &aob->item->frame;
buf = &framebufs->head->buf;
nghttp2_frame_unpack_frame_hd(&hd, buf->pos);
CU_ASSERT(NGHTTP2_FLAG_NONE == hd.flags);
CU_ASSERT(NGHTTP2_FLAG_NONE == frame->hd.flags);
CU_ASSERT(1 == hd.length)
/* frame->hd.flags has these flags */
CU_ASSERT(NGHTTP2_FLAG_END_STREAM == data_frame->hd.flags);
/* aux_data.data.flags has these flags */
CU_ASSERT(NGHTTP2_FLAG_END_STREAM == aob->item->aux_data.data.flags);
nghttp2_session_del(session);
}
@ -3275,7 +3334,7 @@ void test_nghttp2_submit_request_with_data(void)
CU_ASSERT(1 == nghttp2_submit_request(session, NULL,
nva, ARRLEN(nva), &data_prd, NULL));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == ud.data_source_length);
@ -3311,8 +3370,8 @@ void test_nghttp2_submit_request_without_data(void)
CU_ASSERT(1 == nghttp2_submit_request(session, NULL,
nva, ARRLEN(nva), &data_prd, NULL));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
CU_ASSERT(OB_CTRL(item)->hd.flags & NGHTTP2_FLAG_END_STREAM);
CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
@ -3352,7 +3411,7 @@ void test_nghttp2_submit_response_with_data(void)
CU_ASSERT(0 == nghttp2_submit_response(session, 1, nva, ARRLEN(nva),
&data_prd));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == ud.data_source_length);
@ -3391,8 +3450,8 @@ void test_nghttp2_submit_response_without_data(void)
CU_ASSERT(0 == nghttp2_submit_response(session, 1, nva, ARRLEN(nva),
&data_prd));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
CU_ASSERT(OB_CTRL(item)->hd.flags & NGHTTP2_FLAG_END_STREAM);
CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
CU_ASSERT(item->frame.hd.flags & NGHTTP2_FLAG_END_STREAM);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == unpack_frame(&frame, acc.buf, acc.length));
@ -3425,10 +3484,10 @@ void test_nghttp2_submit_headers_start_stream(void)
-1, NULL,
nv, ARRLEN(nv), NULL));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
CU_ASSERT((NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_STREAM) ==
OB_CTRL(item)->hd.flags);
CU_ASSERT(0 == (OB_CTRL(item)->hd.flags & NGHTTP2_FLAG_PRIORITY));
item->frame.hd.flags);
CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
nghttp2_session_del(session);
}
@ -3454,9 +3513,9 @@ void test_nghttp2_submit_headers_reply(void)
1, NULL,
nv, ARRLEN(nv), NULL));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
OB_CTRL(item)->hd.flags);
item->frame.hd.flags);
ud.frame_send_cb_called = 0;
ud.sent_frame_type = 0;
@ -3567,9 +3626,9 @@ void test_nghttp2_submit_headers(void)
1, NULL,
nv, ARRLEN(nv), NULL));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
CU_ASSERT(nvnameeq(":version", &item->frame.headers.nva[0]));
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
OB_CTRL(item)->hd.flags);
item->frame.hd.flags);
ud.frame_send_cb_called = 0;
ud.sent_frame_type = 0;
@ -3640,10 +3699,10 @@ void test_nghttp2_submit_headers_continuation(void)
-1, NULL,
nv, ARRLEN(nv), NULL));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_HEADERS == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
CU_ASSERT((NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_HEADERS) ==
OB_CTRL(item)->hd.flags);
CU_ASSERT(0 == (OB_CTRL(item)->hd.flags & NGHTTP2_FLAG_PRIORITY));
item->frame.hd.flags);
CU_ASSERT(0 == (item->frame.hd.flags & NGHTTP2_FLAG_PRIORITY));
ud.frame_send_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_send(session));
@ -3774,9 +3833,9 @@ void test_nghttp2_submit_settings(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_SETTINGS == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_SETTINGS == item->frame.hd.type);
frame = item->frame;
frame = &item->frame;
CU_ASSERT(5 == frame->settings.niv);
CU_ASSERT(5 == frame->settings.iv[0].value);
CU_ASSERT(NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS ==
@ -3849,8 +3908,8 @@ void test_nghttp2_submit_settings_update_local_window_size(void)
CU_ASSERT(16*1024 == stream->local_window_size);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(32768 == OB_CTRL(item)->window_update.window_size_increment);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(32768 == item->frame.window_update.window_size_increment);
nghttp2_session_del(session);
@ -3868,8 +3927,8 @@ void test_nghttp2_submit_settings_update_local_window_size(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(NGHTTP2_FLOW_CONTROL_ERROR == item->frame.goaway.error_code);
nghttp2_session_del(session);
nghttp2_frame_settings_free(&ack_frame.settings);
@ -3929,24 +3988,24 @@ void test_nghttp2_submit_window_update(void)
CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
1024));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(1024 == OB_CTRL(item)->window_update.window_size_increment);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(1024 == item->frame.window_update.window_size_increment);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(3072 == stream->recv_window_size);
CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
4096));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(4096 == OB_CTRL(item)->window_update.window_size_increment);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == stream->recv_window_size);
CU_ASSERT(0 == nghttp2_submit_window_update(session, NGHTTP2_FLAG_NONE, 2,
4096));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(4096 == OB_CTRL(item)->window_update.window_size_increment);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(4096 == item->frame.window_update.window_size_increment);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(0 == stream->recv_window_size);
@ -3982,8 +4041,8 @@ void test_nghttp2_submit_window_update_local_window_size(void)
CU_ASSERT(NGHTTP2_INITIAL_WINDOW_SIZE + 1 == stream->local_window_size);
CU_ASSERT(0 == stream->recv_window_size);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(4097 == OB_CTRL(item)->window_update.window_size_increment);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
CU_ASSERT(0 == nghttp2_session_send(session));
@ -4020,8 +4079,8 @@ void test_nghttp2_submit_window_update_local_window_size(void)
session->local_window_size);
CU_ASSERT(0 == session->recv_window_size);
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(4097 == OB_CTRL(item)->window_update.window_size_increment);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(4097 == item->frame.window_update.window_size_increment);
CU_ASSERT(0 == nghttp2_session_send(session));
@ -4092,7 +4151,7 @@ void test_nghttp2_submit_altsvc(void)
item = nghttp2_session_get_next_ob_item(session);
frame = OB_CTRL(item);
frame = &item->frame;
CU_ASSERT(NGHTTP2_EXT_ALTSVC == frame->hd.type);
CU_ASSERT(9 == frame->hd.stream_id);
@ -4247,11 +4306,11 @@ void test_nghttp2_session_get_next_ob_item(void)
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
nghttp2_submit_ping(session, NGHTTP2_FLAG_NONE, NULL);
CU_ASSERT(NGHTTP2_PING ==
OB_CTRL_TYPE(nghttp2_session_get_next_ob_item(session)));
nghttp2_session_get_next_ob_item(session)->frame.hd.type);
nghttp2_submit_request(session, NULL, NULL, 0, NULL, NULL);
CU_ASSERT(NGHTTP2_PING ==
OB_CTRL_TYPE(nghttp2_session_get_next_ob_item(session)));
nghttp2_session_get_next_ob_item(session)->frame.hd.type);
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(session));
@ -4266,7 +4325,7 @@ void test_nghttp2_session_get_next_ob_item(void)
nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
CU_ASSERT(NGHTTP2_HEADERS ==
OB_CTRL_TYPE(nghttp2_session_get_next_ob_item(session)));
nghttp2_session_get_next_ob_item(session)->frame.hd.type);
CU_ASSERT(0 == nghttp2_session_send(session));
nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
@ -4275,7 +4334,7 @@ void test_nghttp2_session_get_next_ob_item(void)
session->remote_settings.max_concurrent_streams = 3;
CU_ASSERT(NGHTTP2_HEADERS ==
OB_CTRL_TYPE(nghttp2_session_get_next_ob_item(session)));
nghttp2_session_get_next_ob_item(session)->frame.hd.type);
nghttp2_session_del(session);
}
@ -4302,12 +4361,12 @@ void test_nghttp2_session_pop_next_ob_item(void)
nghttp2_submit_request(session, &pri_spec, NULL, 0, NULL, NULL);
item = nghttp2_session_pop_next_ob_item(session);
CU_ASSERT(NGHTTP2_PING == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_PING == item->frame.hd.type);
nghttp2_outbound_item_free(item);
free(item);
item = nghttp2_session_pop_next_ob_item(session);
CU_ASSERT(NGHTTP2_HEADERS == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
nghttp2_outbound_item_free(item);
free(item);
@ -4327,8 +4386,8 @@ void test_nghttp2_session_pop_next_ob_item(void)
nghttp2_submit_response(session, 1, NULL, 0, NULL);
item = nghttp2_session_pop_next_ob_item(session);
CU_ASSERT(NGHTTP2_HEADERS == OB_CTRL_TYPE(item));
CU_ASSERT(1 == OB_CTRL(item)->hd.stream_id);
CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
CU_ASSERT(1 == item->frame.hd.stream_id);
nghttp2_outbound_item_free(item);
free(item);
@ -4337,7 +4396,7 @@ void test_nghttp2_session_pop_next_ob_item(void)
session->remote_settings.max_concurrent_streams = 2;
item = nghttp2_session_pop_next_ob_item(session);
CU_ASSERT(NGHTTP2_HEADERS == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_HEADERS == item->frame.hd.type);
nghttp2_outbound_item_free(item);
free(item);
@ -4402,8 +4461,8 @@ void test_nghttp2_session_max_concurrent_streams(void)
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));
CU_ASSERT(NGHTTP2_REFUSED_STREAM == OB_CTRL(item)->rst_stream.error_code);
CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
CU_ASSERT(NGHTTP2_REFUSED_STREAM == item->frame.rst_stream.error_code);
CU_ASSERT(0 == nghttp2_session_send(session));
@ -4415,8 +4474,8 @@ void test_nghttp2_session_max_concurrent_streams(void)
nghttp2_session_on_request_headers_received(session, &frame));
item = nghttp2_session_get_ob_pq_top(session);
CU_ASSERT(NGHTTP2_GOAWAY == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_ENHANCE_YOUR_CALM == OB_CTRL(item)->goaway.error_code);
CU_ASSERT(NGHTTP2_GOAWAY == item->frame.hd.type);
CU_ASSERT(NGHTTP2_ENHANCE_YOUR_CALM == item->frame.goaway.error_code);
nghttp2_frame_headers_free(&frame.headers);
nghttp2_session_del(session);
@ -4537,7 +4596,7 @@ void test_nghttp2_session_defer_data(void)
/* Resume deferred DATA */
CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
item = (nghttp2_outbound_item*)nghttp2_pq_top(&session->ob_da_pq);
OB_DATA(item)->data_prd.read_callback =
item->aux_data.data.data_prd.read_callback =
fixed_length_data_source_read_callback;
ud.block_count = 1;
/* Reads 2 DATA chunks */
@ -4545,7 +4604,7 @@ void test_nghttp2_session_defer_data(void)
CU_ASSERT(ud.data_source_length == NGHTTP2_DATA_PAYLOADLEN * 2);
/* Deferred again */
OB_DATA(item)->data_prd.read_callback = defer_data_source_read_callback;
item->aux_data.data.data_prd.read_callback = defer_data_source_read_callback;
/* This is needed since 4KiB block is already read and waiting to be
sent. No read_callback invocation. */
ud.block_count = 1;
@ -4555,7 +4614,7 @@ void test_nghttp2_session_defer_data(void)
/* Resume deferred DATA */
CU_ASSERT(0 == nghttp2_session_resume_data(session, 1));
item = (nghttp2_outbound_item*)nghttp2_pq_top(&session->ob_da_pq);
OB_DATA(item)->data_prd.read_callback =
item->aux_data.data.data_prd.read_callback =
fixed_length_data_source_read_callback;
ud.block_count = 1;
/* Reads 2 4KiB blocks */
@ -4719,10 +4778,10 @@ void test_nghttp2_session_flow_control_data_recv(void)
item = nghttp2_session_get_next_ob_item(session);
/* Since this is the last frame, stream-level WINDOW_UPDATE is not
issued, but connection-level is. */
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(0 == OB_CTRL(item)->hd.stream_id);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(0 == item->frame.hd.stream_id);
CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
OB_CTRL(item)->window_update.window_size_increment);
item->frame.window_update.window_size_increment);
CU_ASSERT(0 == nghttp2_session_send(session));
@ -4737,10 +4796,10 @@ void test_nghttp2_session_flow_control_data_recv(void)
NGHTTP2_FRAME_HDLEN));
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == OB_CTRL_TYPE(item));
CU_ASSERT(0 == OB_CTRL(item)->hd.stream_id);
CU_ASSERT(NGHTTP2_WINDOW_UPDATE == item->frame.hd.type);
CU_ASSERT(0 == item->frame.hd.stream_id);
CU_ASSERT(NGHTTP2_MAX_PAYLOADLEN ==
OB_CTRL(item)->window_update.window_size_increment);
item->frame.window_update.window_size_increment);
nghttp2_session_del(session);
}
@ -4799,7 +4858,6 @@ void test_nghttp2_session_data_read_temporal_failure(void)
my_user_data ud;
nghttp2_data_provider data_prd;
nghttp2_frame frame;
nghttp2_private_data *data_frame;
nghttp2_stream *stream;
size_t data_size = 128*1024;
@ -4821,9 +4879,9 @@ void test_nghttp2_session_data_read_temporal_failure(void)
stream = nghttp2_session_get_stream(session, 1);
CU_ASSERT(nghttp2_stream_check_deferred_by_flow_control(stream));
CU_ASSERT(NGHTTP2_CAT_DATA == stream->data_item->frame_cat);
data_frame = (nghttp2_private_data*)stream->data_item->frame;
data_frame->data_prd.read_callback =
CU_ASSERT(NGHTTP2_DATA == stream->data_item->frame.hd.type);
stream->data_item->aux_data.data.data_prd.read_callback =
temporal_failure_data_source_read_callback;
/* Back NGHTTP2_INITIAL_WINDOW_SIZE to both connection-level and
@ -5161,7 +5219,7 @@ void test_nghttp2_session_pack_data_with_padding(void)
my_user_data ud;
nghttp2_session_callbacks callbacks;
nghttp2_data_provider data_prd;
nghttp2_private_data *frame;
nghttp2_frame *frame;
size_t datalen = 55;
memset(&callbacks, 0, sizeof(callbacks));
@ -5182,9 +5240,9 @@ void test_nghttp2_session_pack_data_with_padding(void)
CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(NGHTTP2_HEADERS == ud.sent_frame_type);
frame = OB_DATA(session->aob.item);
frame = &session->aob.item->frame;
CU_ASSERT(ud.padlen == frame->padlen);
CU_ASSERT(ud.padlen == frame->data.padlen);
CU_ASSERT(frame->hd.flags & NGHTTP2_FLAG_PADDED);
/* Check reception of this DATA frame */
@ -6393,7 +6451,7 @@ void test_nghttp2_session_on_header_temporal_failure(void)
item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(NGHTTP2_RST_STREAM == OB_CTRL_TYPE(item));
CU_ASSERT(NGHTTP2_RST_STREAM == item->frame.hd.type);
/* Make sure no header decompression error occurred */
CU_ASSERT(NGHTTP2_GOAWAY_NONE == session->goaway_flags);

View File

@ -295,7 +295,6 @@ nghttp2_outbound_item* create_data_ob_item(void)
item = malloc(sizeof(nghttp2_outbound_item));
memset(item, 0, sizeof(nghttp2_outbound_item));
item->frame_cat = NGHTTP2_CAT_DATA;
return item;
}