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;
}
/*
* 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,
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));
callbacks->send_callback = send_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_recv_callback = on_frame_recv_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)
{
int rv;
int32_t stream_id;
const nghttp2_nv nva[] = {
/* Make sure that the last item is NULL */
MAKE_NV(":method", "GET"),
@@ -480,11 +456,17 @@ static void submit_request(struct Connection *connection, struct Request *req)
MAKE_NV("accept", "*/*"),
MAKE_NV("user-agent", "nghttp2/"NGHTTP2_VERSION)
};
rv = nghttp2_submit_request(connection->session, NULL,
nva, sizeof(nva)/sizeof(nva[0]), NULL, req);
if(rv != 0) {
diec("nghttp2_submit_request", rv);
stream_id = nghttp2_submit_request(connection->session, NULL,
nva, sizeof(nva)/sizeof(nva[0]),
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;
}
/* 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
single header name/value pair. */
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));
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_data_chunk_recv_callback = on_data_chunk_recv_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 */
static void submit_request(http2_session_data *session_data)
{
int rv;
int32_t stream_id;
http2_stream_data *stream_data = session_data->stream_data;
const char *uri = stream_data->uri;
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");
print_headers(stderr, hdrs, ARRLEN(hdrs));
rv = nghttp2_submit_request(session_data->session, NULL,
hdrs, ARRLEN(hdrs), NULL, stream_data);
if(rv != 0) {
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(rv));
stream_id = nghttp2_submit_request(session_data->session, NULL,
hdrs, ARRLEN(hdrs), NULL, stream_data);
if(stream_id < 0) {
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