Return new stream ID from nghttp2_submit_{request, headers, push_promise}

Previously stream ID was assigned just before HEADERS or PUSH_PROMISE
was serialized and nghttp2_submit_{request, headers, push_promise} did
not return stream ID.  The application has to check assigned stream ID
using before_frame_send_callback.  Now it is apparent that priority is
meant to DATA transfer only.  Also application can reorder the
requests if it wants. Therefore we can assign stream ID in
nghttp2_submit_* functions and return stream ID from them.  With this
change, now application does not have to check stream ID using
before_frame_send_callback and its code will be simplified.
This commit is contained in:
Tatsuhiro Tsujikawa 2014-05-07 23:24:07 +09:00
parent 51e79c5a3d
commit e8de437d5c
13 changed files with 293 additions and 415 deletions

View File

@ -197,29 +197,6 @@ static ssize_t recv_callback(nghttp2_session *session,
return rv; return rv;
} }
/*
* The implementation of nghttp2_before_frame_send_callback type. We
* use this function to get stream ID of the request. This is because
* stream ID is not known when we submit the request
* (nghttp2_submit_request).
*/
static int before_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data)
{
if(frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
struct Request *req;
int32_t stream_id = frame->hd.stream_id;
req = nghttp2_session_get_stream_user_data(session, stream_id);
if(req && req->stream_id == -1) {
req->stream_id = stream_id;
printf("[INFO] Stream ID = %d\n", stream_id);
}
}
return 0;
}
static int on_frame_send_callback(nghttp2_session *session, static int on_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data) const nghttp2_frame *frame, void *user_data)
{ {
@ -335,7 +312,6 @@ static void setup_nghttp2_callbacks(nghttp2_session_callbacks *callbacks)
memset(callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks->send_callback = send_callback; callbacks->send_callback = send_callback;
callbacks->recv_callback = recv_callback; callbacks->recv_callback = recv_callback;
callbacks->before_frame_send_callback = before_frame_send_callback;
callbacks->on_frame_send_callback = on_frame_send_callback; callbacks->on_frame_send_callback = on_frame_send_callback;
callbacks->on_frame_recv_callback = on_frame_recv_callback; callbacks->on_frame_recv_callback = on_frame_recv_callback;
callbacks->on_stream_close_callback = on_stream_close_callback; callbacks->on_stream_close_callback = on_stream_close_callback;
@ -470,7 +446,7 @@ static void ctl_poll(struct pollfd *pollfd, struct Connection *connection)
*/ */
static void submit_request(struct Connection *connection, struct Request *req) static void submit_request(struct Connection *connection, struct Request *req)
{ {
int rv; int32_t stream_id;
const nghttp2_nv nva[] = { const nghttp2_nv nva[] = {
/* Make sure that the last item is NULL */ /* Make sure that the last item is NULL */
MAKE_NV(":method", "GET"), MAKE_NV(":method", "GET"),
@ -480,11 +456,17 @@ static void submit_request(struct Connection *connection, struct Request *req)
MAKE_NV("accept", "*/*"), MAKE_NV("accept", "*/*"),
MAKE_NV("user-agent", "nghttp2/"NGHTTP2_VERSION) MAKE_NV("user-agent", "nghttp2/"NGHTTP2_VERSION)
}; };
rv = nghttp2_submit_request(connection->session, NULL,
nva, sizeof(nva)/sizeof(nva[0]), NULL, req); stream_id = nghttp2_submit_request(connection->session, NULL,
if(rv != 0) { nva, sizeof(nva)/sizeof(nva[0]),
diec("nghttp2_submit_request", rv); NULL, req);
if(stream_id < 0) {
diec("nghttp2_submit_request", stream_id);
} }
req->stream_id = stream_id;
printf("[INFO] Stream ID = %d\n", stream_id);
} }
/* /*

View File

@ -188,28 +188,6 @@ static ssize_t send_callback(nghttp2_session *session,
return length; return length;
} }
/* nghttp2_before_frame_send_callback: Called when nghttp2 library is
about to send a frame. We use this callback to get stream ID of new
stream. Since HEADERS in HTTP/2 has several roles, we check that
it is a HTTP request HEADERS. */
static int before_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
http2_stream_data *stream_data;
if(frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
stream_data =
(http2_stream_data*)nghttp2_session_get_stream_user_data
(session, frame->hd.stream_id);
if(stream_data == session_data->stream_data) {
stream_data->stream_id = frame->hd.stream_id;
}
}
return 0;
}
/* nghttp2_on_header_callback: Called when nghttp2 library emits /* nghttp2_on_header_callback: Called when nghttp2 library emits
single header name/value pair. */ single header name/value pair. */
static int on_header_callback(nghttp2_session *session, static int on_header_callback(nghttp2_session *session,
@ -357,7 +335,6 @@ static void initialize_nghttp2_session(http2_session_data *session_data)
memset(&callbacks, 0, sizeof(callbacks)); memset(&callbacks, 0, sizeof(callbacks));
callbacks.send_callback = send_callback; callbacks.send_callback = send_callback;
callbacks.before_frame_send_callback = before_frame_send_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_stream_close_callback = on_stream_close_callback;
@ -394,7 +371,7 @@ static void send_client_connection_header(http2_session_data *session_data)
/* Send HTTP request to the remote peer */ /* Send HTTP request to the remote peer */
static void submit_request(http2_session_data *session_data) static void submit_request(http2_session_data *session_data)
{ {
int rv; int32_t stream_id;
http2_stream_data *stream_data = session_data->stream_data; http2_stream_data *stream_data = session_data->stream_data;
const char *uri = stream_data->uri; const char *uri = stream_data->uri;
const struct http_parser_url *u = stream_data->u; const struct http_parser_url *u = stream_data->u;
@ -407,11 +384,13 @@ static void submit_request(http2_session_data *session_data)
}; };
fprintf(stderr, "Request headers:\n"); fprintf(stderr, "Request headers:\n");
print_headers(stderr, hdrs, ARRLEN(hdrs)); print_headers(stderr, hdrs, ARRLEN(hdrs));
rv = nghttp2_submit_request(session_data->session, NULL, stream_id = nghttp2_submit_request(session_data->session, NULL,
hdrs, ARRLEN(hdrs), NULL, stream_data); hdrs, ARRLEN(hdrs), NULL, stream_data);
if(rv != 0) { if(stream_id < 0) {
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(rv)); errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(stream_id));
} }
stream_data->stream_id = stream_id;
} }
/* Serialize the frame and send (or buffer) the data to /* Serialize the frame and send (or buffer) the data to

View File

@ -2231,29 +2231,20 @@ int nghttp2_priority_spec_check_default(const nghttp2_priority_spec *pri_spec);
* arbitrary pointer, which can be retrieved later by * arbitrary pointer, which can be retrieved later by
* `nghttp2_session_get_stream_user_data()`. * `nghttp2_session_get_stream_user_data()`.
* *
* Since the library reorders the frames and tries to send the highest * This function returns assigned stream ID if it succeeds, or one of
* prioritized one first and the HTTP/2 specification requires the * the following negative error codes:
* stream ID must be strictly increasing, the stream ID of this
* request cannot be known until it is about to sent. To know the
* stream ID of the request, the application can use
* :member:`nghttp2_session_callbacks.before_frame_send_callback`.
* This callback is called just before the frame is sent. For HEADERS
* frame, the argument frame has the stream ID assigned. Also since
* the stream is already opened,
* `nghttp2_session_get_stream_user_data()` can be used to get
* |stream_user_data| to identify which HEADERS we are processing.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
* *
* :enum:`NGHTTP2_ERR_NOMEM` * :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory. * Out of memory.
* :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
* No stream ID is available because maximum stream ID was
* reached.
*/ */
int nghttp2_submit_request(nghttp2_session *session, int32_t nghttp2_submit_request(nghttp2_session *session,
const nghttp2_priority_spec *pri_spec, const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva, size_t nvlen, const nghttp2_nv *nva, size_t nvlen,
const nghttp2_data_provider *data_prd, const nghttp2_data_provider *data_prd,
void *stream_user_data); void *stream_user_data);
/** /**
* @function * @function
@ -2314,8 +2305,8 @@ int nghttp2_submit_response(nghttp2_session *session,
* *
* If the |stream_id| is -1, this frame is assumed as request (i.e., * If the |stream_id| is -1, this frame is assumed as request (i.e.,
* request HEADERS frame which opens new stream). In this case, the * request HEADERS frame which opens new stream). In this case, the
* actual stream ID is assigned just before the frame is sent. For * assigned stream ID will be returned. Otherwise, specify stream ID
* response, specify stream ID in |stream_id|. * in |stream_id|.
* *
* The |pri_spec| is priority specification of this request. ``NULL`` * The |pri_spec| is priority specification of this request. ``NULL``
* means the default priority (see * means the default priority (see
@ -2348,17 +2339,21 @@ int nghttp2_submit_response(nghttp2_session *session,
* specify flags directly. For usual HTTP request, * specify flags directly. For usual HTTP request,
* `nghttp2_submit_request()` is useful. * `nghttp2_submit_request()` is useful.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns newly assigned stream ID if it succeeds and
* negative error codes: * |stream_id| is -1. Otherwise, this function returns 0 if it
* succeeds, or one of the following negative error codes:
* *
* :enum:`NGHTTP2_ERR_NOMEM` * :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory. * Out of memory.
* :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
* No stream ID is available because maximum stream ID was
* reached.
*/ */
int nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
int32_t stream_id, int32_t stream_id,
const nghttp2_priority_spec *pri_spec, const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva, size_t nvlen, const nghttp2_nv *nva, size_t nvlen,
void *stream_user_data); void *stream_user_data);
/** /**
* @function * @function
@ -2500,31 +2495,24 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
* access it in :type:`nghttp2_before_frame_send_callback` and * access it in :type:`nghttp2_before_frame_send_callback` and
* :type:`nghttp2_on_frame_send_callback` of this frame. * :type:`nghttp2_on_frame_send_callback` of this frame.
* *
* Since the library reorders the frames and tries to send the highest
* prioritized one first and the HTTP/2 specification requires the
* stream ID must be strictly increasing, the promised stream ID
* cannot be known until it is about to sent. To know the promised
* stream ID, the application can use
* :member:`nghttp2_session_callbacks.before_frame_send_callback`.
* This callback is called just before the frame is sent. For
* PUSH_PROMISE frame, the argument frame has the promised stream ID
* assigned.
*
* The client side is not allowed to use this function. * The client side is not allowed to use this function.
* *
* This function returns 0 if it succeeds, or one of the following * This function returns assigned promised stream ID if it succeeds,
* negative error codes: * or one of the following negative error codes:
* *
* :enum:`NGHTTP2_ERR_NOMEM` * :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory. * Out of memory.
* :enum:`NGHTTP2_ERR_PROTO` * :enum:`NGHTTP2_ERR_PROTO`
* This function was invoked when |session| is initialized as * This function was invoked when |session| is initialized as
* client. * client.
* :enum:`NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE`
* No stream ID is available because maximum stream ID was
* reached.
*/ */
int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags, int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
int32_t stream_id, int32_t stream_id,
const nghttp2_nv *nva, size_t nvlen, const nghttp2_nv *nva, size_t nvlen,
void *promised_stream_user_data); void *promised_stream_user_data);
/** /**
* @function * @function

View File

@ -66,6 +66,7 @@ static void nghttp2_frame_set_hd(nghttp2_frame_hd *hd, uint16_t length,
void nghttp2_frame_headers_init(nghttp2_headers *frame, void nghttp2_frame_headers_init(nghttp2_headers *frame,
uint8_t flags, int32_t stream_id, uint8_t flags, int32_t stream_id,
nghttp2_headers_category cat,
const nghttp2_priority_spec *pri_spec, const nghttp2_priority_spec *pri_spec,
nghttp2_nv *nva, size_t nvlen) nghttp2_nv *nva, size_t nvlen)
{ {
@ -73,7 +74,7 @@ void nghttp2_frame_headers_init(nghttp2_headers *frame,
frame->padlen = 0; frame->padlen = 0;
frame->nva = nva; frame->nva = nva;
frame->nvlen = nvlen; frame->nvlen = nvlen;
frame->cat = NGHTTP2_HCAT_REQUEST; frame->cat = cat;
if(pri_spec) { if(pri_spec) {
frame->pri_spec = *pri_spec; frame->pri_spec = *pri_spec;

View File

@ -436,6 +436,7 @@ int nghttp2_frame_pack_blocked(nghttp2_bufs *bufs, nghttp2_blocked *frame);
*/ */
void nghttp2_frame_headers_init(nghttp2_headers *frame, void nghttp2_frame_headers_init(nghttp2_headers *frame,
uint8_t flags, int32_t stream_id, uint8_t flags, int32_t stream_id,
nghttp2_headers_category cat,
const nghttp2_priority_spec *pri_spec, const nghttp2_priority_spec *pri_spec,
nghttp2_nv *nva, size_t nvlen); nghttp2_nv *nva, size_t nvlen);

