Update doc

This commit is contained in:
Tatsuhiro Tsujikawa 2014-01-29 21:57:16 +09:00
parent cd0b716f08
commit de27a9bf03
10 changed files with 362 additions and 488 deletions

View File

@ -820,6 +820,16 @@ Types (structs, unions and typedefs)
respectively. The header name/value pairs are emitted via respectively. The header name/value pairs are emitted via
:type:`nghttp2_on_header_callback`. :type:`nghttp2_on_header_callback`.
For HEADERS, PUSH_PROMISE and DATA frames, this callback may be
called after stream is closed (see
:type:`nghttp2_on_stream_close_callback`). The application should
check that stream is still alive using its own stream management or
:func:`nghttp2_session_get_stream_user_data()`.
Only HEADERS and DATA frame can signal the end of incoming data. If
``frame->hd.flags & NGHTTP2_FLAG_END_STREAM`` is nonzero, the
*frame* is the last frame from the remote peer in this stream.
The implementation of this function must return 0 if it The implementation of this function must return 0 if it
succeeds. If nonzero value is returned, it is treated as fatal succeeds. If nonzero value is returned, it is treated as fatal
error and `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` error and `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`
@ -840,10 +850,6 @@ Types (structs, unions and typedefs)
member of their data structure are always ``NULL`` and 0 member of their data structure are always ``NULL`` and 0
respectively. respectively.
If this callback is called, :type:`nghttp2_on_header_callback` and
:type:`nghttp2_on_end_headers_callback` will not be called for this
frame.
The implementation of this function must return 0 if it The implementation of this function must return 0 if it
succeeds. If nonzero is returned, it is treated as fatal error and succeeds. If nonzero is returned, it is treated as fatal error and
`nghttp2_session_recv()` and `nghttp2_session_send()` functions `nghttp2_session_recv()` and `nghttp2_session_send()` functions
@ -935,21 +941,6 @@ Types (structs, unions and typedefs)
`nghttp2_session_recv()` and `nghttp2_session_send()` functions `nghttp2_session_recv()` and `nghttp2_session_send()` functions
immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`.
.. type:: typedef int (*nghttp2_on_request_recv_callback) (nghttp2_session *session, int32_t stream_id, void *user_data)
Callback function invoked when the request from the remote peer is
received. In other words, the frame with END_STREAM flag set is
received. In HTTP, this means HTTP request, including request
body, is fully received. The *user_data* pointer is the third
argument passed in to the call to `nghttp2_session_client_new()` or
`nghttp2_session_server_new()`.
The implementation of this function must return 0 if it
succeeds. If nonzero is returned, it is treated as fatal error and
`nghttp2_session_recv()` and `nghttp2_session_send()` functions
immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`.
.. type:: typedef int (*nghttp2_on_unknown_frame_recv_callback) (nghttp2_session *session, const uint8_t *head, size_t headlen, const uint8_t *payload, size_t payloadlen, void *user_data) .. type:: typedef int (*nghttp2_on_unknown_frame_recv_callback) (nghttp2_session *session, const uint8_t *head, size_t headlen, const uint8_t *payload, size_t payloadlen, void *user_data)
@ -969,6 +960,27 @@ Types (structs, unions and typedefs)
`nghttp2_session_recv()` and `nghttp2_session_send()` functions `nghttp2_session_recv()` and `nghttp2_session_send()` functions
immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`.
.. type:: typedef int (*nghttp2_on_begin_headers_callback) (nghttp2_session *session, const nghttp2_frame *frame, void *user_data)
Callback function invoked when the reception of header block in
HEADERS or PUSH_PROMISE is started. Each header name/value pair
will be emitted by :type:`nghttp2_on_header_callback`.
The ``frame->hd.flags`` may not have
:macro:`NGHTTP2_FLAG_END_HEADERS` flag set, which indicates that one
or more CONTINUATION frames are involved. But the application does
not need to care about that because the header name/value pairs are
emitted transparently regardless of CONTINUATION frames.
The implementation of this function must return 0 if it succeeds or
:macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. If nonzero value other than
:macro:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, it is treated as
if :macro:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. If
:macro:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,
`nghttp2_session_mem_recv()` function will immediately return
:macro:`NGHTTP2_ERR_CALLBACK_FAILURE`.
.. type:: typedef int (*nghttp2_on_header_callback) (nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, void *user_data) .. type:: typedef int (*nghttp2_on_header_callback) (nghttp2_session *session, const nghttp2_frame *frame, const uint8_t *name, size_t namelen, const uint8_t *value, size_t valuelen, void *user_data)
@ -976,9 +988,11 @@ Types (structs, unions and typedefs)
for the *frame*. When this callback is invoked, ``frame->hd.type`` for the *frame*. When this callback is invoked, ``frame->hd.type``
is either :macro:`NGHTTP2_HEADERS` or :macro:`NGHTTP2_PUSH_PROMISE`. is either :macro:`NGHTTP2_HEADERS` or :macro:`NGHTTP2_PUSH_PROMISE`.
After all header name/value pairs are processed with this callback, After all header name/value pairs are processed with this callback,
or header decompression error occurred, then and no error has been detected,
:type:`nghttp2_on_end_headers_callback` will be invoked unless :type:`nghttp2_on_frame_recv_callback` will be invoked. If there
application returns nonzero value from this callback. is an error in decompression,
:type:`nghttp2_on_frame_recv_callback` for the *frame* will not be
invoked.
The *name* may be ``NULL`` if the *namelen* is 0. The same thing The *name* may be ``NULL`` if the *namelen* is 0. The same thing
can be said about the *value*. can be said about the *value*.
@ -995,7 +1009,7 @@ Types (structs, unions and typedefs)
Returning :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close Returning :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close
the stream by issuing RST_STREAM with the stream by issuing RST_STREAM with
:macro:`NGHTTP2_INTERNAL_ERROR`. In this case, :macro:`NGHTTP2_INTERNAL_ERROR`. In this case,
:type:`nghttp2_on_end_headers_callback` will not be invoked. :type:`nghttp2_on_frame_recv_callback` will not be invoked.
The implementation of this function must return 0 if it The implementation of this function must return 0 if it
succeeds. It may return :macro:`NGHTTP2_ERR_PAUSE` or succeeds. It may return :macro:`NGHTTP2_ERR_PAUSE` or
@ -1007,26 +1021,6 @@ Types (structs, unions and typedefs)
`nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions `nghttp2_session_recv()` and `nghttp2_session_mem_recv()` functions
immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`. immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`.
.. type:: typedef int (*nghttp2_on_end_headers_callback) (nghttp2_session *session, const nghttp2_frame *frame, nghttp2_error_code error_code, void *user_data)
Callback function invoked when all header name/value pairs are
processed or after the header decompression error is detected. If
the *error_code* is :macro:`NGHTTP2_NO_ERROR`, it indicates the
header decompression succeeded. Otherwise, error prevented the
completion of the header decompression. In this case, the library
will handle the error by either transmitting RST_STREAM or GOAWAY
and terminate session.
If the *error_code* is not :macro:`NGHTTP2_NO_ERROR`, then
:type:`nghttp2_on_request_recv_callback` will not called for this
frame if the *frame* is HEADERS.
The implementation of this function must return 0 if it
succeeds. If nonzero value is returned, it is treated as fatal
error and `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`
functions immediately return :macro:`NGHTTP2_ERR_CALLBACK_FAILURE`.
.. type:: nghttp2_session_callbacks .. type:: nghttp2_session_callbacks
@ -1065,22 +1059,18 @@ Types (structs, unions and typedefs)
.. member:: nghttp2_on_stream_close_callback on_stream_close_callback .. member:: nghttp2_on_stream_close_callback on_stream_close_callback
Callback function invoked when the stream is closed. Callback function invoked when the stream is closed.
.. member:: nghttp2_on_request_recv_callback on_request_recv_callback
Callback function invoked when request from the remote peer is
received.
.. member:: nghttp2_on_unknown_frame_recv_callback on_unknown_frame_recv_callback .. member:: nghttp2_on_unknown_frame_recv_callback on_unknown_frame_recv_callback
Callback function invoked when the received frame type is Callback function invoked when the received frame type is
unknown. unknown.
.. member:: nghttp2_on_begin_headers_callback on_begin_headers_callback
Callback function invoked when the reception of header block in
HEADERS or PUSH_PROMISE is started.
.. member:: nghttp2_on_header_callback on_header_callback .. member:: nghttp2_on_header_callback on_header_callback
Callback function invoked when a header name/value pair is Callback function invoked when a header name/value pair is
received. received.
.. member:: nghttp2_on_end_headers_callback on_end_headers_callback
Callback function invoked when all header name/value pairs are
processed.
.. type:: nghttp2_opt_set .. type:: nghttp2_opt_set
@ -1260,9 +1250,7 @@ Functions
is invoked. is invoked.
2. If one DATA frame is completely received, 2. If one DATA frame is completely received,
:member:`nghttp2_session_callbacks.on_frame_recv_callback` is :member:`nghttp2_session_callbacks.on_frame_recv_callback` is
invoked. If the frame is the final frame of the request, invoked. If the reception of the frame triggers the
:member:`nghttp2_session_callbacks.on_request_recv_callback`
is invoked. If the reception of the frame triggers the
closure of the stream, closure of the stream,
:member:`nghttp2_session_callbacks.on_stream_close_callback` :member:`nghttp2_session_callbacks.on_stream_close_callback`
is invoked. is invoked.
@ -1271,17 +1259,20 @@ Functions
1. :member:`nghttp2_session_callbacks.recv_callback` is invoked 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked
one or more times to receive whole frame. one or more times to receive whole frame.
2. If the received frame is valid,
:member:`nghttp2_session_callbacks.on_frame_recv_callback` is 2. If the received frame is valid, then following actions are
invoked. If frame is either HEADERS or PUSH_PROMISE, taken. If the frame is either HEADERS or PUSH_PROMISE,
:member:`nghttp2_session_callbacks.on_begin_headers_callback`
is invoked. Then
:member:`nghttp2_session_callbacks.on_header_callback` is :member:`nghttp2_session_callbacks.on_header_callback` is
invoked for each header name/value pair. After all name/value invoked for each header name/value pair. After all name/value
pairs are emitted (or decompression failed), pairs are emitted successfully,
:member:`nghttp2_session_callbacks.on_end_headers_callback` :member:`nghttp2_session_callbacks.on_frame_recv_callback` is
is invoked. If the frame is the final frame of the request, invoked. For other frames,
:member:`nghttp2_session_callbacks.on_request_recv_callback` :member:`nghttp2_session_callbacks.on_frame_recv_callback` is
is invoked. If the reception of the frame triggers the invoked.
closure of the stream, If the reception of the frame triggers the closure of the
stream,
:member:`nghttp2_session_callbacks.on_stream_close_callback` :member:`nghttp2_session_callbacks.on_stream_close_callback`
is invoked. is invoked.
3. If the received frame is unpacked but is interpreted as 3. If the received frame is unpacked but is interpreted as

View File