View File

@ -560,40 +560,13 @@ int nghttp2_session_add_frame(nghttp2_session *session,
if(frame_cat == NGHTTP2_CAT_CTRL) { if(frame_cat == NGHTTP2_CAT_CTRL) {
nghttp2_frame *frame = (nghttp2_frame*)abs_frame; nghttp2_frame *frame = (nghttp2_frame*)abs_frame;
nghttp2_stream *stream; nghttp2_stream *stream;
nghttp2_stream *dep_stream;
stream = nghttp2_session_get_stream(session, frame->hd.stream_id); stream = nghttp2_session_get_stream(session, frame->hd.stream_id);
switch(frame->hd.type) { switch(frame->hd.type) {
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
if(frame->hd.stream_id == -1) { item->weight = NGHTTP2_MAX_WEIGHT;
/* Initial HEADERS, which will open stream */
/* TODO If we always frame.headers.pri_spec filled in, we
don't have to check flags */
if(frame->hd.flags & NGHTTP2_FLAG_PRIORITY) {
if(frame->headers.pri_spec.stream_id == 0) {
item->weight = frame->headers.pri_spec.weight;
} else {
dep_stream = nghttp2_session_get_stream
(session, frame->headers.pri_spec.stream_id);
if(dep_stream) {
item->weight = nghttp2_stream_dep_distributed_effective_weight
(dep_stream, frame->headers.pri_spec.weight);
} else {
item->weight = frame->headers.pri_spec.weight;
}
}
} else {
item->weight = NGHTTP2_DEFAULT_WEIGHT;
}
} else if(stream) {
/* Otherwise, the frame must have stream ID. We use its
effective_weight. */
item->weight = stream->effective_weight;
}
break; break;
case NGHTTP2_PRIORITY: case NGHTTP2_PRIORITY:
break; break;
@ -607,18 +580,13 @@ int nghttp2_session_add_frame(nghttp2_session *session,
stream->state = NGHTTP2_STREAM_CLOSING; stream->state = NGHTTP2_STREAM_CLOSING;
} }
} }
break; break;
case NGHTTP2_SETTINGS: case NGHTTP2_SETTINGS:
item->weight = NGHTTP2_OB_SETTINGS_WEIGHT; item->weight = NGHTTP2_OB_SETTINGS_WEIGHT;
break; break;
case NGHTTP2_PUSH_PROMISE: case NGHTTP2_PUSH_PROMISE:
/* Use priority of associated stream */ item->weight = NGHTTP2_MAX_WEIGHT;
if(stream) {
item->weight = stream->effective_weight;
}
break; break;
case NGHTTP2_PING: case NGHTTP2_PING:
/* Ping has highest priority. */ /* Ping has highest priority. */
@ -637,7 +605,7 @@ int nghttp2_session_add_frame(nghttp2_session *session,
} }
if(frame->hd.type == NGHTTP2_HEADERS && if(frame->hd.type == NGHTTP2_HEADERS &&
(frame->hd.stream_id == -1 || (frame->headers.cat == NGHTTP2_HCAT_REQUEST ||
(stream && stream->state == NGHTTP2_STREAM_RESERVED))) { (stream && stream->state == NGHTTP2_STREAM_RESERVED))) {
/* We push request HEADERS and push response HEADERS to /* We push request HEADERS and push response HEADERS to
dedicated queue because their transmission is affected by dedicated queue because their transmission is affected by
@ -996,9 +964,6 @@ static int nghttp2_predicate_stream_for_send(nghttp2_stream *stream)
* NGHTTP2_ERR_START_STREAM_NOT_ALLOWED * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
* New stream cannot be created because GOAWAY is already sent or * New stream cannot be created because GOAWAY is already sent or
* received. * received.
* NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE
* Stream ID has reached the maximum value. Therefore no stream ID
* is available.
*/ */
static int nghttp2_session_predicate_request_headers_send static int nghttp2_session_predicate_request_headers_send
(nghttp2_session *session, nghttp2_headers *frame) (nghttp2_session *session, nghttp2_headers *frame)
@ -1008,10 +973,6 @@ static int nghttp2_session_predicate_request_headers_send
HEADERS. */ HEADERS. */
return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED; return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
} }
/* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) {
return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
}
return 0; return 0;
} }
@ -1176,9 +1137,6 @@ static int nghttp2_session_predicate_priority_send
* NGHTTP2_ERR_START_STREAM_NOT_ALLOWED * NGHTTP2_ERR_START_STREAM_NOT_ALLOWED
* New stream cannot be created because GOAWAY is already sent or * New stream cannot be created because GOAWAY is already sent or
* received. * received.
* NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE
* Stream ID has reached the maximum value. Therefore no stream ID
* is available.
* NGHTTP2_ERR_PROTO * NGHTTP2_ERR_PROTO
* The client side attempts to send PUSH_PROMISE, or the server * The client side attempts to send PUSH_PROMISE, or the server
* sends PUSH_PROMISE for the stream not initiated by the client. * sends PUSH_PROMISE for the stream not initiated by the client.
@ -1220,10 +1178,6 @@ static int nghttp2_session_predicate_push_promise_send
stream ID */ stream ID */
return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED; return NGHTTP2_ERR_START_STREAM_NOT_ALLOWED;
} }
/* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) {
return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
}
return 0; return 0;
} }
@ -1598,19 +1552,16 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
aux_data = (nghttp2_headers_aux_data*)item->aux_data; aux_data = (nghttp2_headers_aux_data*)item->aux_data;
if(frame->hd.stream_id == -1) { if(frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
nghttp2_priority_spec pri_spec_default; nghttp2_priority_spec pri_spec_default;
nghttp2_stream *stream; nghttp2_stream *stream;
/* initial HEADERS, which opens stream */ /* initial HEADERS, which opens stream */
frame->headers.cat = NGHTTP2_HCAT_REQUEST;
rv = nghttp2_session_predicate_request_headers_send(session, rv = nghttp2_session_predicate_request_headers_send(session,
&frame->headers); &frame->headers);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }
frame->hd.stream_id = session->next_stream_id;
session->next_stream_id += 2;
/* We first open strea with default priority. This is because /* We first open strea with default priority. This is because
priority may be adjusted in callback. */ priority may be adjusted in callback. */
@ -1733,8 +1684,7 @@ static int nghttp2_session_prep_frame(nghttp2_session *session,
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }
frame->push_promise.promised_stream_id = session->next_stream_id;
session->next_stream_id += 2;
framerv = nghttp2_frame_pack_push_promise(&session->aob.framebufs, framerv = nghttp2_frame_pack_push_promise(&session->aob.framebufs,
&frame->push_promise, &frame->push_promise,
&session->hd_deflater); &session->hd_deflater);

View File

@ -35,7 +35,7 @@
/* This function takes ownership of |nva_copy|. Regardless of the /* This function takes ownership of |nva_copy|. Regardless of the
return value, the caller must not free |nva_copy| after this return value, the caller must not free |nva_copy| after this
function returns. */ function returns. */
static int nghttp2_submit_headers_shared static int32_t nghttp2_submit_headers_shared
(nghttp2_session *session, (nghttp2_session *session,
uint8_t flags, uint8_t flags,
int32_t stream_id, int32_t stream_id,
@ -50,6 +50,7 @@ static int nghttp2_submit_headers_shared
nghttp2_frame *frame = NULL; nghttp2_frame *frame = NULL;
nghttp2_data_provider *data_prd_copy = NULL; nghttp2_data_provider *data_prd_copy = NULL;
nghttp2_headers_aux_data *aux_data = NULL; nghttp2_headers_aux_data *aux_data = NULL;
nghttp2_headers_category hcat;
if(data_prd != NULL && data_prd->read_callback != NULL) { if(data_prd != NULL && data_prd->read_callback != NULL) {
data_prd_copy = malloc(sizeof(nghttp2_data_provider)); data_prd_copy = malloc(sizeof(nghttp2_data_provider));
@ -80,8 +81,24 @@ static int nghttp2_submit_headers_shared
NGHTTP2_FLAG_PRIORITY)) | NGHTTP2_FLAG_PRIORITY)) |
NGHTTP2_FLAG_END_HEADERS; NGHTTP2_FLAG_END_HEADERS;
nghttp2_frame_headers_init(&frame->headers, flags_copy, stream_id, pri_spec, if(stream_id == -1) {
nva_copy, nvlen); if(session->next_stream_id > INT32_MAX) {
rv = NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
goto fail;
}
stream_id = session->next_stream_id;
session->next_stream_id += 2;
hcat = NGHTTP2_HCAT_REQUEST;
} else {
/* More specific categorization will be done later. */
hcat = NGHTTP2_HCAT_HEADERS;
}
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, rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame,
aux_data); aux_data);
@ -90,7 +107,13 @@ static int nghttp2_submit_headers_shared
nghttp2_frame_headers_free(&frame->headers); nghttp2_frame_headers_free(&frame->headers);
goto fail2; goto fail2;
} }
if(hcat == NGHTTP2_HCAT_REQUEST) {
return stream_id;
}
return 0; return 0;
fail: fail:
/* nghttp2_frame_headers_init() takes ownership of nva_copy. */ /* nghttp2_frame_headers_init() takes ownership of nva_copy. */
nghttp2_nv_array_del(nva_copy); nghttp2_nv_array_del(nva_copy);
@ -110,7 +133,7 @@ static void adjust_priority_spec_weight(nghttp2_priority_spec *pri_spec)
} }
} }
static int nghttp2_submit_headers_shared_nva static int32_t nghttp2_submit_headers_shared_nva
(nghttp2_session *session, (nghttp2_session *session,
uint8_t flags, uint8_t flags,
int32_t stream_id, int32_t stream_id,
@ -141,11 +164,11 @@ static int nghttp2_submit_headers_shared_nva
stream_user_data); stream_user_data);
} }
int nghttp2_submit_headers(nghttp2_session *session, uint8_t flags, int32_t nghttp2_submit_headers(nghttp2_session *session, uint8_t flags,
int32_t stream_id, int32_t stream_id,
const nghttp2_priority_spec *pri_spec, const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva, size_t nvlen, const nghttp2_nv *nva, size_t nvlen,
void *stream_user_data) void *stream_user_data)
{ {
flags &= NGHTTP2_FLAG_END_STREAM; flags &= NGHTTP2_FLAG_END_STREAM;
@ -227,15 +250,16 @@ int nghttp2_submit_settings(nghttp2_session *session, uint8_t flags,
return nghttp2_session_add_settings(session, NGHTTP2_FLAG_NONE, iv, niv); return nghttp2_session_add_settings(session, NGHTTP2_FLAG_NONE, iv, niv);
} }
int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags, int32_t nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
int32_t stream_id, int32_t stream_id,
const nghttp2_nv *nva, size_t nvlen, const nghttp2_nv *nva, size_t nvlen,
void *promised_stream_user_data) void *promised_stream_user_data)
{ {
nghttp2_frame *frame; nghttp2_frame *frame;
nghttp2_nv *nva_copy; nghttp2_nv *nva_copy;
uint8_t flags_copy; uint8_t flags_copy;
nghttp2_headers_aux_data *aux_data = NULL; nghttp2_headers_aux_data *aux_data = NULL;
int32_t promised_stream_id;
int rv; int rv;
if(!session->server) { if(!session->server) {
@ -261,16 +285,35 @@ int nghttp2_submit_push_promise(nghttp2_session *session, uint8_t flags,
free(frame); free(frame);
return rv; return rv;
} }
flags_copy = NGHTTP2_FLAG_END_HEADERS; flags_copy = NGHTTP2_FLAG_END_HEADERS;
/* All 32bit signed stream IDs are spent. */
if(session->next_stream_id > INT32_MAX) {
free(aux_data);
free(frame);
return NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE;
}
promised_stream_id = session->next_stream_id;
session->next_stream_id += 2;
nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy, nghttp2_frame_push_promise_init(&frame->push_promise, flags_copy,
stream_id, -1, nva_copy, nvlen); stream_id, promised_stream_id,
nva_copy, nvlen);
rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, aux_data); rv = nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, aux_data);
if(rv != 0) { if(rv != 0) {
nghttp2_frame_push_promise_free(&frame->push_promise); nghttp2_frame_push_promise_free(&frame->push_promise);
free(aux_data); free(aux_data);
free(frame); free(frame);
return rv;
} }
return 0;
return promised_stream_id;
} }
int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags, int nghttp2_submit_window_update(nghttp2_session *session, uint8_t flags,
@ -404,11 +447,11 @@ static uint8_t set_request_flags(const nghttp2_priority_spec *pri_spec,
return flags; return flags;
} }
int nghttp2_submit_request(nghttp2_session *session, int32_t nghttp2_submit_request(nghttp2_session *session,
const nghttp2_priority_spec *pri_spec, const nghttp2_priority_spec *pri_spec,
const nghttp2_nv *nva, size_t nvlen, const nghttp2_nv *nva, size_t nvlen,
const nghttp2_data_provider *data_prd, const nghttp2_data_provider *data_prd,
void *stream_user_data) void *stream_user_data)
{ {
uint8_t flags; uint8_t flags;

View File

@ -89,6 +89,17 @@ void print_session_id(int64_t id)
} }
} // namespace } // namespace
namespace {
void append_nv(Stream *stream, const std::vector<nghttp2_nv>& nva)
{
for(auto& nv : nva) {
http2::split_add_header(stream->headers,
nv.name, nv.namelen, nv.value, nv.valuelen,
nv.flags & NGHTTP2_NV_FLAG_NO_INDEX);
}
}
} // namespace
Config::Config() Config::Config()
: stream_read_timeout{60, 0}, : stream_read_timeout{60, 0},
stream_write_timeout{60, 0}, stream_write_timeout{60, 0},
@ -851,9 +862,22 @@ int Http2Handler::submit_push_promise(Stream *stream,
http2::make_nv_ll(":scheme", "https"), http2::make_nv_ll(":scheme", "https"),
http2::make_nv_ls(":authority", (*itr).value) http2::make_nv_ls(":authority", (*itr).value)
}; };
return nghttp2_submit_push_promise(session_, NGHTTP2_FLAG_END_HEADERS,
stream->stream_id, nva.data(), nva.size(), auto promised_stream_id =
nullptr); nghttp2_submit_push_promise(session_, NGHTTP2_FLAG_END_HEADERS,
stream->stream_id, nva.data(), nva.size(),
nullptr);
if(promised_stream_id < 0) {
return promised_stream_id;
}
auto promised_stream = util::make_unique<Stream>(this, promised_stream_id);
append_nv(promised_stream.get(), http2::sort_nva(nva.data(), nva.size()));
add_stream(promised_stream_id, std::move(promised_stream));
return 0;
} }
int Http2Handler::submit_rst_stream(Stream *stream, int Http2Handler::submit_rst_stream(Stream *stream,
@ -1121,17 +1145,6 @@ void prepare_response(Stream *stream, Http2Handler *hd, bool allow_push = true)
} }
} // namespace } // namespace
namespace {
void append_nv(Stream *stream, const std::vector<nghttp2_nv>& nva)
{
for(auto& nv : nva) {
http2::split_add_header(stream->headers,
nv.name, nv.namelen, nv.value, nv.valuelen,
nv.flags & NGHTTP2_NV_FLAG_NO_INDEX);
}
}
} // namespace
namespace { namespace {
const char *REQUIRED_HEADERS[] = { const char *REQUIRED_HEADERS[] = {
":method", ":path", ":scheme", nullptr ":method", ":path", ":scheme", nullptr
@ -1299,25 +1312,6 @@ int hd_on_frame_recv_callback
} }
} // namespace } // namespace
namespace {
int hd_before_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
auto hd = static_cast<Http2Handler*>(user_data);
if(frame->hd.type == NGHTTP2_PUSH_PROMISE) {
auto stream_id = frame->push_promise.promised_stream_id;
auto stream = util::make_unique<Stream>(hd, stream_id);
auto nva = http2::sort_nva(frame->push_promise.nva,
frame->push_promise.nvlen);
append_nv(stream.get(), nva);
hd->add_stream(stream_id, std::move(stream));
}
return 0;
}
} // namespace
namespace { namespace {
int hd_on_frame_send_callback int hd_on_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, (nghttp2_session *session, const nghttp2_frame *frame,
@ -1432,7 +1426,6 @@ void fill_callback(nghttp2_session_callbacks& callbacks, const Config *config)
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_frame_recv_callback = hd_on_frame_recv_callback; callbacks.on_frame_recv_callback = hd_on_frame_recv_callback;
callbacks.before_frame_send_callback = hd_before_frame_send_callback;
callbacks.on_frame_send_callback = hd_on_frame_send_callback; callbacks.on_frame_send_callback = hd_on_frame_send_callback;
if(config->verbose) { if(config->verbose) {
callbacks.on_invalid_frame_recv_callback = callbacks.on_invalid_frame_recv_callback =

View File

@ -43,19 +43,6 @@ Http2Session::~Http2Session()
nghttp2_session_del(session_); nghttp2_session_del(session_);
} }
namespace {
int before_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
auto client = static_cast<Client*>(user_data);
if(frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
client->on_request(frame->hd.stream_id);
}
return 0;
}
} // namespace
namespace { namespace {
int on_header_callback(nghttp2_session *session, int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame, const nghttp2_frame *frame,
@ -116,7 +103,6 @@ void Http2Session::on_connect()
int rv; int rv;
nghttp2_session_callbacks callbacks = {0}; nghttp2_session_callbacks callbacks = {0};
callbacks.before_frame_send_callback = before_frame_send_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_stream_close_callback = on_stream_close_callback;
@ -149,7 +135,6 @@ void Http2Session::on_connect()
void Http2Session::submit_request() void Http2Session::submit_request()
{ {
int rv;
auto config = client_->worker->config; auto config = client_->worker->config;
auto& nva = config->nva[client_->reqidx++]; auto& nva = config->nva[client_->reqidx++];
@ -157,9 +142,12 @@ void Http2Session::submit_request()
client_->reqidx = 0; client_->reqidx = 0;
} }
rv = nghttp2_submit_request(session_, nullptr, nva.data(), nva.size(), auto stream_id = nghttp2_submit_request(session_, nullptr,
nullptr, nullptr); nva.data(), nva.size(),
assert(rv == 0); nullptr, nullptr);
assert(stream_id > 0);
client_->on_request(stream_id);
} }
ssize_t Http2Session::on_read() ssize_t Http2Session::on_read()

View File

@ -196,7 +196,7 @@ struct Request {
Request(const std::string& uri, const http_parser_url &u, Request(const std::string& uri, const http_parser_url &u,
const nghttp2_data_provider *data_prd, int64_t data_length, const nghttp2_data_provider *data_prd, int64_t data_length,
const nghttp2_priority_spec& pri_spec, const nghttp2_priority_spec& pri_spec,
std::shared_ptr<Dependency> dep, int level = 0) std::shared_ptr<Dependency> dep, int pri = 0, int level = 0)
: uri(uri), : uri(uri),
u(u), u(u),
dep(std::move(dep)), dep(std::move(dep)),
@ -208,7 +208,7 @@ struct Request {
data_prd(data_prd), data_prd(data_prd),
stream_id(-1), stream_id(-1),
level(level), level(level),
pri(0) pri(pri)
{} {}
~Request() ~Request()
@ -402,11 +402,6 @@ int submit_request
Request *req); Request *req);
} // namespace } // namespace
namespace {
void check_stream_id(nghttp2_session *session, int32_t stream_id,
void *user_data);
} // namespace
namespace { namespace {
void settings_timeout_cb(evutil_socket_t fd, short what, void *arg); void settings_timeout_cb(evutil_socket_t fd, short what, void *arg);
} // namespace } // namespace
@ -735,7 +730,8 @@ struct HttpClient {
return -1; return -1;
} }
if(stream_user_data) { if(stream_user_data) {
check_stream_id(session, 1, this); stream_user_data->stream_id = 1;
on_request(stream_user_data);
} }
} }
// Send connection header here // Send connection header here
@ -869,7 +865,7 @@ struct HttpClient {
int64_t data_length, int64_t data_length,
const nghttp2_priority_spec& pri_spec, const nghttp2_priority_spec& pri_spec,
std::shared_ptr<Dependency> dep, std::shared_ptr<Dependency> dep,
int level = 0) int pri = 0, int level = 0)
{ {
http_parser_url u; http_parser_url u;
memset(&u, 0, sizeof(u)); memset(&u, 0, sizeof(u));
@ -886,7 +882,7 @@ struct HttpClient {
reqvec.push_back(util::make_unique<Request>(uri, u, data_prd, reqvec.push_back(util::make_unique<Request>(uri, u, data_prd,
data_length, data_length,
pri_spec, std::move(dep), pri_spec, std::move(dep),
level)); pri, level));
return true; return true;
} }
} }
@ -926,6 +922,44 @@ struct HttpClient {
return true; return true;
} }
void on_request(Request *req)
{
streams[req->stream_id] = req;
req->record_request_time();
if(req->pri == 0 && req->dep) {
assert(req->dep->deps.empty());
req->dep->deps.push_back(std::vector<Request*>{req});
return;
}
if(req->stream_id % 2 == 0) {
return;
}
auto itr = std::begin(req->dep->deps);
for(; itr != std::end(req->dep->deps); ++itr) {
if((*itr)[0]->pri == req->pri) {
(*itr).push_back(req);
break;
}
if((*itr)[0]->pri > req->pri) {
auto v = std::vector<Request*>{req};
req->dep->deps.insert(itr, std::move(v));
break;
}
}
if(itr == std::end(req->dep->deps)) {
req->dep->deps.push_back(std::vector<Request*>{req});
}
}
}; };
} // namespace } // namespace
@ -1030,13 +1064,18 @@ int submit_request
nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index)); nva.push_back(http2::make_nv(kv.name, kv.value, kv.no_index));
} }
auto rv = nghttp2_submit_request(client->session, &req->pri_spec, auto stream_id = nghttp2_submit_request(client->session, &req->pri_spec,
nva.data(), nva.size(), req->data_prd, req); nva.data(), nva.size(),
if(rv != 0) { req->data_prd, req);
if(stream_id < 0) {
std::cerr << "nghttp2_submit_request() returned error: " std::cerr << "nghttp2_submit_request() returned error: "
<< nghttp2_strerror(rv) << std::endl; << nghttp2_strerror(stream_id) << std::endl;
return -1; return -1;
} }
req->stream_id = stream_id;
client->on_request(req);
return 0; return 0;
} }
} // namespace } // namespace
@ -1052,6 +1091,8 @@ void update_html_parser(HttpClient *client, Request *req,
for(auto& p : req->html_parser->get_links()) { for(auto& p : req->html_parser->get_links()) {
auto uri = strip_fragment(p.first.c_str()); auto uri = strip_fragment(p.first.c_str());
auto pri = p.second;
http_parser_url u; http_parser_url u;
memset(&u, 0, sizeof(u)); memset(&u, 0, sizeof(u));
if(http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 && if(http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) == 0 &&
@ -1059,18 +1100,10 @@ void update_html_parser(HttpClient *client, Request *req,
util::fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_HOST) && util::fieldeq(uri.c_str(), u, req->uri.c_str(), req->u, UF_HOST) &&
util::porteq(uri.c_str(), u, req->uri.c_str(), req->u)) { util::porteq(uri.c_str(), u, req->uri.c_str(), req->u)) {
// No POST data for assets // No POST data for assets
auto pri_spec = req->resolve_dep(pri);
nghttp2_priority_spec pri_spec;
// We adjust the priority using separate PRIORITY frame after
// stream ID becomes known.
nghttp2_priority_spec_default_init(&pri_spec);
if ( client->add_request(uri, nullptr, 0, pri_spec, req->dep, if ( client->add_request(uri, nullptr, 0, pri_spec, req->dep,
req->level+1) ) { pri, req->level+1) ) {
auto& req = client->reqvec.back();
req->pri = p.second;
submit_request(client, config.headers, submit_request(client, config.headers,
client->reqvec.back().get()); client->reqvec.back().get());
@ -1181,52 +1214,6 @@ int on_data_chunk_recv_callback
} }
} // namespace } // namespace
namespace {
void check_stream_id(nghttp2_session *session, int32_t stream_id,
void *user_data)
{
auto client = get_session(user_data);
auto req = (Request*)nghttp2_session_get_stream_user_data(session,
stream_id);
assert(req);
req->stream_id = stream_id;
client->streams[stream_id] = req;
req->record_request_time();
if(req->pri == 0 && req->dep) {
assert(req->dep->deps.empty());
req->dep->deps.push_back(std::vector<Request*>{req});
return;
}
if(stream_id % 2 == 0) {
return;
}
auto itr = std::begin(req->dep->deps);
for(; itr != std::end(req->dep->deps); ++itr) {
if((*itr)[0]->pri == req->pri) {
(*itr).push_back(req);
break;
}
if((*itr)[0]->pri > req->pri) {
auto v = std::vector<Request*>{req};
req->dep->deps.insert(itr, std::move(v));
break;
}
}
if(itr == std::end(req->dep->deps)) {
req->dep->deps.push_back(std::vector<Request*>{req});
}
}
} // namespace
namespace { namespace {
void settings_timeout_cb(evutil_socket_t fd, short what, void *arg) void settings_timeout_cb(evutil_socket_t fd, short what, void *arg)
{ {
@ -1240,35 +1227,6 @@ void settings_timeout_cb(evutil_socket_t fd, short what, void *arg)
} }
} // namespace } // namespace
namespace {
int adjust_priority_callback
(nghttp2_session *session, const nghttp2_frame *frame,
nghttp2_priority_spec *pri_spec, void *user_data)
{
auto req = (Request*)nghttp2_session_get_stream_user_data
(session, frame->hd.stream_id);
auto pri_spec_adjusted = req->resolve_dep(req->pri);
if(!nghttp2_priority_spec_check_default(&pri_spec_adjusted)) {
*pri_spec = pri_spec_adjusted;
}
return 0;
}
} // namespace
namespace {
int before_frame_send_callback
(nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
{
if(frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
check_stream_id(session, frame->hd.stream_id, user_data);
}
return 0;
}
} // namespace
namespace { namespace {
ssize_t select_padding_callback ssize_t select_padding_callback
(nghttp2_session *session, const nghttp2_frame *frame, size_t max_payload, (nghttp2_session *session, const nghttp2_frame *frame, size_t max_payload,
@ -1323,9 +1281,13 @@ int on_begin_headers_callback(nghttp2_session *session,
auto req = util::make_unique<Request>("", u, nullptr, 0, pri_spec, auto req = util::make_unique<Request>("", u, nullptr, 0, pri_spec,
nullptr); nullptr);
req->stream_id = stream_id;
nghttp2_session_set_stream_user_data(session, stream_id, req.get()); nghttp2_session_set_stream_user_data(session, stream_id, req.get());
client->on_request(req.get());
client->reqvec.push_back(std::move(req)); client->reqvec.push_back(std::move(req));
check_stream_id(session, stream_id, user_data);
break; break;
} }
} }
@ -1868,7 +1830,6 @@ int run(char **uris, int n)
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback2; callbacks.on_frame_recv_callback = on_frame_recv_callback2;
callbacks.before_frame_send_callback = before_frame_send_callback;
if(config.verbose) { if(config.verbose) {
callbacks.on_frame_send_callback = verbose_on_frame_send_callback; callbacks.on_frame_send_callback = verbose_on_frame_send_callback;
callbacks.on_invalid_frame_recv_callback = callbacks.on_invalid_frame_recv_callback =
@ -1882,7 +1843,6 @@ int run(char **uris, int n)
if(config.padding) { if(config.padding) {
callbacks.select_padding_callback = select_padding_callback; callbacks.select_padding_callback = select_padding_callback;
} }
callbacks.adjust_priority_callback = adjust_priority_callback;
std::string prev_scheme; std::string prev_scheme;
std::string prev_host; std::string prev_host;

View File

@ -588,16 +588,18 @@ int Http2Session::submit_request(Http2DownstreamConnection *dconn,
assert(state_ == CONNECTED); assert(state_ == CONNECTED);
auto sd = util::make_unique<StreamData>(); auto sd = util::make_unique<StreamData>();
// TODO Specify nullptr to pri_spec for now // TODO Specify nullptr to pri_spec for now
int rv = nghttp2_submit_request(session_, nullptr, nva, nvlen, auto stream_id = nghttp2_submit_request(session_, nullptr, nva, nvlen,
data_prd, sd.get()); data_prd, sd.get());
if(rv == 0) { if(stream_id < 0) {
dconn->attach_stream_data(sd.get());
streams_.insert(sd.release());
} else {
SSLOG(FATAL, this) << "nghttp2_submit_request() failed: " SSLOG(FATAL, this) << "nghttp2_submit_request() failed: "
<< nghttp2_strerror(rv); << nghttp2_strerror(stream_id);
return -1; return -1;
} }
dconn->attach_stream_data(sd.get());
dconn->get_downstream()->set_downstream_stream_id(stream_id);
streams_.insert(sd.release());
return 0; return 0;
} }
@ -1082,31 +1084,6 @@ int on_data_chunk_recv_callback(nghttp2_session *session,
} }
} // namespace } // namespace
namespace {
int before_frame_send_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data)
{
auto http2session = static_cast<Http2Session*>(user_data);
if(frame->hd.type == NGHTTP2_HEADERS &&
frame->headers.cat == NGHTTP2_HCAT_REQUEST) {
auto sd = static_cast<StreamData*>
(nghttp2_session_get_stream_user_data(session, frame->hd.stream_id));
if(!sd || !sd->dconn) {
http2session->submit_rst_stream(frame->hd.stream_id, NGHTTP2_CANCEL);
return 0;
}
auto downstream = sd->dconn->get_downstream();
if(downstream) {
downstream->set_downstream_stream_id(frame->hd.stream_id);
} else {
http2session->submit_rst_stream(frame->hd.stream_id, NGHTTP2_CANCEL);
}
}
return 0;
}
} // namespace
namespace { namespace {
int on_frame_send_callback(nghttp2_session* session, int on_frame_send_callback(nghttp2_session* session,
const nghttp2_frame *frame, void *user_data) const nghttp2_frame *frame, void *user_data)
@ -1205,7 +1182,6 @@ int Http2Session::on_connect()
callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback; callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.before_frame_send_callback = before_frame_send_callback;
callbacks.on_frame_send_callback = on_frame_send_callback; callbacks.on_frame_send_callback = on_frame_send_callback;
callbacks.on_frame_not_send_callback = on_frame_not_send_callback; callbacks.on_frame_not_send_callback = on_frame_not_send_callback;
callbacks.on_unknown_frame_recv_callback = on_unknown_frame_recv_callback; callbacks.on_unknown_frame_recv_callback = on_unknown_frame_recv_callback;

View File

@ -97,7 +97,8 @@ void test_nghttp2_frame_pack_headers()
nghttp2_frame_headers_init(&frame, nghttp2_frame_headers_init(&frame,
NGHTTP2_FLAG_END_STREAM | NGHTTP2_FLAG_END_STREAM |
NGHTTP2_FLAG_END_HEADERS, NGHTTP2_FLAG_END_HEADERS,
1000000007, &pri_spec, nva, nvlen); 1000000007, NGHTTP2_HCAT_REQUEST,
&pri_spec, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
nghttp2_bufs_rewind(&bufs); nghttp2_bufs_rewind(&bufs);
@ -194,7 +195,8 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
nghttp2_hd_deflate_init(&deflater); nghttp2_hd_deflate_init(&deflater);
nghttp2_frame_headers_init(&frame, nghttp2_frame_headers_init(&frame,
NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS, NGHTTP2_FLAG_END_STREAM|NGHTTP2_FLAG_END_HEADERS,
1000000007, NULL, nva, nvlen); 1000000007, NGHTTP2_HCAT_REQUEST,
NULL, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame, &deflater);
CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == rv); CU_ASSERT(NGHTTP2_ERR_HEADER_COMP == rv);

View File

@ -411,7 +411,7 @@ void test_nghttp2_session_recv(void)
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv)); nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
1, NULL, nva, nvlen); 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -437,7 +437,7 @@ void test_nghttp2_session_recv(void)
/* Received HEADERS without header block, which is valid */ /* Received HEADERS without header block, which is valid */
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS,
5, NULL, NULL, 0); 5, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -510,7 +510,7 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
nghttp2_hd_deflate_init(&deflater); nghttp2_hd_deflate_init(&deflater);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
NULL, NULL, 0); NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -556,7 +556,7 @@ void test_nghttp2_session_recv_invalid_frame(void)
nghttp2_hd_deflate_init(&deflater); nghttp2_hd_deflate_init(&deflater);
nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv)); nvlen = nghttp2_nv_array_copy(&nva, nv, ARRLEN(nv));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NULL, nva, nvlen); NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -809,7 +809,7 @@ void test_nghttp2_session_recv_continuation(void)
/* Make 1 HEADERS and insert CONTINUATION header */ /* Make 1 HEADERS and insert CONTINUATION header */
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1)); nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
NULL, nva, nvlen); NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -871,7 +871,7 @@ void test_nghttp2_session_recv_continuation(void)
/* HEADERS without END_HEADERS flag */ /* HEADERS without END_HEADERS flag */
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1)); nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_NONE, 1,
NULL, nva, nvlen); NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
nghttp2_bufs_reset(&bufs); nghttp2_bufs_reset(&bufs);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
@ -952,7 +952,7 @@ void test_nghttp2_session_recv_headers_with_priority(void)
nghttp2_frame_headers_init(&frame.headers, nghttp2_frame_headers_init(&frame.headers,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
3, &pri_spec, nva, nvlen); 3, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
@ -986,7 +986,7 @@ void test_nghttp2_session_recv_headers_with_priority(void)
nghttp2_frame_headers_init(&frame.headers, nghttp2_frame_headers_init(&frame.headers,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
5, &pri_spec, nva, nvlen); 5, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
@ -1032,7 +1032,7 @@ void test_nghttp2_session_recv_headers_with_priority(void)
nghttp2_frame_headers_init(&frame.headers, nghttp2_frame_headers_init(&frame.headers,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1, &pri_spec, nva, nvlen); 1, NGHTTP2_HCAT_HEADERS, &pri_spec, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
@ -1095,7 +1095,7 @@ void test_nghttp2_session_recv_premature_headers(void)
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1)); nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NULL, nva, nvlen); NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -1259,7 +1259,7 @@ void test_nghttp2_session_continue(void)
/* Make 2 HEADERS frames */ /* Make 2 HEADERS frames */
nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1)); nvlen = nghttp2_nv_array_copy(&nva, nv1, ARRLEN(nv1));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NULL, nva, nvlen); NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
CU_ASSERT(0 == rv); CU_ASSERT(0 == rv);
@ -1275,7 +1275,7 @@ void test_nghttp2_session_continue(void)
nvlen = nghttp2_nv_array_copy(&nva, nv2, ARRLEN(nv2)); nvlen = nghttp2_nv_array_copy(&nva, nv2, ARRLEN(nv2));
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
NULL, nva, nvlen); NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
nghttp2_bufs_reset(&bufs); nghttp2_bufs_reset(&bufs);
rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater); rv = nghttp2_frame_pack_headers(&bufs, &frame.headers, &deflater);
@ -1439,7 +1439,10 @@ void test_nghttp2_session_add_frame(void)
nghttp2_frame_headers_init(&frame->headers, nghttp2_frame_headers_init(&frame->headers,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
-1, NULL, nva, nvlen); session->next_stream_id,
NGHTTP2_HCAT_REQUEST, NULL, nva, nvlen);
session->next_stream_id += 2;
CU_ASSERT(0 == nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, CU_ASSERT(0 == nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame,
aux_data)); aux_data));
@ -1477,7 +1480,8 @@ void test_nghttp2_session_on_request_headers_received(void)
nghttp2_frame_headers_init(&frame.headers, nghttp2_frame_headers_init(&frame.headers,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
stream_id, &pri_spec, NULL, 0); stream_id, NGHTTP2_HCAT_REQUEST, &pri_spec,
NULL, 0);
user_data.begin_headers_cb_called = 0; user_data.begin_headers_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0;
@ -1495,7 +1499,7 @@ void test_nghttp2_session_on_request_headers_received(void)
nghttp2_frame_headers_init(&frame.headers, nghttp2_frame_headers_init(&frame.headers,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_HEADERS |
NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_PRIORITY,
3, NULL, NULL, 0); 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
user_data.invalid_frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_request_headers_received(session, &frame)); nghttp2_session_on_request_headers_received(session, &frame));
@ -1511,7 +1515,7 @@ void test_nghttp2_session_on_request_headers_received(void)
nghttp2_frame_headers_init(&frame.headers, nghttp2_frame_headers_init(&frame.headers,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_END_HEADERS |
NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_PRIORITY,
3, NULL, NULL, 0); 3, NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
user_data.invalid_frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
nghttp2_session_on_request_headers_received(session, &frame)); nghttp2_session_on_request_headers_received(session, &frame));
@ -1528,7 +1532,7 @@ void test_nghttp2_session_on_request_headers_received(void)
nvlen = nghttp2_nv_array_copy(&nva, malformed_nva, ARRLEN(malformed_nva)); nvlen = nghttp2_nv_array_copy(&nva, malformed_nva, ARRLEN(malformed_nva));
nghttp2_frame_headers_init(&frame.headers, nghttp2_frame_headers_init(&frame.headers,
NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY, NGHTTP2_FLAG_END_HEADERS | NGHTTP2_FLAG_PRIORITY,
1, NULL, nva, nvlen); 1, NGHTTP2_HCAT_HEADERS, NULL, nva, nvlen);
user_data.begin_headers_cb_called = 0; user_data.begin_headers_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0;
CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame)); CU_ASSERT(0 == nghttp2_session_on_request_headers_received(session, &frame));
@ -1557,7 +1561,7 @@ void test_nghttp2_session_on_response_headers_received(void)
&pri_spec_default, &pri_spec_default,
NGHTTP2_STREAM_OPENING, NULL); NGHTTP2_STREAM_OPENING, NULL);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NULL, NULL, 0); NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
user_data.begin_headers_cb_called = 0; user_data.begin_headers_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0;
@ -1589,7 +1593,7 @@ void test_nghttp2_session_on_headers_received(void)
NGHTTP2_STREAM_OPENED, NULL); NGHTTP2_STREAM_OPENED, NULL);
nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR); nghttp2_stream_shutdown(stream, NGHTTP2_SHUT_WR);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 1,
NULL, NULL, 0); NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
user_data.begin_headers_cb_called = 0; user_data.begin_headers_cb_called = 0;
user_data.invalid_frame_recv_cb_called = 0; user_data.invalid_frame_recv_cb_called = 0;
@ -1661,7 +1665,7 @@ void test_nghttp2_session_on_push_response_headers_received(void)
&pri_spec_default, &pri_spec_default,
NGHTTP2_STREAM_RESERVED, NULL); NGHTTP2_STREAM_RESERVED, NULL);
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 2,
NULL, NULL, 0); NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
/* nghttp2_session_on_push_response_headers_received assumes /* nghttp2_session_on_push_response_headers_received assumes
stream's state is NGHTTP2_STREAM_RESERVED and session->server is stream's state is NGHTTP2_STREAM_RESERVED and session->server is
0. */ 0. */
@ -2324,8 +2328,12 @@ void test_nghttp2_session_send_headers_start_stream(void)
callbacks.send_callback = null_send_callback; callbacks.send_callback = null_send_callback;
nghttp2_session_client_new(&session, &callbacks, NULL); nghttp2_session_client_new(&session, &callbacks, NULL);
nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, -1,
NULL, NULL, 0); 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_frame(session, NGHTTP2_CAT_CTRL, frame, aux_data);
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
stream = nghttp2_session_get_stream(session, 1); stream = nghttp2_session_get_stream(session, 1);
@ -2349,7 +2357,7 @@ void test_nghttp2_session_send_headers_reply(void)
&pri_spec_default, &pri_spec_default,
NGHTTP2_STREAM_OPENING, NULL); NGHTTP2_STREAM_OPENING, NULL);
nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2, nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
NULL, NULL, 0); NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL); nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
stream = nghttp2_session_get_stream(session, 2); stream = nghttp2_session_get_stream(session, 2);
@ -2386,8 +2394,11 @@ void test_nghttp2_session_send_headers_header_comp_error(void)
nghttp2_session_client_new(&session, &callbacks, NULL); nghttp2_session_client_new(&session, &callbacks, NULL);
nvlen = nghttp2_nv_array_copy(&nva, nv, nnv); nvlen = nghttp2_nv_array_copy(&nva, nv, nnv);
nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, -1, nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS,
NULL, nva, nvlen); 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_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
@ -2416,7 +2427,7 @@ void test_nghttp2_session_send_headers_push_reply(void)
&pri_spec_default, &pri_spec_default,
NGHTTP2_STREAM_RESERVED, NULL); NGHTTP2_STREAM_RESERVED, NULL);
nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2, nghttp2_frame_headers_init(&frame->headers, NGHTTP2_FLAG_END_HEADERS, 2,
NULL, NULL, 0); NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL); nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
CU_ASSERT(0 == session->num_outgoing_streams); CU_ASSERT(0 == session->num_outgoing_streams);
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
@ -2468,8 +2479,12 @@ void test_nghttp2_session_send_push_promise(void)
&pri_spec_default, NGHTTP2_STREAM_OPENING, &pri_spec_default, NGHTTP2_STREAM_OPENING,
NULL); NULL);
nghttp2_frame_push_promise_init(&frame->push_promise, nghttp2_frame_push_promise_init(&frame->push_promise,
NGHTTP2_FLAG_END_HEADERS, 1, -1, NGHTTP2_FLAG_END_HEADERS, 1,
session->next_stream_id,
NULL, 0); NULL, 0);
session->next_stream_id += 2;
nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL); nghttp2_session_add_frame(session, NGHTTP2_CAT_CTRL, frame, NULL);
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
@ -2747,7 +2762,7 @@ void test_nghttp2_submit_request_with_data(void)
data_prd.read_callback = fixed_length_data_source_read_callback; data_prd.read_callback = fixed_length_data_source_read_callback;
ud.data_source_length = 64*1024 - 1; ud.data_source_length = 64*1024 - 1;
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
CU_ASSERT(0 == nghttp2_submit_request(session, NULL, CU_ASSERT(1 == nghttp2_submit_request(session, NULL,
nva, ARRLEN(nva), &data_prd, NULL)); nva, ARRLEN(nva), &data_prd, NULL));
item = nghttp2_session_get_next_ob_item(session); item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0])); CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
@ -2783,7 +2798,7 @@ void test_nghttp2_submit_request_without_data(void)
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
nghttp2_hd_inflate_init(&inflater); nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(0 == nghttp2_submit_request(session, NULL, CU_ASSERT(1 == nghttp2_submit_request(session, NULL,
nva, ARRLEN(nva), &data_prd, NULL)); nva, ARRLEN(nva), &data_prd, NULL));
item = nghttp2_session_get_next_ob_item(session); item = nghttp2_session_get_next_ob_item(session);
CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0])); CU_ASSERT(nvnameeq(":version", &OB_CTRL(item)->headers.nva[0]));
@ -2895,7 +2910,7 @@ void test_nghttp2_submit_headers_start_stream(void)
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL)); CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, NULL));
CU_ASSERT(0 == nghttp2_submit_headers(session, CU_ASSERT(1 == nghttp2_submit_headers(session,
NGHTTP2_FLAG_END_STREAM, NGHTTP2_FLAG_END_STREAM,
-1, NULL, -1, NULL,
nv, ARRLEN(nv), NULL)); nv, ARRLEN(nv), NULL));
@ -3110,7 +3125,7 @@ void test_nghttp2_submit_headers_continuation(void)
callbacks.on_frame_send_callback = on_frame_send_callback; callbacks.on_frame_send_callback = on_frame_send_callback;
CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud)); CU_ASSERT(0 == nghttp2_session_client_new(&session, &callbacks, &ud));
CU_ASSERT(0 == nghttp2_submit_headers(session, CU_ASSERT(1 == nghttp2_submit_headers(session,
NGHTTP2_FLAG_END_STREAM, NGHTTP2_FLAG_END_STREAM,
-1, NULL, -1, NULL,
nv, ARRLEN(nv), NULL)); nv, ARRLEN(nv), NULL));
@ -3363,7 +3378,7 @@ void test_nghttp2_submit_push_promise(void)
nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE, nghttp2_session_open_stream(session, 1, NGHTTP2_STREAM_FLAG_NONE,
&pri_spec_default, &pri_spec_default,
NGHTTP2_STREAM_OPENING, NULL); NGHTTP2_STREAM_OPENING, NULL);
CU_ASSERT(0 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1, CU_ASSERT(2 == nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 1,
nv, ARRLEN(nv), &ud)); nv, ARRLEN(nv), &ud));
ud.frame_send_cb_called = 0; ud.frame_send_cb_called = 0;
@ -3606,7 +3621,7 @@ void test_nghttp2_submit_invalid_nv(void)
CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL)); CU_ASSERT(0 == nghttp2_session_server_new(&session, &callbacks, NULL));
/* nghttp2_submit_request */ /* nghttp2_submit_request */
CU_ASSERT(0 == CU_ASSERT(0 <
nghttp2_submit_request(session, NULL, nghttp2_submit_request(session, NULL,
empty_name_nv, ARRLEN(empty_name_nv), empty_name_nv, ARRLEN(empty_name_nv),
NULL, NULL)); NULL, NULL));
@ -3618,14 +3633,14 @@ void test_nghttp2_submit_invalid_nv(void)
NULL)); NULL));
/* nghttp2_submit_headers */ /* nghttp2_submit_headers */
CU_ASSERT(0 == CU_ASSERT(0 <
nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1, nghttp2_submit_headers(session, NGHTTP2_FLAG_NONE, -1,
NULL, NULL,
empty_name_nv, ARRLEN(empty_name_nv), empty_name_nv, ARRLEN(empty_name_nv),
NULL)); NULL));
/* nghttp2_submit_push_promise */ /* nghttp2_submit_push_promise */
CU_ASSERT(0 == CU_ASSERT(0 <
nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 2, nghttp2_submit_push_promise(session, NGHTTP2_FLAG_NONE, 2,
empty_name_nv, ARRLEN(empty_name_nv), empty_name_nv, ARRLEN(empty_name_nv),
NULL)); NULL));
@ -3862,7 +3877,7 @@ void test_nghttp2_session_max_concurrent_streams(void)
/* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */ /* Check un-ACKed SETTINGS_MAX_CONCURRENT_STREAMS */
nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3, nghttp2_frame_headers_init(&frame.headers, NGHTTP2_FLAG_END_HEADERS, 3,
NULL, NULL, 0); NGHTTP2_HCAT_HEADERS, NULL, NULL, 0);
session->pending_local_max_concurrent_stream = 1; session->pending_local_max_concurrent_stream = 1;
CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK == CU_ASSERT(NGHTTP2_ERR_IGN_HEADER_BLOCK ==
@ -4412,19 +4427,19 @@ void test_nghttp2_session_on_ctrl_not_send(void)
CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0); CU_ASSERT(nghttp2_session_client_new(&session, &callbacks, &user_data) == 0);
/* Maximum Stream ID is reached */ /* Maximum Stream ID is reached */
session->next_stream_id = (1u << 31)+1; session->next_stream_id = (1u << 31)+1;
CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1, CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE ==
NULL, NULL, 0, NULL)); nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
CU_ASSERT(0 == nghttp2_session_send(session)); NULL, NULL, 0, NULL));
CU_ASSERT(1 == user_data.frame_not_send_cb_called);
CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
CU_ASSERT(NGHTTP2_ERR_STREAM_ID_NOT_AVAILABLE == user_data.not_sent_error);
user_data.frame_not_send_cb_called = 0; user_data.frame_not_send_cb_called = 0;
/* Send GOAWAY */ /* Send GOAWAY */
CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE, CU_ASSERT(0 == nghttp2_submit_goaway(session, NGHTTP2_FLAG_NONE,
NGHTTP2_NO_ERROR, NULL, 0)); NGHTTP2_NO_ERROR, NULL, 0));
CU_ASSERT(0 == nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
NULL, NULL, 0, NULL)); session->next_stream_id = 9;
CU_ASSERT(0 < nghttp2_submit_headers(session, NGHTTP2_FLAG_END_STREAM, -1,
NULL, NULL, 0, NULL));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(1 == user_data.frame_not_send_cb_called); CU_ASSERT(1 == user_data.frame_not_send_cb_called);
CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type); CU_ASSERT(NGHTTP2_HEADERS == user_data.not_sent_frame_type);
@ -4740,7 +4755,7 @@ void test_nghttp2_session_pack_headers_with_padding(void)
ud.padding_boundary = 16385; ud.padding_boundary = 16385;
CU_ASSERT(0 == CU_ASSERT(1 ==
nghttp2_submit_request(session, NULL, nghttp2_submit_request(session, NULL,
nva, ARRLEN(nva), NULL, NULL)); nva, ARRLEN(nva), NULL, NULL));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
@ -4753,7 +4768,7 @@ void test_nghttp2_session_pack_headers_with_padding(void)
CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session)); CU_ASSERT(NULL == nghttp2_session_get_next_ob_item(sv_session));
/* Check PUSH_PROMISE */ /* Check PUSH_PROMISE */
CU_ASSERT(0 == CU_ASSERT(2 ==
nghttp2_submit_push_promise(sv_session, NGHTTP2_FLAG_NONE, 1, nghttp2_submit_push_promise(sv_session, NGHTTP2_FLAG_NONE, 1,
nva, ARRLEN(nva), NULL)); nva, ARRLEN(nva), NULL));
acc.length = 0; acc.length = 0;
@ -4802,7 +4817,7 @@ void test_nghttp2_session_pack_headers_with_padding2(void)
ud.padding_boundary = 16385; ud.padding_boundary = 16385;
CU_ASSERT(0 == CU_ASSERT(1 ==
nghttp2_submit_request(session, NULL, nghttp2_submit_request(session, NULL,
nva, ARRLEN(nva), NULL, NULL)); nva, ARRLEN(nva), NULL, NULL));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
@ -4852,7 +4867,7 @@ void test_nghttp2_session_pack_headers_with_padding3(void)
ud.padding_boundary = 16385; ud.padding_boundary = 16385;
CU_ASSERT(0 == CU_ASSERT(1 ==
nghttp2_submit_request(session, NULL, nghttp2_submit_request(session, NULL,
nva, ARRLEN(nva), NULL, NULL)); nva, ARRLEN(nva), NULL, NULL));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
@ -4891,7 +4906,7 @@ void test_nghttp2_session_pack_headers_with_padding4(void)
ud.padding_boundary = 16385; ud.padding_boundary = 16385;
CU_ASSERT(0 == CU_ASSERT(1 ==
nghttp2_submit_request(session, NULL, nghttp2_submit_request(session, NULL,
&nv, 1, NULL, NULL)); &nv, 1, NULL, NULL));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));