@ -164,7 +164,7 @@ finished successfully. We first initialize nghttp2 session object in
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;
callbacks.on_header_callback = on_header_callback; callbacks.on_header_callback = on_header_callback;
callbacks.on_end_headers_callback = on_end_headers_callback; callbacks.on_begin_headers_callback = on_begin_headers_callback;
nghttp2_session_client_new(&session_data->session, &callbacks, session_data); nghttp2_session_client_new(&session_data->session, &callbacks, session_data);
} }
@ -386,30 +386,6 @@ multiple streams, and *stream_user_data* is very handy to identify
which HEADERS we are seeing in the callback. Therefore we just show which HEADERS we are seeing in the callback. Therefore we just show
how to use it here. how to use it here.
The ``on_frame_recv_callback()`` function is invoked when a frame is
received from the remote peer::
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
fprintf(stderr, "Response headers for stream ID=%d:\n",
frame->hd.stream_id);
}
break;
}
return 0;
}
In this tutorial, we are just interested in the HTTP response
HEADERS. We check te frame type and its category (it should be
:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check
its stream ID.
Each request header name/value pair is emitted via Each request header name/value pair is emitted via
``on_header_callback`` function:: ``on_header_callback`` function::
@ -435,27 +411,27 @@ Each request header name/value pair is emitted via
In this turotial, we just print the name/value pair. In this turotial, we just print the name/value pair.
After all name/value pairs are emitted for a frame, After all name/value pairs are emitted for a frame,
``on_end_headers_callback`` function is called:: ``on_frame_recv_callback`` function is called::
static int on_end_headers_callback(nghttp2_session *session, static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, const nghttp2_frame *frame, void *user_data)
nghttp2_error_code error_code,
void *user_data)
{ {
http2_session_data *session_data = (http2_session_data*)user_data; http2_session_data *session_data = (http2_session_data*)user_data;
switch(frame->hd.type) { switch(frame->hd.type) {
case NGHTTP2_HEADERS: case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE && if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) { session_data->stream_data->stream_id == frame->hd.stream_id) {
fprintf(stderr, "All headers received with error_code=%d\n", error_code); fprintf(stderr, "All headers received\n");
} }
break; break;
} }
return 0; return 0;
} }
This callback may be called prematurely because of errors (e.g., In this tutorial, we are just interested in the HTTP response
header decompression failure) which is indicated by ``error_code``. HEADERS. We check te frame type and its category (it should be
:macro:`NGHTTP2_HCAT_RESPONSE` for HTTP response HEADERS). Also check
its stream ID.
The ``on_data_chunk_recv_callback()`` function is invoked when a chunk The ``on_data_chunk_recv_callback()`` function is invoked when a chunk
of data is received from the remote peer:: of data is received from the remote peer::

View File

@ -241,9 +241,9 @@ We initialize nghttp2 session object which is done in
callbacks.send_callback = send_callback; callbacks.send_callback = send_callback;
callbacks.on_frame_recv_callback = on_frame_recv_callback; callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_request_recv_callback = on_request_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback; callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_header_callback = on_header_callback; callbacks.on_header_callback = on_header_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback;
nghttp2_session_server_new(&session_data->session, &callbacks, session_data); nghttp2_session_server_new(&session_data->session, &callbacks, session_data);
} }
@ -414,26 +414,23 @@ We have already described about nghttp2 callback ``send_callback()``.
Let's describe remaining nghttp2 callbacks we setup in Let's describe remaining nghttp2 callbacks we setup in
``initialize_nghttp2_setup()`` function. ``initialize_nghttp2_setup()`` function.
The ``on_frame_recv_callback()`` function is invoked when a frame is The ``on_begin_headers_callback()`` function is invoked when reception
received from the remote peer:: of header block in HEADERS or PUSH_PROMISE frame is started::
static int on_frame_recv_callback(nghttp2_session *session, static int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data) const nghttp2_frame *frame,
void *user_data)
{ {
http2_session_data *session_data = (http2_session_data*)user_data; http2_session_data *session_data = (http2_session_data*)user_data;
http2_stream_data *stream_data; http2_stream_data *stream_data;
switch(frame->hd.type) {
case NGHTTP2_HEADERS: if(frame->hd.type != NGHTTP2_HEADERS ||
if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) { frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
break; return 0;
}
stream_data = create_http2_stream_data(session_data, frame->hd.stream_id);
nghttp2_session_set_stream_user_data(session, frame->hd.stream_id,
stream_data);
break;
default:
break;
} }
stream_data = create_http2_stream_data(session_data, frame->hd.stream_id);
nghttp2_session_set_stream_user_data(session, frame->hd.stream_id,
stream_data);
return 0; return 0;
} }
@ -448,7 +445,7 @@ order to get the object without searching through doubly linked list.
In this example server, we want to serve files relative to the current In this example server, we want to serve files relative to the current
working directory the program was invoked. Each header name/value pair working directory the program was invoked. Each header name/value pair
is emitted via ``on_header_callback`` function, which is called after is emitted via ``on_header_callback`` function, which is called after
``on_frame_recv_callback()``:: ``on_begin_headers_callback()``::
static int on_header_callback(nghttp2_session *session, static int on_header_callback(nghttp2_session *session,
const nghttp2_frame *frame, const nghttp2_frame *frame,
@ -483,60 +480,37 @@ requested path in ``http2_stream_data`` object. In this example
program, we ignore ``:method`` header field and always treat the program, we ignore ``:method`` header field and always treat the
request as GET request. request as GET request.
It is ok for the server to start sending response in this callback (or The ``on_frame_recv_callback()`` function is invoked when a frame is
in `nghttp2_on_end_headers_callback()`, which is not used in this fully received::
tutorial). In this example, we defer it to
``on_request_recv_callback()`` function.
The ``on_request_recv_callback()`` function is invoked when all HTTP static int on_frame_recv_callback(nghttp2_session *session,
request, including entity body, was received:: const nghttp2_frame *frame, void *user_data)
static int on_request_recv_callback(nghttp2_session *session,
int32_t stream_id, void *user_data)
{ {
int fd;
http2_session_data *session_data = (http2_session_data*)user_data; http2_session_data *session_data = (http2_session_data*)user_data;
http2_stream_data *stream_data; http2_stream_data *stream_data;
nghttp2_nv hdrs[] = { switch(frame->hd.type) {
MAKE_NV(":status", "200") case NGHTTP2_DATA:
}; case NGHTTP2_HEADERS:
char *rel_path; /* Check that the client request has finished */
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream_data = (http2_stream_data*)nghttp2_session_get_stream_user_data stream_data = nghttp2_session_get_stream_user_data(session,
(session, stream_id); frame->hd.stream_id);
if(!stream_data->request_path) { /* For DATA and HEADERS frame, this callback may be called after
if(error_reply(session, stream_data) != 0) { on_stream_close_callback. Check that stream still alive. */
return NGHTTP2_ERR_CALLBACK_FAILURE; if(!stream_data) {
return 0;
}
return on_request_recv(session, session_data, stream_data);
} }
return 0; break;
} default:
fprintf(stderr, "%s GET %s\n", session_data->client_addr, break;
stream_data->request_path);
if(!check_path(stream_data->request_path)) {
if(error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
for(rel_path = stream_data->request_path; *rel_path == '/'; ++rel_path);
fd = open(rel_path, O_RDONLY);
if(fd == -1) {
if(error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
}
return 0;
}
stream_data->fd = fd;
if(send_response(session, stream_id, hdrs, ARRLEN(hdrs), fd) != 0) {
close(fd);
return NGHTTP2_ERR_CALLBACK_FAILURE;
} }
return 0; return 0;
} }
First we retrieve ``http2_stream_data`` object associated to the First we retrieve ``http2_stream_data`` object associated to the
stream in ``on_frame_recv_callback()``. It is done using stream in ``on_begin_headers_callback()``. It is done using
`nghttp2_session_get_stream_user_data()`. If the requested path cannot `nghttp2_session_get_stream_user_data()`. If the requested path cannot
be served for some reasons (e.g., file is not found), we send 404 be served for some reasons (e.g., file is not found), we send 404
response, which is done in ``error_reply()``. Otherwise, we open response, which is done in ``error_reply()``. Otherwise, we open

View File

@ -1331,6 +1331,14 @@ in to the call to <a class="reference internal" href="#nghttp2_session_client_ne
member of their data structure are always <tt class="docutils literal"><span class="pre">NULL</span></tt> and 0 member of their data structure are always <tt class="docutils literal"><span class="pre">NULL</span></tt> and 0
respectively. The header name/value pairs are emitted via respectively. The header name/value pairs are emitted via
<a class="reference internal" href="#nghttp2_on_header_callback" title="nghttp2_on_header_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_header_callback</span></tt></a>.</p> <a class="reference internal" href="#nghttp2_on_header_callback" title="nghttp2_on_header_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_header_callback</span></tt></a>.</p>
<p>For HEADERS, PUSH_PROMISE and DATA frames, this callback may be
called after stream is closed (see
<a class="reference internal" href="#nghttp2_on_stream_close_callback" title="nghttp2_on_stream_close_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_stream_close_callback</span></tt></a>). The application should
check that stream is still alive using its own stream management or
<a class="reference internal" href="#nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a>.</p>
<p>Only HEADERS and DATA frame can signal the end of incoming data. If
<tt class="docutils literal"><span class="pre">frame-&gt;hd.flags</span> <span class="pre">&amp;</span> <span class="pre">NGHTTP2_FLAG_END_STREAM</span></tt> is nonzero, the
<em>frame</em> is the last frame from the remote peer in this stream.</p>
<p>The implementation of this function must return 0 if it <p>The implementation of this function must return 0 if it
succeeds. If nonzero value is returned, it is treated as fatal succeeds. If nonzero value is returned, it is treated as fatal
error and <a class="reference internal" href="#nghttp2_session_recv" title="nghttp2_session_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_recv()</span></tt></a> and <a class="reference internal" href="#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> error and <a class="reference internal" href="#nghttp2_session_recv" title="nghttp2_session_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_recv()</span></tt></a> and <a class="reference internal" href="#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a>
@ -1350,9 +1358,6 @@ third argument passed in to the call to
<p>If frame is HEADERS or PUSH_PROMISE, the <tt class="docutils literal"><span class="pre">nva</span></tt> and <tt class="docutils literal"><span class="pre">nvlen</span></tt> <p>If frame is HEADERS or PUSH_PROMISE, the <tt class="docutils literal"><span class="pre">nva</span></tt> and <tt class="docutils literal"><span class="pre">nvlen</span></tt>
member of their data structure are always <tt class="docutils literal"><span class="pre">NULL</span></tt> and 0 member of their data structure are always <tt class="docutils literal"><span class="pre">NULL</span></tt> and 0
respectively.</p> respectively.</p>
<p>If this callback is called, <a class="reference internal" href="#nghttp2_on_header_callback" title="nghttp2_on_header_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_header_callback</span></tt></a> and
<a class="reference internal" href="#nghttp2_on_end_headers_callback" title="nghttp2_on_end_headers_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_end_headers_callback</span></tt></a> will not be called for this
frame.</p>
<p>The implementation of this function must return 0 if it <p>The implementation of this function must return 0 if it
succeeds. If nonzero is returned, it is treated as fatal error and succeeds. If nonzero is returned, it is treated as fatal error and
<a class="reference internal" href="#nghttp2_session_recv" title="nghttp2_session_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_recv()</span></tt></a> and <a class="reference internal" href="#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> functions <a class="reference internal" href="#nghttp2_session_recv" title="nghttp2_session_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_recv()</span></tt></a> and <a class="reference internal" href="#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> functions
@ -1444,21 +1449,6 @@ succeeds. If nonzero is returned, it is treated as fatal error and
immediately return <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p> immediately return <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p>
</dd></dl> </dd></dl>
<dl class="type">
<dt id="nghttp2_on_request_recv_callback">
typedef int <tt class="descname">(*nghttp2_on_request_recv_callback)</tt><big>(</big><a class="reference internal" href="#nghttp2_session" title="nghttp2_session">nghttp2_session</a><em>&nbsp;*session</em>, int32_t<em>&nbsp;stream_id</em>, void<em>&nbsp;*user_data</em><big>)</big><a class="headerlink" href="#nghttp2_on_request_recv_callback" title="Permalink to this definition"></a></dt>
<dd><p>Callback function invoked when the request from the remote peer is
received. In other words, the frame with END_STREAM flag set is
received. In HTTP, this means HTTP request, including request
body, is fully received. The <em>user_data</em> pointer is the third
argument passed in to the call to <a class="reference internal" href="#nghttp2_session_client_new" title="nghttp2_session_client_new"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_client_new()</span></tt></a> or
<a class="reference internal" href="#nghttp2_session_server_new" title="nghttp2_session_server_new"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_server_new()</span></tt></a>.</p>
<p>The implementation of this function must return 0 if it
succeeds. If nonzero is returned, it is treated as fatal error and
<a class="reference internal" href="#nghttp2_session_recv" title="nghttp2_session_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_recv()</span></tt></a> and <a class="reference internal" href="#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> functions
immediately return <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p>
</dd></dl>
<dl class="type"> <dl class="type">
<dt id="nghttp2_on_unknown_frame_recv_callback"> <dt id="nghttp2_on_unknown_frame_recv_callback">
typedef int <tt class="descname">(*nghttp2_on_unknown_frame_recv_callback)</tt><big>(</big><a class="reference internal" href="#nghttp2_session" title="nghttp2_session">nghttp2_session</a><em>&nbsp;*session</em>, const uint8_t<em>&nbsp;*head</em>, size_t<em>&nbsp;headlen</em>, const uint8_t<em>&nbsp;*payload</em>, size_t<em>&nbsp;payloadlen</em>, void<em>&nbsp;*user_data</em><big>)</big><a class="headerlink" href="#nghttp2_on_unknown_frame_recv_callback" title="Permalink to this definition"></a></dt> typedef int <tt class="descname">(*nghttp2_on_unknown_frame_recv_callback)</tt><big>(</big><a class="reference internal" href="#nghttp2_session" title="nghttp2_session">nghttp2_session</a><em>&nbsp;*session</em>, const uint8_t<em>&nbsp;*head</em>, size_t<em>&nbsp;headlen</em>, const uint8_t<em>&nbsp;*payload</em>, size_t<em>&nbsp;payloadlen</em>, void<em>&nbsp;*user_data</em><big>)</big><a class="headerlink" href="#nghttp2_on_unknown_frame_recv_callback" title="Permalink to this definition"></a></dt>
@ -1478,6 +1468,26 @@ succeeds. If nonzero is returned, it is treated as fatal error and
immediately return <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p> immediately return <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p>
</dd></dl> </dd></dl>
<dl class="type">
<dt id="nghttp2_on_begin_headers_callback">
typedef int <tt class="descname">(*nghttp2_on_begin_headers_callback)</tt><big>(</big><a class="reference internal" href="#nghttp2_session" title="nghttp2_session">nghttp2_session</a><em>&nbsp;*session</em>, const <a class="reference internal" href="#nghttp2_frame" title="nghttp2_frame">nghttp2_frame</a><em>&nbsp;*frame</em>, void<em>&nbsp;*user_data</em><big>)</big><a class="headerlink" href="#nghttp2_on_begin_headers_callback" title="Permalink to this definition"></a></dt>
<dd><p>Callback function invoked when the reception of header block in
HEADERS or PUSH_PROMISE is started. Each header name/value pair
will be emitted by <a class="reference internal" href="#nghttp2_on_header_callback" title="nghttp2_on_header_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_header_callback</span></tt></a>.</p>
<p>The <tt class="docutils literal"><span class="pre">frame-&gt;hd.flags</span></tt> may not have
<a class="reference internal" href="#NGHTTP2_FLAG_END_HEADERS" title="NGHTTP2_FLAG_END_HEADERS"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_FLAG_END_HEADERS</span></tt></a> flag set, which indicates that one
or more CONTINUATION frames are involved. But the application does
not need to care about that because the header name/value pairs are
emitted transparently regardless of CONTINUATION frames.</p>
<p>The implementation of this function must return 0 if it succeeds or
<a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>. If nonzero value other than
<a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a> is returned, it is treated as
if <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a> is returned. If
<a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a> is returned,
<a class="reference internal" href="#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a> function will immediately return
<a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p>
</dd></dl>
<dl class="type"> <dl class="type">
<dt id="nghttp2_on_header_callback"> <dt id="nghttp2_on_header_callback">
typedef int <tt class="descname">(*nghttp2_on_header_callback)</tt><big>(</big><a class="reference internal" href="#nghttp2_session" title="nghttp2_session">nghttp2_session</a><em>&nbsp;*session</em>, const <a class="reference internal" href="#nghttp2_frame" title="nghttp2_frame">nghttp2_frame</a><em>&nbsp;*frame</em>, const uint8_t<em>&nbsp;*name</em>, size_t<em>&nbsp;namelen</em>, const uint8_t<em>&nbsp;*value</em>, size_t<em>&nbsp;valuelen</em>, void<em>&nbsp;*user_data</em><big>)</big><a class="headerlink" href="#nghttp2_on_header_callback" title="Permalink to this definition"></a></dt> typedef int <tt class="descname">(*nghttp2_on_header_callback)</tt><big>(</big><a class="reference internal" href="#nghttp2_session" title="nghttp2_session">nghttp2_session</a><em>&nbsp;*session</em>, const <a class="reference internal" href="#nghttp2_frame" title="nghttp2_frame">nghttp2_frame</a><em>&nbsp;*frame</em>, const uint8_t<em>&nbsp;*name</em>, size_t<em>&nbsp;namelen</em>, const uint8_t<em>&nbsp;*value</em>, size_t<em>&nbsp;valuelen</em>, void<em>&nbsp;*user_data</em><big>)</big><a class="headerlink" href="#nghttp2_on_header_callback" title="Permalink to this definition"></a></dt>
@ -1485,9 +1495,11 @@ typedef int <tt class="descname">(*nghttp2_on_header_callback)</tt><big>(</big><
for the <em>frame</em>. When this callback is invoked, <tt class="docutils literal"><span class="pre">frame-&gt;hd.type</span></tt> for the <em>frame</em>. When this callback is invoked, <tt class="docutils literal"><span class="pre">frame-&gt;hd.type</span></tt>
is either <a class="reference internal" href="#NGHTTP2_HEADERS" title="NGHTTP2_HEADERS"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_HEADERS</span></tt></a> or <a class="reference internal" href="#NGHTTP2_PUSH_PROMISE" title="NGHTTP2_PUSH_PROMISE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_PUSH_PROMISE</span></tt></a>. is either <a class="reference internal" href="#NGHTTP2_HEADERS" title="NGHTTP2_HEADERS"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_HEADERS</span></tt></a> or <a class="reference internal" href="#NGHTTP2_PUSH_PROMISE" title="NGHTTP2_PUSH_PROMISE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_PUSH_PROMISE</span></tt></a>.
After all header name/value pairs are processed with this callback, After all header name/value pairs are processed with this callback,
or header decompression error occurred, then and no error has been detected,
<a class="reference internal" href="#nghttp2_on_end_headers_callback" title="nghttp2_on_end_headers_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_end_headers_callback</span></tt></a> will be invoked unless <a class="reference internal" href="#nghttp2_on_frame_recv_callback" title="nghttp2_on_frame_recv_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_frame_recv_callback</span></tt></a> will be invoked. If there
application returns nonzero value from this callback.</p> is an error in decompression,
<a class="reference internal" href="#nghttp2_on_frame_recv_callback" title="nghttp2_on_frame_recv_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_frame_recv_callback</span></tt></a> for the <em>frame</em> will not be
invoked.</p>
<p>The <em>name</em> may be <tt class="docutils literal"><span class="pre">NULL</span></tt> if the <em>namelen</em> is 0. The same thing <p>The <em>name</em> may be <tt class="docutils literal"><span class="pre">NULL</span></tt> if the <em>namelen</em> is 0. The same thing
can be said about the <em>value</em>.</p> can be said about the <em>value</em>.</p>
<p>If the application uses <a class="reference internal" href="#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a>, it can return <p>If the application uses <a class="reference internal" href="#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a>, it can return
@ -1501,7 +1513,7 @@ region included in the input bytes.</p>
<p>Returning <a class="reference internal" href="#NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE" title="NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE</span></tt></a> will close <p>Returning <a class="reference internal" href="#NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE" title="NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE</span></tt></a> will close
the stream by issuing RST_STREAM with the stream by issuing RST_STREAM with
<a class="reference internal" href="#NGHTTP2_INTERNAL_ERROR" title="NGHTTP2_INTERNAL_ERROR"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_INTERNAL_ERROR</span></tt></a>. In this case, <a class="reference internal" href="#NGHTTP2_INTERNAL_ERROR" title="NGHTTP2_INTERNAL_ERROR"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_INTERNAL_ERROR</span></tt></a>. In this case,
<a class="reference internal" href="#nghttp2_on_end_headers_callback" title="nghttp2_on_end_headers_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_end_headers_callback</span></tt></a> will not be invoked.</p> <a class="reference internal" href="#nghttp2_on_frame_recv_callback" title="nghttp2_on_frame_recv_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_frame_recv_callback</span></tt></a> will not be invoked.</p>
<p>The implementation of this function must return 0 if it <p>The implementation of this function must return 0 if it
succeeds. It may return <a class="reference internal" href="#NGHTTP2_ERR_PAUSE" title="NGHTTP2_ERR_PAUSE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_PAUSE</span></tt></a> or succeeds. It may return <a class="reference internal" href="#NGHTTP2_ERR_PAUSE" title="NGHTTP2_ERR_PAUSE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_PAUSE</span></tt></a> or
<a class="reference internal" href="#NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE" title="NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE</span></tt></a>. For other critical <a class="reference internal" href="#NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE" title="NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE</span></tt></a>. For other critical
@ -1513,25 +1525,6 @@ the other nonzero value is returned, it is treated as
immediately return <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p> immediately return <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p>
</dd></dl> </dd></dl>
<dl class="type">
<dt id="nghttp2_on_end_headers_callback">
typedef int <tt class="descname">(*nghttp2_on_end_headers_callback)</tt><big>(</big><a class="reference internal" href="#nghttp2_session" title="nghttp2_session">nghttp2_session</a><em>&nbsp;*session</em>, const <a class="reference internal" href="#nghttp2_frame" title="nghttp2_frame">nghttp2_frame</a><em>&nbsp;*frame</em>, <a class="reference internal" href="#nghttp2_error_code" title="nghttp2_error_code">nghttp2_error_code</a><em>&nbsp;error_code</em>, void<em>&nbsp;*user_data</em><big>)</big><a class="headerlink" href="#nghttp2_on_end_headers_callback" title="Permalink to this definition"></a></dt>
<dd><p>Callback function invoked when all header name/value pairs are
processed or after the header decompression error is detected. If
the <em>error_code</em> is <a class="reference internal" href="#NGHTTP2_NO_ERROR" title="NGHTTP2_NO_ERROR"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_NO_ERROR</span></tt></a>, it indicates the
header decompression succeeded. Otherwise, error prevented the
completion of the header decompression. In this case, the library
will handle the error by either transmitting RST_STREAM or GOAWAY
and terminate session.</p>
<p>If the <em>error_code</em> is not <a class="reference internal" href="#NGHTTP2_NO_ERROR" title="NGHTTP2_NO_ERROR"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_NO_ERROR</span></tt></a>, then
<a class="reference internal" href="#nghttp2_on_request_recv_callback" title="nghttp2_on_request_recv_callback"><tt class="xref c c-type docutils literal"><span class="pre">nghttp2_on_request_recv_callback</span></tt></a> will not called for this
frame if the <em>frame</em> is HEADERS.</p>
<p>The implementation of this function must return 0 if it
succeeds. If nonzero value is returned, it is treated as fatal
error and <a class="reference internal" href="#nghttp2_session_recv" title="nghttp2_session_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_recv()</span></tt></a> and <a class="reference internal" href="#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a>
functions immediately return <a class="reference internal" href="#NGHTTP2_ERR_CALLBACK_FAILURE" title="NGHTTP2_ERR_CALLBACK_FAILURE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_CALLBACK_FAILURE</span></tt></a>.</p>
</dd></dl>
<dl class="type"> <dl class="type">
<dt id="nghttp2_session_callbacks"> <dt id="nghttp2_session_callbacks">
<tt class="descname">nghttp2_session_callbacks</tt><a class="headerlink" href="#nghttp2_session_callbacks" title="Permalink to this definition"></a></dt> <tt class="descname">nghttp2_session_callbacks</tt><a class="headerlink" href="#nghttp2_session_callbacks" title="Permalink to this definition"></a></dt>
@ -1596,13 +1589,6 @@ because of an error.</p>
<dd><p>Callback function invoked when the stream is closed.</p> <dd><p>Callback function invoked when the stream is closed.</p>
</dd></dl> </dd></dl>
<dl class="member">
<dt id="nghttp2_session_callbacks.on_request_recv_callback">
<a class="reference internal" href="#nghttp2_on_request_recv_callback" title="nghttp2_on_request_recv_callback">nghttp2_on_request_recv_callback</a> <tt class="descname">on_request_recv_callback</tt><a class="headerlink" href="#nghttp2_session_callbacks.on_request_recv_callback" title="Permalink to this definition"></a></dt>
<dd><p>Callback function invoked when request from the remote peer is
received.</p>
</dd></dl>
<dl class="member"> <dl class="member">
<dt id="nghttp2_session_callbacks.on_unknown_frame_recv_callback"> <dt id="nghttp2_session_callbacks.on_unknown_frame_recv_callback">
<a class="reference internal" href="#nghttp2_on_unknown_frame_recv_callback" title="nghttp2_on_unknown_frame_recv_callback">nghttp2_on_unknown_frame_recv_callback</a> <tt class="descname">on_unknown_frame_recv_callback</tt><a class="headerlink" href="#nghttp2_session_callbacks.on_unknown_frame_recv_callback" title="Permalink to this definition"></a></dt> <a class="reference internal" href="#nghttp2_on_unknown_frame_recv_callback" title="nghttp2_on_unknown_frame_recv_callback">nghttp2_on_unknown_frame_recv_callback</a> <tt class="descname">on_unknown_frame_recv_callback</tt><a class="headerlink" href="#nghttp2_session_callbacks.on_unknown_frame_recv_callback" title="Permalink to this definition"></a></dt>
@ -1610,6 +1596,13 @@ received.</p>
unknown.</p> unknown.</p>
</dd></dl> </dd></dl>
<dl class="member">
<dt id="nghttp2_session_callbacks.on_begin_headers_callback">
<a class="reference internal" href="#nghttp2_on_begin_headers_callback" title="nghttp2_on_begin_headers_callback">nghttp2_on_begin_headers_callback</a> <tt class="descname">on_begin_headers_callback</tt><a class="headerlink" href="#nghttp2_session_callbacks.on_begin_headers_callback" title="Permalink to this definition"></a></dt>
<dd><p>Callback function invoked when the reception of header block in
HEADERS or PUSH_PROMISE is started.</p>
</dd></dl>
<dl class="member"> <dl class="member">
<dt id="nghttp2_session_callbacks.on_header_callback"> <dt id="nghttp2_session_callbacks.on_header_callback">
<a class="reference internal" href="#nghttp2_on_header_callback" title="nghttp2_on_header_callback">nghttp2_on_header_callback</a> <tt class="descname">on_header_callback</tt><a class="headerlink" href="#nghttp2_session_callbacks.on_header_callback" title="Permalink to this definition"></a></dt> <a class="reference internal" href="#nghttp2_on_header_callback" title="nghttp2_on_header_callback">nghttp2_on_header_callback</a> <tt class="descname">on_header_callback</tt><a class="headerlink" href="#nghttp2_session_callbacks.on_header_callback" title="Permalink to this definition"></a></dt>
@ -1617,13 +1610,6 @@ unknown.</p>
received.</p> received.</p>
</dd></dl> </dd></dl>
<dl class="member">
<dt id="nghttp2_session_callbacks.on_end_headers_callback">
<a class="reference internal" href="#nghttp2_on_end_headers_callback" title="nghttp2_on_end_headers_callback">nghttp2_on_end_headers_callback</a> <tt class="descname">on_end_headers_callback</tt><a class="headerlink" href="#nghttp2_session_callbacks.on_end_headers_callback" title="Permalink to this definition"></a></dt>
<dd><p>Callback function invoked when all header name/value pairs are
processed.</p>
</dd></dl>
</dd></dl> </dd></dl>
<dl class="type"> <dl class="type">
@ -1810,9 +1796,7 @@ to receive DATA payload. For each chunk of data,
is invoked.</li> is invoked.</li>
<li>If one DATA frame is completely received, <li>If one DATA frame is completely received,
<a class="reference internal" href="#nghttp2_session_callbacks.on_frame_recv_callback" title="nghttp2_session_callbacks.on_frame_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_frame_recv_callback</span></tt></a> is <a class="reference internal" href="#nghttp2_session_callbacks.on_frame_recv_callback" title="nghttp2_session_callbacks.on_frame_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_frame_recv_callback</span></tt></a> is
invoked. If the frame is the final frame of the request, invoked. If the reception of the frame triggers the
<a class="reference internal" href="#nghttp2_session_callbacks.on_request_recv_callback" title="nghttp2_session_callbacks.on_request_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_request_recv_callback</span></tt></a>
is invoked. If the reception of the frame triggers the
closure of the stream, closure of the stream,
<a class="reference internal" href="#nghttp2_session_callbacks.on_stream_close_callback" title="nghttp2_session_callbacks.on_stream_close_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_stream_close_callback</span></tt></a> <a class="reference internal" href="#nghttp2_session_callbacks.on_stream_close_callback" title="nghttp2_session_callbacks.on_stream_close_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_stream_close_callback</span></tt></a>
is invoked.</li> is invoked.</li>
@ -1821,17 +1805,19 @@ is invoked.</li>
<li>If the frame is the control frame:<ol class="arabic"> <li>If the frame is the control frame:<ol class="arabic">
<li><a class="reference internal" href="#nghttp2_session_callbacks.recv_callback" title="nghttp2_session_callbacks.recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.recv_callback</span></tt></a> is invoked <li><a class="reference internal" href="#nghttp2_session_callbacks.recv_callback" title="nghttp2_session_callbacks.recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.recv_callback</span></tt></a> is invoked
one or more times to receive whole frame.</li> one or more times to receive whole frame.</li>
<li>If the received frame is valid, <li>If the received frame is valid, then following actions are
<a class="reference internal" href="#nghttp2_session_callbacks.on_frame_recv_callback" title="nghttp2_session_callbacks.on_frame_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_frame_recv_callback</span></tt></a> is taken. If the frame is either HEADERS or PUSH_PROMISE,
invoked. If frame is either HEADERS or PUSH_PROMISE, <a class="reference internal" href="#nghttp2_session_callbacks.on_begin_headers_callback" title="nghttp2_session_callbacks.on_begin_headers_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_begin_headers_callback</span></tt></a>
is invoked. Then
<a class="reference internal" href="#nghttp2_session_callbacks.on_header_callback" title="nghttp2_session_callbacks.on_header_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_header_callback</span></tt></a> is <a class="reference internal" href="#nghttp2_session_callbacks.on_header_callback" title="nghttp2_session_callbacks.on_header_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_header_callback</span></tt></a> is
invoked for each header name/value pair. After all name/value invoked for each header name/value pair. After all name/value
pairs are emitted (or decompression failed), pairs are emitted successfully,
<a class="reference internal" href="#nghttp2_session_callbacks.on_end_headers_callback" title="nghttp2_session_callbacks.on_end_headers_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_end_headers_callback</span></tt></a> <a class="reference internal" href="#nghttp2_session_callbacks.on_frame_recv_callback" title="nghttp2_session_callbacks.on_frame_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_frame_recv_callback</span></tt></a> is
is invoked. If the frame is the final frame of the request, invoked. For other frames,
<a class="reference internal" href="#nghttp2_session_callbacks.on_request_recv_callback" title="nghttp2_session_callbacks.on_request_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_request_recv_callback</span></tt></a> <a class="reference internal" href="#nghttp2_session_callbacks.on_frame_recv_callback" title="nghttp2_session_callbacks.on_frame_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_frame_recv_callback</span></tt></a> is
is invoked. If the reception of the frame triggers the invoked.
closure of the stream, If the reception of the frame triggers the closure of the
stream,
<a class="reference internal" href="#nghttp2_session_callbacks.on_stream_close_callback" title="nghttp2_session_callbacks.on_stream_close_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_stream_close_callback</span></tt></a> <a class="reference internal" href="#nghttp2_session_callbacks.on_stream_close_callback" title="nghttp2_session_callbacks.on_stream_close_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_stream_close_callback</span></tt></a>
is invoked.</li> is invoked.</li>
<li>If the received frame is unpacked but is interpreted as <li>If the received frame is unpacked but is interpreted as

View File

@ -606,18 +606,18 @@
<dt><a href="apiref.html#nghttp2_nv.valuelen">nghttp2_nv.valuelen (C member)</a> <dt><a href="apiref.html#nghttp2_nv.valuelen">nghttp2_nv.valuelen (C member)</a>
</dt> </dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="apiref.html#nghttp2_nv_compare_name">nghttp2_nv_compare_name (C function)</a> <dt><a href="apiref.html#nghttp2_nv_compare_name">nghttp2_nv_compare_name (C function)</a>
</dt> </dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="apiref.html#nghttp2_on_data_chunk_recv_callback">nghttp2_on_data_chunk_recv_callback (C type)</a> <dt><a href="apiref.html#nghttp2_on_begin_headers_callback">nghttp2_on_begin_headers_callback (C type)</a>
</dt> </dt>
<dt><a href="apiref.html#nghttp2_on_end_headers_callback">nghttp2_on_end_headers_callback (C type)</a> <dt><a href="apiref.html#nghttp2_on_data_chunk_recv_callback">nghttp2_on_data_chunk_recv_callback (C type)</a>
</dt> </dt>
@ -641,10 +641,6 @@
</dt> </dt>
<dt><a href="apiref.html#nghttp2_on_request_recv_callback">nghttp2_on_request_recv_callback (C type)</a>
</dt>
<dt><a href="apiref.html#nghttp2_on_stream_close_callback">nghttp2_on_stream_close_callback (C type)</a> <dt><a href="apiref.html#nghttp2_on_stream_close_callback">nghttp2_on_stream_close_callback (C type)</a>
</dt> </dt>
@ -805,11 +801,11 @@
</dt> </dt>
<dt><a href="apiref.html#nghttp2_session_callbacks.on_data_chunk_recv_callback">nghttp2_session_callbacks.on_data_chunk_recv_callback (C member)</a> <dt><a href="apiref.html#nghttp2_session_callbacks.on_begin_headers_callback">nghttp2_session_callbacks.on_begin_headers_callback (C member)</a>
</dt> </dt>
<dt><a href="apiref.html#nghttp2_session_callbacks.on_end_headers_callback">nghttp2_session_callbacks.on_end_headers_callback (C member)</a> <dt><a href="apiref.html#nghttp2_session_callbacks.on_data_chunk_recv_callback">nghttp2_session_callbacks.on_data_chunk_recv_callback (C member)</a>
</dt> </dt>
@ -833,10 +829,6 @@
</dt> </dt>
<dt><a href="apiref.html#nghttp2_session_callbacks.on_request_recv_callback">nghttp2_session_callbacks.on_request_recv_callback (C member)</a>
</dt>
<dt><a href="apiref.html#nghttp2_session_callbacks.on_stream_close_callback">nghttp2_session_callbacks.on_stream_close_callback (C member)</a> <dt><a href="apiref.html#nghttp2_session_callbacks.on_stream_close_callback">nghttp2_session_callbacks.on_stream_close_callback (C member)</a>
</dt> </dt>

View File

@ -1031,6 +1031,16 @@
<span class="cm"> * respectively. The header name/value pairs are emitted via</span> <span class="cm"> * respectively. The header name/value pairs are emitted via</span>
<span class="cm"> * :type:`nghttp2_on_header_callback`.</span> <span class="cm"> * :type:`nghttp2_on_header_callback`.</span>
<span class="cm"> *</span> <span class="cm"> *</span>
<span class="cm"> * For HEADERS, PUSH_PROMISE and DATA frames, this callback may be</span>
<span class="cm"> * called after stream is closed (see</span>
<span class="cm"> * :type:`nghttp2_on_stream_close_callback`). The application should</span>
<span class="cm"> * check that stream is still alive using its own stream management or</span>
<span class="cm"> * :func:`nghttp2_session_get_stream_user_data()`.</span>
<span class="cm"> *</span>
<span class="cm"> * Only HEADERS and DATA frame can signal the end of incoming data. If</span>
<span class="cm"> * ``frame-&gt;hd.flags &amp; NGHTTP2_FLAG_END_STREAM`` is nonzero, the</span>
<span class="cm"> * |frame| is the last frame from the remote peer in this stream.</span>
<span class="cm"> *</span>
<span class="cm"> * The implementation of this function must return 0 if it</span> <span class="cm"> * The implementation of this function must return 0 if it</span>
<span class="cm"> * succeeds. If nonzero value is returned, it is treated as fatal</span> <span class="cm"> * succeeds. If nonzero value is returned, it is treated as fatal</span>
<span class="cm"> * error and `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`</span> <span class="cm"> * error and `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`</span>
@ -1054,10 +1064,6 @@
<span class="cm"> * member of their data structure are always ``NULL`` and 0</span> <span class="cm"> * member of their data structure are always ``NULL`` and 0</span>
<span class="cm"> * respectively.</span> <span class="cm"> * respectively.</span>
<span class="cm"> *</span> <span class="cm"> *</span>
<span class="cm"> * If this callback is called, :type:`nghttp2_on_header_callback` and</span>
<span class="cm"> * :type:`nghttp2_on_end_headers_callback` will not be called for this</span>
<span class="cm"> * frame.</span>
<span class="cm"> *</span>
<span class="cm"> * The implementation of this function must return 0 if it</span> <span class="cm"> * The implementation of this function must return 0 if it</span>
<span class="cm"> * succeeds. If nonzero is returned, it is treated as fatal error and</span> <span class="cm"> * succeeds. If nonzero is returned, it is treated as fatal error and</span>
<span class="cm"> * `nghttp2_session_recv()` and `nghttp2_session_send()` functions</span> <span class="cm"> * `nghttp2_session_recv()` and `nghttp2_session_send()` functions</span>
@ -1171,24 +1177,6 @@
<span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="n">nghttp2_error_code</span> <span class="n">error_code</span><span class="p">,</span> <span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="n">nghttp2_error_code</span> <span class="n">error_code</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span>
<span class="cm">/**</span>
<span class="cm"> * @functypedef</span>
<span class="cm"> *</span>
<span class="cm"> * Callback function invoked when the request from the remote peer is</span>
<span class="cm"> * received. In other words, the frame with END_STREAM flag set is</span>
<span class="cm"> * received. In HTTP, this means HTTP request, including request</span>
<span class="cm"> * body, is fully received. The |user_data| pointer is the third</span>
<span class="cm"> * argument passed in to the call to `nghttp2_session_client_new()` or</span>
<span class="cm"> * `nghttp2_session_server_new()`.</span>
<span class="cm"> *</span>
<span class="cm"> * The implementation of this function must return 0 if it</span>
<span class="cm"> * succeeds. If nonzero is returned, it is treated as fatal error and</span>
<span class="cm"> * `nghttp2_session_recv()` and `nghttp2_session_send()` functions</span>
<span class="cm"> * immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.</span>
<span class="cm"> */</span>
<span class="k">typedef</span> <span class="nf">int</span> <span class="p">(</span><span class="o">*</span><span class="n">nghttp2_on_request_recv_callback</span><span class="p">)</span>
<span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span>
<span class="cm">/**</span> <span class="cm">/**</span>
<span class="cm"> * @functypedef</span> <span class="cm"> * @functypedef</span>
<span class="cm"> *</span> <span class="cm"> *</span>
@ -1214,6 +1202,30 @@
<span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">payload</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">payloadlen</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">payload</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">payloadlen</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span>
<span class="cm">/**</span>
<span class="cm"> * @functypedef</span>
<span class="cm"> *</span>
<span class="cm"> * Callback function invoked when the reception of header block in</span>
<span class="cm"> * HEADERS or PUSH_PROMISE is started. Each header name/value pair</span>
<span class="cm"> * will be emitted by :type:`nghttp2_on_header_callback`.</span>
<span class="cm"> *</span>
<span class="cm"> * The ``frame-&gt;hd.flags`` may not have</span>
<span class="cm"> * :enum:`NGHTTP2_FLAG_END_HEADERS` flag set, which indicates that one</span>
<span class="cm"> * or more CONTINUATION frames are involved. But the application does</span>
<span class="cm"> * not need to care about that because the header name/value pairs are</span>
<span class="cm"> * emitted transparently regardless of CONTINUATION frames.</span>
<span class="cm"> *</span>
<span class="cm"> * The implementation of this function must return 0 if it succeeds or</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`. If nonzero value other than</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned, it is treated as</span>
<span class="cm"> * if :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned. If</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE` is returned,</span>
<span class="cm"> * `nghttp2_session_mem_recv()` function will immediately return</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.</span>
<span class="cm"> */</span>
<span class="k">typedef</span> <span class="nf">int</span> <span class="p">(</span><span class="o">*</span><span class="n">nghttp2_on_begin_headers_callback</span><span class="p">)</span>
<span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span>
<span class="cm">/**</span> <span class="cm">/**</span>
<span class="cm"> * @functypedef</span> <span class="cm"> * @functypedef</span>
<span class="cm"> *</span> <span class="cm"> *</span>
@ -1221,9 +1233,11 @@
<span class="cm"> * for the |frame|. When this callback is invoked, ``frame-&gt;hd.type``</span> <span class="cm"> * for the |frame|. When this callback is invoked, ``frame-&gt;hd.type``</span>
<span class="cm"> * is either :enum:`NGHTTP2_HEADERS` or :enum:`NGHTTP2_PUSH_PROMISE`.</span> <span class="cm"> * is either :enum:`NGHTTP2_HEADERS` or :enum:`NGHTTP2_PUSH_PROMISE`.</span>
<span class="cm"> * After all header name/value pairs are processed with this callback,</span> <span class="cm"> * After all header name/value pairs are processed with this callback,</span>
<span class="cm"> * or header decompression error occurred, then</span> <span class="cm"> * and no error has been detected,</span>
<span class="cm"> * :type:`nghttp2_on_end_headers_callback` will be invoked unless</span> <span class="cm"> * :type:`nghttp2_on_frame_recv_callback` will be invoked. If there</span>
<span class="cm"> * application returns nonzero value from this callback.</span> <span class="cm"> * is an error in decompression,</span>
<span class="cm"> * :type:`nghttp2_on_frame_recv_callback` for the |frame| will not be</span>
<span class="cm"> * invoked.</span>
<span class="cm"> *</span> <span class="cm"> *</span>
<span class="cm"> * The |name| may be ``NULL`` if the |namelen| is 0. The same thing</span> <span class="cm"> * The |name| may be ``NULL`` if the |namelen| is 0. The same thing</span>
<span class="cm"> * can be said about the |value|.</span> <span class="cm"> * can be said about the |value|.</span>
@ -1240,7 +1254,7 @@
<span class="cm"> * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close</span> <span class="cm"> * Returning :enum:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close</span>
<span class="cm"> * the stream by issuing RST_STREAM with</span> <span class="cm"> * the stream by issuing RST_STREAM with</span>
<span class="cm"> * :enum:`NGHTTP2_INTERNAL_ERROR`. In this case,</span> <span class="cm"> * :enum:`NGHTTP2_INTERNAL_ERROR`. In this case,</span>
<span class="cm"> * :type:`nghttp2_on_end_headers_callback` will not be invoked.</span> <span class="cm"> * :type:`nghttp2_on_frame_recv_callback` will not be invoked.</span>
<span class="cm"> *</span> <span class="cm"> *</span>
<span class="cm"> * The implementation of this function must return 0 if it</span> <span class="cm"> * The implementation of this function must return 0 if it</span>
<span class="cm"> * succeeds. It may return :enum:`NGHTTP2_ERR_PAUSE` or</span> <span class="cm"> * succeeds. It may return :enum:`NGHTTP2_ERR_PAUSE` or</span>
@ -1259,32 +1273,6 @@
<span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">value</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">valuelen</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">value</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">valuelen</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span>
<span class="cm">/**</span>
<span class="cm"> * @functypedef</span>
<span class="cm"> *</span>
<span class="cm"> * Callback function invoked when all header name/value pairs are</span>
<span class="cm"> * processed or after the header decompression error is detected. If</span>
<span class="cm"> * the |error_code| is :enum:`NGHTTP2_NO_ERROR`, it indicates the</span>
<span class="cm"> * header decompression succeeded. Otherwise, error prevented the</span>
<span class="cm"> * completion of the header decompression. In this case, the library</span>
<span class="cm"> * will handle the error by either transmitting RST_STREAM or GOAWAY</span>
<span class="cm"> * and terminate session.</span>
<span class="cm"> *</span>
<span class="cm"> * If the |error_code| is not :enum:`NGHTTP2_NO_ERROR`, then</span>
<span class="cm"> * :type:`nghttp2_on_request_recv_callback` will not called for this</span>
<span class="cm"> * frame if the |frame| is HEADERS.</span>
<span class="cm"> *</span>
<span class="cm"> * The implementation of this function must return 0 if it</span>
<span class="cm"> * succeeds. If nonzero value is returned, it is treated as fatal</span>
<span class="cm"> * error and `nghttp2_session_recv()` and `nghttp2_session_mem_recv()`</span>
<span class="cm"> * functions immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.</span>
<span class="cm"> */</span>
<span class="k">typedef</span> <span class="nf">int</span> <span class="p">(</span><span class="o">*</span><span class="n">nghttp2_on_end_headers_callback</span><span class="p">)</span>
<span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span>
<span class="n">nghttp2_error_code</span> <span class="n">error_code</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">);</span>
<span class="cm">/**</span> <span class="cm">/**</span>
<span class="cm"> * @struct</span> <span class="cm"> * @struct</span>
<span class="cm"> *</span> <span class="cm"> *</span>
@ -1334,25 +1322,20 @@
<span class="cm"> */</span> <span class="cm"> */</span>
<span class="n">nghttp2_on_stream_close_callback</span> <span class="n">on_stream_close_callback</span><span class="p">;</span> <span class="n">nghttp2_on_stream_close_callback</span> <span class="n">on_stream_close_callback</span><span class="p">;</span>
<span class="cm">/**</span> <span class="cm">/**</span>
<span class="cm"> * Callback function invoked when request from the remote peer is</span>
<span class="cm"> * received.</span>
<span class="cm"> */</span>
<span class="n">nghttp2_on_request_recv_callback</span> <span class="n">on_request_recv_callback</span><span class="p">;</span>
<span class="cm">/**</span>
<span class="cm"> * Callback function invoked when the received frame type is</span> <span class="cm"> * Callback function invoked when the received frame type is</span>
<span class="cm"> * unknown.</span> <span class="cm"> * unknown.</span>
<span class="cm"> */</span> <span class="cm"> */</span>
<span class="n">nghttp2_on_unknown_frame_recv_callback</span> <span class="n">on_unknown_frame_recv_callback</span><span class="p">;</span> <span class="n">nghttp2_on_unknown_frame_recv_callback</span> <span class="n">on_unknown_frame_recv_callback</span><span class="p">;</span>
<span class="cm">/**</span> <span class="cm">/**</span>
<span class="cm"> * Callback function invoked when the reception of header block in</span>
<span class="cm"> * HEADERS or PUSH_PROMISE is started.</span>
<span class="cm"> */</span>
<span class="n">nghttp2_on_begin_headers_callback</span> <span class="n">on_begin_headers_callback</span><span class="p">;</span>
<span class="cm">/**</span>
<span class="cm"> * Callback function invoked when a header name/value pair is</span> <span class="cm"> * Callback function invoked when a header name/value pair is</span>
<span class="cm"> * received.</span> <span class="cm"> * received.</span>
<span class="cm"> */</span> <span class="cm"> */</span>
<span class="n">nghttp2_on_header_callback</span> <span class="n">on_header_callback</span><span class="p">;</span> <span class="n">nghttp2_on_header_callback</span> <span class="n">on_header_callback</span><span class="p">;</span>
<span class="cm">/**</span>
<span class="cm"> * Callback function invoked when all header name/value pairs are</span>
<span class="cm"> * processed.</span>
<span class="cm"> */</span>
<span class="n">nghttp2_on_end_headers_callback</span> <span class="n">on_end_headers_callback</span><span class="p">;</span>
<span class="p">}</span> <span class="n">nghttp2_session_callbacks</span><span class="p">;</span> <span class="p">}</span> <span class="n">nghttp2_session_callbacks</span><span class="p">;</span>
<span class="cm">/**</span> <span class="cm">/**</span>
@ -1589,9 +1572,7 @@
<span class="cm"> * is invoked.</span> <span class="cm"> * is invoked.</span>
<span class="cm"> * 2. If one DATA frame is completely received,</span> <span class="cm"> * 2. If one DATA frame is completely received,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is</span> <span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is</span>
<span class="cm"> * invoked. If the frame is the final frame of the request,</span> <span class="cm"> * invoked. If the reception of the frame triggers the</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_request_recv_callback`</span>
<span class="cm"> * is invoked. If the reception of the frame triggers the</span>
<span class="cm"> * closure of the stream,</span> <span class="cm"> * closure of the stream,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_stream_close_callback`</span> <span class="cm"> * :member:`nghttp2_session_callbacks.on_stream_close_callback`</span>
<span class="cm"> * is invoked.</span> <span class="cm"> * is invoked.</span>
@ -1600,17 +1581,20 @@
<span class="cm"> *</span> <span class="cm"> *</span>
<span class="cm"> * 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked</span> <span class="cm"> * 1. :member:`nghttp2_session_callbacks.recv_callback` is invoked</span>
<span class="cm"> * one or more times to receive whole frame.</span> <span class="cm"> * one or more times to receive whole frame.</span>
<span class="cm"> * 2. If the received frame is valid,</span> <span class="cm"> *</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is</span> <span class="cm"> * 2. If the received frame is valid, then following actions are</span>
<span class="cm"> * invoked. If frame is either HEADERS or PUSH_PROMISE,</span> <span class="cm"> * taken. If the frame is either HEADERS or PUSH_PROMISE,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_begin_headers_callback`</span>
<span class="cm"> * is invoked. Then</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_header_callback` is</span> <span class="cm"> * :member:`nghttp2_session_callbacks.on_header_callback` is</span>
<span class="cm"> * invoked for each header name/value pair. After all name/value</span> <span class="cm"> * invoked for each header name/value pair. After all name/value</span>
<span class="cm"> * pairs are emitted (or decompression failed),</span> <span class="cm"> * pairs are emitted successfully,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_end_headers_callback`</span> <span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is</span>
<span class="cm"> * is invoked. If the frame is the final frame of the request,</span> <span class="cm"> * invoked. For other frames,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_request_recv_callback`</span> <span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is</span>
<span class="cm"> * is invoked. If the reception of the frame triggers the</span> <span class="cm"> * invoked.</span>
<span class="cm"> * closure of the stream,</span> <span class="cm"> * If the reception of the frame triggers the closure of the</span>
<span class="cm"> * stream,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_stream_close_callback`</span> <span class="cm"> * :member:`nghttp2_session_callbacks.on_stream_close_callback`</span>
<span class="cm"> * is invoked.</span> <span class="cm"> * is invoked.</span>
<span class="cm"> * 3. If the received frame is unpacked but is interpreted as</span> <span class="cm"> * 3. If the received frame is unpacked but is interpreted as</span>

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -293,7 +293,7 @@ finished successfully. We first initialize nghttp2 session object in
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_data_chunk_recv_callback</span> <span class="o">=</span> <span class="n">on_data_chunk_recv_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_data_chunk_recv_callback</span> <span class="o">=</span> <span class="n">on_data_chunk_recv_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_stream_close_callback</span> <span class="o">=</span> <span class="n">on_stream_close_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_stream_close_callback</span> <span class="o">=</span> <span class="n">on_stream_close_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_header_callback</span> <span class="o">=</span> <span class="n">on_header_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_header_callback</span> <span class="o">=</span> <span class="n">on_header_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_end_headers_callback</span> <span class="o">=</span> <span class="n">on_end_headers_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_begin_headers_callback</span> <span class="o">=</span> <span class="n">on_begin_headers_callback</span><span class="p">;</span>
<span class="n">nghttp2_session_client_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_data</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">session_data</span><span class="p">);</span> <span class="n">nghttp2_session_client_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_data</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">session_data</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>
</pre></div> </pre></div>
@ -508,29 +508,6 @@ unnecessary to compare them, but real applications surely deal with
multiple streams, and <em>stream_user_data</em> is very handy to identify multiple streams, and <em>stream_user_data</em> is very handy to identify
which HEADERS we are seeing in the callback. Therefore we just show which HEADERS we are seeing in the callback. Therefore we just show
how to use it here.</p> how to use it here.</p>
<p>The <tt class="docutils literal"><span class="pre">on_frame_recv_callback()</span></tt> function is invoked when a frame is
received from the remote peer:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_frame_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">==</span> <span class="n">NGHTTP2_HCAT_RESPONSE</span> <span class="o">&amp;&amp;</span>
<span class="n">session_data</span><span class="o">-&gt;</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">stream_id</span> <span class="o">==</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">)</span> <span class="p">{</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;Response headers for stream ID=%d:</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span>
<span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</div>
<p>In this tutorial, we are just interested in the HTTP response
HEADERS. We check te frame type and its category (it should be
<a class="reference internal" href="apiref.html#NGHTTP2_HCAT_RESPONSE" title="NGHTTP2_HCAT_RESPONSE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_HCAT_RESPONSE</span></tt></a> for HTTP response HEADERS). Also check
its stream ID.</p>
<p>Each request header name/value pair is emitted via <p>Each request header name/value pair is emitted via
<tt class="docutils literal"><span class="pre">on_header_callback</span></tt> function:</p> <tt class="docutils literal"><span class="pre">on_header_callback</span></tt> function:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_header_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_header_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
@ -555,18 +532,16 @@ its stream ID.</p>
</div> </div>
<p>In this turotial, we just print the name/value pair.</p> <p>In this turotial, we just print the name/value pair.</p>
<p>After all name/value pairs are emitted for a frame, <p>After all name/value pairs are emitted for a frame,
<tt class="docutils literal"><span class="pre">on_end_headers_callback</span></tt> function is called:</p> <tt class="docutils literal"><span class="pre">on_frame_recv_callback</span></tt> function is called:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_end_headers_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_frame_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="n">nghttp2_error_code</span> <span class="n">error_code</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span> <span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span> <span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span> <span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>: <span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">==</span> <span class="n">NGHTTP2_HCAT_RESPONSE</span> <span class="o">&amp;&amp;</span> <span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">==</span> <span class="n">NGHTTP2_HCAT_RESPONSE</span> <span class="o">&amp;&amp;</span>
<span class="n">session_data</span><span class="o">-&gt;</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">stream_id</span> <span class="o">==</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">)</span> <span class="p">{</span> <span class="n">session_data</span><span class="o">-&gt;</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">stream_id</span> <span class="o">==</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">)</span> <span class="p">{</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;All headers received with error_code=%d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">error_code</span><span class="p">);</span> <span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;All headers received</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>
<span class="k">break</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
@ -574,8 +549,10 @@ its stream ID.</p>
<span class="p">}</span> <span class="p">}</span>
</pre></div> </pre></div>
</div> </div>
<p>This callback may be called prematurely because of errors (e.g., <p>In this tutorial, we are just interested in the HTTP response
header decompression failure) which is indicated by <tt class="docutils literal"><span class="pre">error_code</span></tt>.</p> HEADERS. We check te frame type and its category (it should be
<a class="reference internal" href="apiref.html#NGHTTP2_HCAT_RESPONSE" title="NGHTTP2_HCAT_RESPONSE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_HCAT_RESPONSE</span></tt></a> for HTTP response HEADERS). Also check
its stream ID.</p>
<p>The <tt class="docutils literal"><span class="pre">on_data_chunk_recv_callback()</span></tt> function is invoked when a chunk <p>The <tt class="docutils literal"><span class="pre">on_data_chunk_recv_callback()</span></tt> function is invoked when a chunk
of data is received from the remote peer:</p> of data is received from the remote peer:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_data_chunk_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">flags</span><span class="p">,</span> <div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_data_chunk_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="n">flags</span><span class="p">,</span>
@ -859,30 +836,11 @@ here.</p>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
<span class="cm">/* nghttp2_on_end_headers_callback: Called when nghttp2 library emits</span> <span class="cm">/* nghttp2_on_begin_headers_callback: Called when nghttp2 library gets</span>
<span class="cm"> all header name/value pairs, or may be called prematurely because</span> <span class="cm"> started to receive header block. */</span>
<span class="cm"> of errors which is indicated by |error_code|. */</span> <span class="k">static</span> <span class="kt">int</span> <span class="nf">on_begin_headers_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_end_headers_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="n">nghttp2_error_code</span> <span class="n">error_code</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">==</span> <span class="n">NGHTTP2_HCAT_RESPONSE</span> <span class="o">&amp;&amp;</span>
<span class="n">session_data</span><span class="o">-&gt;</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">stream_id</span> <span class="o">==</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">)</span> <span class="p">{</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;All headers received with error_code=%d</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">error_code</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* nghttp2_on_frame_recv_callback: Called when nghttp2 library</span>
<span class="cm"> received a frame from the remote peer. */</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_frame_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span> <span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span> <span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span> <span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
@ -897,6 +855,23 @@ here.</p>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
<span class="cm">/* nghttp2_on_frame_recv_callback: Called when nghttp2 library</span>
<span class="cm"> received a complete frame from the remote peer. */</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_frame_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">==</span> <span class="n">NGHTTP2_HCAT_RESPONSE</span> <span class="o">&amp;&amp;</span>
<span class="n">session_data</span><span class="o">-&gt;</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">stream_id</span> <span class="o">==</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">)</span> <span class="p">{</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;All headers received</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* nghttp2_on_data_chunk_recv_callback: Called when DATA frame is</span> <span class="cm">/* nghttp2_on_data_chunk_recv_callback: Called when DATA frame is</span>
<span class="cm"> received from the remote peer. In this implementation, if the frame</span> <span class="cm"> received from the remote peer. In this implementation, if the frame</span>
<span class="cm"> is meant to the stream we initiated, print the received data in</span> <span class="cm"> is meant to the stream we initiated, print the received data in</span>
@ -989,7 +964,7 @@ here.</p>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_data_chunk_recv_callback</span> <span class="o">=</span> <span class="n">on_data_chunk_recv_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_data_chunk_recv_callback</span> <span class="o">=</span> <span class="n">on_data_chunk_recv_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_stream_close_callback</span> <span class="o">=</span> <span class="n">on_stream_close_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_stream_close_callback</span> <span class="o">=</span> <span class="n">on_stream_close_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_header_callback</span> <span class="o">=</span> <span class="n">on_header_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_header_callback</span> <span class="o">=</span> <span class="n">on_header_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_end_headers_callback</span> <span class="o">=</span> <span class="n">on_end_headers_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_begin_headers_callback</span> <span class="o">=</span> <span class="n">on_begin_headers_callback</span><span class="p">;</span>
<span class="n">nghttp2_session_client_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_data</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">session_data</span><span class="p">);</span> <span class="n">nghttp2_session_client_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_data</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">session_data</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>

View File

@ -367,9 +367,9 @@ these 2 functions later.</p>
<span class="n">callbacks</span><span class="p">.</span><span class="n">send_callback</span> <span class="o">=</span> <span class="n">send_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">send_callback</span> <span class="o">=</span> <span class="n">send_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_frame_recv_callback</span> <span class="o">=</span> <span class="n">on_frame_recv_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_frame_recv_callback</span> <span class="o">=</span> <span class="n">on_frame_recv_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_request_recv_callback</span> <span class="o">=</span> <span class="n">on_request_recv_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_stream_close_callback</span> <span class="o">=</span> <span class="n">on_stream_close_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_stream_close_callback</span> <span class="o">=</span> <span class="n">on_stream_close_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_header_callback</span> <span class="o">=</span> <span class="n">on_header_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_header_callback</span> <span class="o">=</span> <span class="n">on_header_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_begin_headers_callback</span> <span class="o">=</span> <span class="n">on_begin_headers_callback</span><span class="p">;</span>
<span class="n">nghttp2_session_server_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_data</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">session_data</span><span class="p">);</span> <span class="n">nghttp2_session_server_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_data</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">session_data</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>
</pre></div> </pre></div>
@ -534,25 +534,22 @@ pending data when output buffer becomes empty.</p>
<p>We have already described about nghttp2 callback <tt class="docutils literal"><span class="pre">send_callback()</span></tt>. <p>We have already described about nghttp2 callback <tt class="docutils literal"><span class="pre">send_callback()</span></tt>.
Let&#8217;s describe remaining nghttp2 callbacks we setup in Let&#8217;s describe remaining nghttp2 callbacks we setup in
<tt class="docutils literal"><span class="pre">initialize_nghttp2_setup()</span></tt> function.</p> <tt class="docutils literal"><span class="pre">initialize_nghttp2_setup()</span></tt> function.</p>
<p>The <tt class="docutils literal"><span class="pre">on_frame_recv_callback()</span></tt> function is invoked when a frame is <p>The <tt class="docutils literal"><span class="pre">on_begin_headers_callback()</span></tt> function is invoked when reception
received from the remote peer:</p> of header block in HEADERS or PUSH_PROMISE frame is started:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_frame_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_begin_headers_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span> <span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span> <span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span> <span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span> <span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>: <span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span> <span class="o">!=</span> <span class="n">NGHTTP2_HEADERS</span> <span class="o">||</span>
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">!=</span> <span class="n">NGHTTP2_HCAT_REQUEST</span><span class="p">)</span> <span class="p">{</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">!=</span> <span class="n">NGHTTP2_HCAT_REQUEST</span><span class="p">)</span> <span class="p">{</span>
<span class="k">break</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="n">create_http2_stream_data</span><span class="p">(</span><span class="n">session_data</span><span class="p">,</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="n">nghttp2_session_set_stream_user_data</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">,</span>
<span class="n">stream_data</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="nl">default:</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="n">create_http2_stream_data</span><span class="p">(</span><span class="n">session_data</span><span class="p">,</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="n">nghttp2_session_set_stream_user_data</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">,</span>
<span class="n">stream_data</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
</pre></div> </pre></div>
@ -567,7 +564,7 @@ order to get the object without searching through doubly linked list.</p>
<p>In this example server, we want to serve files relative to the current <p>In this example server, we want to serve files relative to the current
working directory the program was invoked. Each header name/value pair working directory the program was invoked. Each header name/value pair
is emitted via <tt class="docutils literal"><span class="pre">on_header_callback</span></tt> function, which is called after is emitted via <tt class="docutils literal"><span class="pre">on_header_callback</span></tt> function, which is called after
<tt class="docutils literal"><span class="pre">on_frame_recv_callback()</span></tt>:</p> <tt class="docutils literal"><span class="pre">on_begin_headers_callback()</span></tt>:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_header_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_header_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">namelen</span><span class="p">,</span> <span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">namelen</span><span class="p">,</span>
@ -601,59 +598,37 @@ is emitted via <tt class="docutils literal"><span class="pre">on_header_callback
requested path in <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object. In this example requested path in <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object. In this example
program, we ignore <tt class="docutils literal"><span class="pre">:method</span></tt> header field and always treat the program, we ignore <tt class="docutils literal"><span class="pre">:method</span></tt> header field and always treat the
request as GET request.</p> request as GET request.</p>
<p>It is ok for the server to start sending response in this callback (or <p>The <tt class="docutils literal"><span class="pre">on_frame_recv_callback()</span></tt> function is invoked when a frame is
in <a class="reference internal" href="apiref.html#nghttp2_on_end_headers_callback" title="nghttp2_on_end_headers_callback"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_on_end_headers_callback()</span></tt></a>, which is not used in this fully received:</p>
tutorial). In this example, we defer it to <div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_frame_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<tt class="docutils literal"><span class="pre">on_request_recv_callback()</span></tt> function.</p> <span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<p>The <tt class="docutils literal"><span class="pre">on_request_recv_callback()</span></tt> function is invoked when all HTTP
request, including entity body, was received:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">on_request_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span> <span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span> <span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span>
<span class="n">nghttp2_nv</span> <span class="n">hdrs</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="n">MAKE_NV</span><span class="p">(</span><span class="s">&quot;:status&quot;</span><span class="p">,</span> <span class="s">&quot;200&quot;</span><span class="p">)</span> <span class="k">case</span> <span class="n">NGHTTP2_DATA</span>:
<span class="p">};</span> <span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="kt">char</span> <span class="o">*</span><span class="n">rel_path</span><span class="p">;</span> <span class="cm">/* Check that the client request has finished */</span>
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="n">NGHTTP2_FLAG_END_STREAM</span><span class="p">)</span> <span class="p">{</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_stream_data</span><span class="o">*</span><span class="p">)</span><span class="n">nghttp2_session_get_stream_user_data</span> <span class="n">stream_data</span> <span class="o">=</span> <span class="n">nghttp2_session_get_stream_user_data</span><span class="p">(</span><span class="n">session</span><span class="p">,</span>
<span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_id</span><span class="p">);</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span><span class="p">)</span> <span class="p">{</span> <span class="cm">/* For DATA and HEADERS frame, this callback may be called after</span>
<span class="k">if</span><span class="p">(</span><span class="n">error_reply</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_data</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="cm"> on_stream_close_callback. Check that stream still alive. */</span>
<span class="k">return</span> <span class="n">NGHTTP2_ERR_CALLBACK_FAILURE</span><span class="p">;</span> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">stream_data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">on_request_recv</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">session_data</span><span class="p">,</span> <span class="n">stream_data</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="k">break</span><span class="p">;</span>
<span class="p">}</span> <span class="nl">default:</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">stderr</span><span class="p">,</span> <span class="s">&quot;%s GET %s</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">,</span> <span class="n">session_data</span><span class="o">-&gt;</span><span class="n">client_addr</span><span class="p">,</span> <span class="k">break</span><span class="p">;</span>
<span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">check_path</span><span class="p">(</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span><span class="p">))</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">error_reply</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_data</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">NGHTTP2_ERR_CALLBACK_FAILURE</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">for</span><span class="p">(</span><span class="n">rel_path</span> <span class="o">=</span> <span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span><span class="p">;</span> <span class="o">*</span><span class="n">rel_path</span> <span class="o">==</span> <span class="sc">&#39;/&#39;</span><span class="p">;</span> <span class="o">++</span><span class="n">rel_path</span><span class="p">);</span>
<span class="n">fd</span> <span class="o">=</span> <span class="n">open</span><span class="p">(</span><span class="n">rel_path</span><span class="p">,</span> <span class="n">O_RDONLY</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">fd</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">error_reply</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_data</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">NGHTTP2_ERR_CALLBACK_FAILURE</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">fd</span> <span class="o">=</span> <span class="n">fd</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">send_response</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_id</span><span class="p">,</span> <span class="n">hdrs</span><span class="p">,</span> <span class="n">ARRLEN</span><span class="p">(</span><span class="n">hdrs</span><span class="p">),</span> <span class="n">fd</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="k">return</span> <span class="n">NGHTTP2_ERR_CALLBACK_FAILURE</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
</pre></div> </pre></div>
</div> </div>
<p>First we retrieve <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object associated to the <p>First we retrieve <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object associated to the
stream in <tt class="docutils literal"><span class="pre">on_frame_recv_callback()</span></tt>. It is done using stream in <tt class="docutils literal"><span class="pre">on_begin_headers_callback()</span></tt>. It is done using
<a class="reference internal" href="apiref.html#nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a>. If the requested path cannot <a class="reference internal" href="apiref.html#nghttp2_session_get_stream_user_data" title="nghttp2_session_get_stream_user_data"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_get_stream_user_data()</span></tt></a>. If the requested path cannot
be served for some reasons (e.g., file is not found), we send 404 be served for some reasons (e.g., file is not found), we send 404
response, which is done in <tt class="docutils literal"><span class="pre">error_reply()</span></tt>. Otherwise, we open response, which is done in <tt class="docutils literal"><span class="pre">error_reply()</span></tt>. Otherwise, we open
@ -1056,56 +1031,6 @@ stream is about to close and we no longer use that object.</p>
<span class="k">return</span> <span class="n">res</span><span class="p">;</span> <span class="k">return</span> <span class="n">res</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
<span class="cm">/* nghttp2_on_header_callback: Called when nghttp2 library emits</span>
<span class="cm"> single header name/value pair. */</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_header_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">namelen</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">value</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">valuelen</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">char</span> <span class="n">PATH</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&quot;:path&quot;</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">!=</span> <span class="n">NGHTTP2_HCAT_REQUEST</span><span class="p">)</span> <span class="p">{</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="n">nghttp2_session_get_stream_user_data</span><span class="p">(</span><span class="n">session</span><span class="p">,</span>
<span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span><span class="p">)</span> <span class="p">{</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">namelen</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">PATH</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">memcmp</span><span class="p">(</span><span class="n">PATH</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">size_t</span> <span class="n">j</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">valuelen</span> <span class="o">&amp;&amp;</span> <span class="n">value</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39;?&#39;</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">);</span>
<span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span> <span class="o">=</span> <span class="n">percent_decode</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">j</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_frame_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">!=</span> <span class="n">NGHTTP2_HCAT_REQUEST</span><span class="p">)</span> <span class="p">{</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="n">create_http2_stream_data</span><span class="p">(</span><span class="n">session_data</span><span class="p">,</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="n">nghttp2_session_set_stream_user_data</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">,</span>
<span class="n">stream_data</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="nl">default:</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">static</span> <span class="kt">ssize_t</span> <span class="nf">file_read_callback</span> <span class="k">static</span> <span class="kt">ssize_t</span> <span class="nf">file_read_callback</span>
<span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span>
<span class="kt">uint8_t</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">length</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">eof</span><span class="p">,</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">buf</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">length</span><span class="p">,</span> <span class="kt">int</span> <span class="o">*</span><span class="n">eof</span><span class="p">,</span>
@ -1174,6 +1099,53 @@ stream is about to close and we no longer use that object.</p>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
<span class="cm">/* nghttp2_on_header_callback: Called when nghttp2 library emits</span>
<span class="cm"> single header name/value pair. */</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_header_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">name</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">namelen</span><span class="p">,</span>
<span class="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">value</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">valuelen</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span>
<span class="k">const</span> <span class="kt">char</span> <span class="n">PATH</span><span class="p">[]</span> <span class="o">=</span> <span class="s">&quot;:path&quot;</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">!=</span> <span class="n">NGHTTP2_HCAT_REQUEST</span><span class="p">)</span> <span class="p">{</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="n">nghttp2_session_get_stream_user_data</span><span class="p">(</span><span class="n">session</span><span class="p">,</span>
<span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span><span class="p">)</span> <span class="p">{</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">namelen</span> <span class="o">==</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">PATH</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span> <span class="o">&amp;&amp;</span> <span class="n">memcmp</span><span class="p">(</span><span class="n">PATH</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">namelen</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="kt">size_t</span> <span class="n">j</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="n">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">j</span> <span class="o">&lt;</span> <span class="n">valuelen</span> <span class="o">&amp;&amp;</span> <span class="n">value</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">!=</span> <span class="sc">&#39;?&#39;</span><span class="p">;</span> <span class="o">++</span><span class="n">j</span><span class="p">);</span>
<span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span> <span class="o">=</span> <span class="n">percent_decode</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">j</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_begin_headers_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span>
<span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span> <span class="o">!=</span> <span class="n">NGHTTP2_HEADERS</span> <span class="o">||</span>
<span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">cat</span> <span class="o">!=</span> <span class="n">NGHTTP2_HCAT_REQUEST</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="n">create_http2_stream_data</span><span class="p">(</span><span class="n">session_data</span><span class="p">,</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="n">nghttp2_session_set_stream_user_data</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">,</span>
<span class="n">stream_data</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* Minimum check for directory traversal. Returns nonzero if it is</span> <span class="cm">/* Minimum check for directory traversal. Returns nonzero if it is</span>
<span class="cm"> safe. */</span> <span class="cm"> safe. */</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">check_path</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path</span><span class="p">)</span> <span class="k">static</span> <span class="kt">int</span> <span class="nf">check_path</span><span class="p">(</span><span class="k">const</span> <span class="kt">char</span> <span class="o">*</span><span class="n">path</span><span class="p">)</span>
@ -1186,19 +1158,16 @@ stream is about to close and we no longer use that object.</p>
<span class="o">!</span><span class="n">ends_with</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s">&quot;/..&quot;</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">ends_with</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s">&quot;/.&quot;</span><span class="p">);</span> <span class="o">!</span><span class="n">ends_with</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s">&quot;/..&quot;</span><span class="p">)</span> <span class="o">&amp;&amp;</span> <span class="o">!</span><span class="n">ends_with</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="s">&quot;/.&quot;</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_request_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="k">static</span> <span class="kt">int</span> <span class="nf">on_request_recv</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span> <span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span><span class="p">,</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">)</span>
<span class="p">{</span> <span class="p">{</span>
<span class="kt">int</span> <span class="n">fd</span><span class="p">;</span> <span class="kt">int</span> <span class="n">fd</span><span class="p">;</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span>
<span class="n">nghttp2_nv</span> <span class="n">hdrs</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span> <span class="n">nghttp2_nv</span> <span class="n">hdrs</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="n">MAKE_NV</span><span class="p">(</span><span class="s">&quot;:status&quot;</span><span class="p">,</span> <span class="s">&quot;200&quot;</span><span class="p">)</span> <span class="n">MAKE_NV</span><span class="p">(</span><span class="s">&quot;:status&quot;</span><span class="p">,</span> <span class="s">&quot;200&quot;</span><span class="p">)</span>
<span class="p">};</span> <span class="p">};</span>
<span class="kt">char</span> <span class="o">*</span><span class="n">rel_path</span><span class="p">;</span> <span class="kt">char</span> <span class="o">*</span><span class="n">rel_path</span><span class="p">;</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_stream_data</span><span class="o">*</span><span class="p">)</span><span class="n">nghttp2_session_get_stream_user_data</span>
<span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_id</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">request_path</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">error_reply</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_data</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span><span class="p">(</span><span class="n">error_reply</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_data</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="n">NGHTTP2_ERR_CALLBACK_FAILURE</span><span class="p">;</span> <span class="k">return</span> <span class="n">NGHTTP2_ERR_CALLBACK_FAILURE</span><span class="p">;</span>
@ -1223,13 +1192,40 @@ stream is about to close and we no longer use that object.</p>
<span class="p">}</span> <span class="p">}</span>
<span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">fd</span> <span class="o">=</span> <span class="n">fd</span><span class="p">;</span> <span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">fd</span> <span class="o">=</span> <span class="n">fd</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">send_response</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_id</span><span class="p">,</span> <span class="n">hdrs</span><span class="p">,</span> <span class="n">ARRLEN</span><span class="p">(</span><span class="n">hdrs</span><span class="p">),</span> <span class="n">fd</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span> <span class="k">if</span><span class="p">(</span><span class="n">send_response</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">stream_data</span><span class="o">-&gt;</span><span class="n">stream_id</span><span class="p">,</span> <span class="n">hdrs</span><span class="p">,</span>
<span class="n">ARRLEN</span><span class="p">(</span><span class="n">hdrs</span><span class="p">),</span> <span class="n">fd</span><span class="p">)</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span> <span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">);</span>
<span class="k">return</span> <span class="n">NGHTTP2_ERR_CALLBACK_FAILURE</span><span class="p">;</span> <span class="k">return</span> <span class="n">NGHTTP2_ERR_CALLBACK_FAILURE</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span> <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span> <span class="p">}</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_frame_recv_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="k">const</span> <span class="n">nghttp2_frame</span> <span class="o">*</span><span class="n">frame</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">user_data</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">http2_session_data</span> <span class="o">*</span><span class="n">session_data</span> <span class="o">=</span> <span class="p">(</span><span class="n">http2_session_data</span><span class="o">*</span><span class="p">)</span><span class="n">user_data</span><span class="p">;</span>
<span class="n">http2_stream_data</span> <span class="o">*</span><span class="n">stream_data</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="n">NGHTTP2_DATA</span>:
<span class="k">case</span> <span class="n">NGHTTP2_HEADERS</span>:
<span class="cm">/* Check that the client request has finished */</span>
<span class="k">if</span><span class="p">(</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">flags</span> <span class="o">&amp;</span> <span class="n">NGHTTP2_FLAG_END_STREAM</span><span class="p">)</span> <span class="p">{</span>
<span class="n">stream_data</span> <span class="o">=</span> <span class="n">nghttp2_session_get_stream_user_data</span><span class="p">(</span><span class="n">session</span><span class="p">,</span>
<span class="n">frame</span><span class="o">-&gt;</span><span class="n">hd</span><span class="p">.</span><span class="n">stream_id</span><span class="p">);</span>
<span class="cm">/* For DATA and HEADERS frame, this callback may be called after</span>
<span class="cm"> on_stream_close_callback. Check that stream still alive. */</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="n">stream_data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">on_request_recv</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">session_data</span><span class="p">,</span> <span class="n">stream_data</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">break</span><span class="p">;</span>
<span class="nl">default:</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">static</span> <span class="kt">int</span> <span class="nf">on_stream_close_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span> <span class="k">static</span> <span class="kt">int</span> <span class="nf">on_stream_close_callback</span><span class="p">(</span><span class="n">nghttp2_session</span> <span class="o">*</span><span class="n">session</span><span class="p">,</span>
<span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span> <span class="kt">int32_t</span> <span class="n">stream_id</span><span class="p">,</span>
<span class="n">nghttp2_error_code</span> <span class="n">error_code</span><span class="p">,</span> <span class="n">nghttp2_error_code</span> <span class="n">error_code</span><span class="p">,</span>
@ -1250,9 +1246,9 @@ stream is about to close and we no longer use that object.</p>
<span class="n">callbacks</span><span class="p">.</span><span class="n">send_callback</span> <span class="o">=</span> <span class="n">send_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">send_callback</span> <span class="o">=</span> <span class="n">send_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_frame_recv_callback</span> <span class="o">=</span> <span class="n">on_frame_recv_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_frame_recv_callback</span> <span class="o">=</span> <span class="n">on_frame_recv_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_request_recv_callback</span> <span class="o">=</span> <span class="n">on_request_recv_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_stream_close_callback</span> <span class="o">=</span> <span class="n">on_stream_close_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_stream_close_callback</span> <span class="o">=</span> <span class="n">on_stream_close_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_header_callback</span> <span class="o">=</span> <span class="n">on_header_callback</span><span class="p">;</span> <span class="n">callbacks</span><span class="p">.</span><span class="n">on_header_callback</span> <span class="o">=</span> <span class="n">on_header_callback</span><span class="p">;</span>
<span class="n">callbacks</span><span class="p">.</span><span class="n">on_begin_headers_callback</span> <span class="o">=</span> <span class="n">on_begin_headers_callback</span><span class="p">;</span>
<span class="n">nghttp2_session_server_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_data</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">session_data</span><span class="p">);</span> <span class="n">nghttp2_session_server_new</span><span class="p">(</span><span class="o">&amp;</span><span class="n">session_data</span><span class="o">-&gt;</span><span class="n">session</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">callbacks</span><span class="p">,</span> <span class="n">session_data</span><span class="p">);</span>
<span class="p">}</span> <span class="p">}</span>