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
: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
succeeds. If nonzero value is returned, it is treated as fatal
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
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
succeeds. If nonzero is returned, it is treated as fatal error and
`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
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)
@ -969,6 +960,27 @@ Types (structs, unions and typedefs)
`nghttp2_session_recv()` and `nghttp2_session_send()` functions
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)
@ -976,9 +988,11 @@ Types (structs, unions and typedefs)
for the *frame*. When this callback is invoked, ``frame->hd.type``
is either :macro:`NGHTTP2_HEADERS` or :macro:`NGHTTP2_PUSH_PROMISE`.
After all header name/value pairs are processed with this callback,
or header decompression error occurred, then
:type:`nghttp2_on_end_headers_callback` will be invoked unless
application returns nonzero value from this callback.
and no error has been detected,
:type:`nghttp2_on_frame_recv_callback` will be invoked. If there
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
can be said about the *value*.
@ -995,7 +1009,7 @@ Types (structs, unions and typedefs)
Returning :macro:`NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE` will close
the stream by issuing RST_STREAM with
: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
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
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
@ -1065,22 +1059,18 @@ Types (structs, unions and typedefs)
.. member:: nghttp2_on_stream_close_callback on_stream_close_callback
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
Callback function invoked when the received frame type is
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
Callback function invoked when a header name/value pair is
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
@ -1260,9 +1250,7 @@ Functions
is invoked.
2. If one DATA frame is completely received,
:member:`nghttp2_session_callbacks.on_frame_recv_callback` is
invoked. If the frame is the final frame of the request,
:member:`nghttp2_session_callbacks.on_request_recv_callback`
is invoked. If the reception of the frame triggers the
invoked. If the reception of the frame triggers the
closure of the stream,
:member:`nghttp2_session_callbacks.on_stream_close_callback`
is invoked.
@ -1271,17 +1259,20 @@ Functions
1. :member:`nghttp2_session_callbacks.recv_callback` is invoked
one or more times to receive whole frame.
2. If the received frame is valid,
:member:`nghttp2_session_callbacks.on_frame_recv_callback` is
invoked. If frame is either HEADERS or PUSH_PROMISE,
2. If the received frame is valid, then following actions are
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
invoked for each header name/value pair. After all name/value
pairs are emitted (or decompression failed),
:member:`nghttp2_session_callbacks.on_end_headers_callback`
is invoked. If the frame is the final frame of the request,
:member:`nghttp2_session_callbacks.on_request_recv_callback`
is invoked. If the reception of the frame triggers the
closure of the stream,
pairs are emitted successfully,
:member:`nghttp2_session_callbacks.on_frame_recv_callback` is
invoked. For other frames,
:member:`nghttp2_session_callbacks.on_frame_recv_callback` is
invoked.
If the reception of the frame triggers the closure of the
stream,
:member:`nghttp2_session_callbacks.on_stream_close_callback`
is invoked.
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_stream_close_callback = on_stream_close_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);
}
@ -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
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
``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.
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,
const nghttp2_frame *frame,
nghttp2_error_code error_code,
void *user_data)
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, "All headers received with error_code=%d\n", error_code);
fprintf(stderr, "All headers received\n");
}
break;
}
return 0;
}
This callback may be called prematurely because of errors (e.g.,
header decompression failure) which is indicated by ``error_code``.
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.
The ``on_data_chunk_recv_callback()`` function is invoked when a chunk
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.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_header_callback = on_header_callback;
callbacks.on_begin_headers_callback = on_begin_headers_callback;
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
``initialize_nghttp2_setup()`` function.
The ``on_frame_recv_callback()`` function is invoked when a frame is
received from the remote peer::
The ``on_begin_headers_callback()`` function is invoked when reception
of header block in HEADERS or PUSH_PROMISE frame is started::
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
static int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame,
void *user_data)
{
http2_session_data *session_data = (http2_session_data*)user_data;
http2_stream_data *stream_data;
switch(frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
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);
break;
default:
break;
if(frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
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);
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
working directory the program was invoked. Each header name/value pair
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,
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
request as GET request.
It is ok for the server to start sending response in this callback (or
in `nghttp2_on_end_headers_callback()`, which is not used in this
tutorial). In this example, we defer it to
``on_request_recv_callback()`` function.
The ``on_frame_recv_callback()`` function is invoked when a frame is
fully received::
The ``on_request_recv_callback()`` function is invoked when all HTTP
request, including entity body, was received::
static int on_request_recv_callback(nghttp2_session *session,
int32_t stream_id, void *user_data)
static int on_frame_recv_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data)
{
int fd;
http2_session_data *session_data = (http2_session_data*)user_data;
http2_stream_data *stream_data;
nghttp2_nv hdrs[] = {
MAKE_NV(":status", "200")
};
char *rel_path;
stream_data = (http2_stream_data*)nghttp2_session_get_stream_user_data
(session, stream_id);
if(!stream_data->request_path) {
if(error_reply(session, stream_data) != 0) {
return NGHTTP2_ERR_CALLBACK_FAILURE;
switch(frame->hd.type) {
case NGHTTP2_DATA:
case NGHTTP2_HEADERS:
/* Check that the client request has finished */
if(frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
stream_data = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id);
/* For DATA and HEADERS frame, this callback may be called after
on_stream_close_callback. Check that stream still alive. */
if(!stream_data) {
return 0;
}
return on_request_recv(session, session_data, stream_data);
}
return 0;
}
fprintf(stderr, "%s GET %s\n", session_data->client_addr,
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;
break;
default:
break;
}
return 0;
}
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
be served for some reasons (e.g., file is not found), we send 404
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
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>
<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
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>
@ -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>
member of their data structure are always <tt class="docutils literal"><span class="pre">NULL</span></tt> and 0
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
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
@ -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>
</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">
<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>
@ -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>
</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">
<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>
@ -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>
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,
or header decompression error occurred, then
<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
application returns nonzero value from this callback.</p>
and no error has been detected,
<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
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
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
@ -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
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_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
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
@ -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>
</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">
<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>
@ -1596,13 +1589,6 @@ because of an error.</p>
<dd><p>Callback function invoked when the stream is closed.</p>
</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">
<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>
@ -1610,6 +1596,13 @@ received.</p>
unknown.</p>
</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">
<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>
@ -1617,13 +1610,6 @@ unknown.</p>
received.</p>
</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>
<dl class="type">
@ -1810,9 +1796,7 @@ to receive DATA payload. For each chunk of data,
is invoked.</li>
<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
invoked. If the frame is the final frame of the request,
<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
invoked. 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>
is invoked.</li>
@ -1821,17 +1805,19 @@ is invoked.</li>
<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
one or more times to receive whole frame.</li>
<li>If the received frame is valid,
<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 frame is either HEADERS or PUSH_PROMISE,
<li>If the received frame is valid, then following actions are
taken. If the 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
invoked for each header name/value pair. After all name/value
pairs are emitted (or decompression failed),
<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>
is invoked. If the frame is the final frame of the request,
<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,
pairs are emitted successfully,
<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. For other frames,
<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 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>
is invoked.</li>
<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>
</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>
</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><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>
@ -641,10 +641,6 @@
</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>
@ -805,11 +801,11 @@
</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><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>
@ -833,10 +829,6 @@
</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>

View File

@ -1031,6 +1031,16 @@
<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"> *</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"> * 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>
@ -1054,10 +1064,6 @@
<span class="cm"> * member of their data structure are always ``NULL`` and 0</span>
<span class="cm"> * respectively.</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"> * 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>
@ -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="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"> * @functypedef</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="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"> * @functypedef</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"> * 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"> * or header decompression error occurred, then</span>
<span class="cm"> * :type:`nghttp2_on_end_headers_callback` will be invoked unless</span>
<span class="cm"> * application returns nonzero value from this callback.</span>
<span class="cm"> * and no error has been detected,</span>
<span class="cm"> * :type:`nghttp2_on_frame_recv_callback` will be invoked. If there</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"> * The |name| may be ``NULL`` if the |namelen| is 0. The same thing</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"> * the stream by issuing RST_STREAM with</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"> * The implementation of this function must return 0 if it</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="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"> * @struct</span>
<span class="cm"> *</span>
@ -1334,25 +1322,20 @@
<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="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"> * unknown.</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="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"> * received.</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="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="cm">/**</span>
@ -1589,9 +1572,7 @@
<span class="cm"> * is invoked.</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"> * invoked. If the frame is the final frame of the request,</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"> * invoked. If the reception of the frame triggers the</span>
<span class="cm"> * closure of the stream,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_stream_close_callback`</span>
<span class="cm"> * is invoked.</span>
@ -1600,17 +1581,20 @@
<span class="cm"> *</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"> * 2. If the received frame is valid,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is</span>
<span class="cm"> * invoked. If frame is either HEADERS or PUSH_PROMISE,</span>
<span class="cm"> *</span>
<span class="cm"> * 2. If the received frame is valid, then following actions are</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"> * 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"> * :member:`nghttp2_session_callbacks.on_end_headers_callback`</span>
<span class="cm"> * is invoked. If the frame is the final frame of the request,</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"> * pairs are emitted successfully,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is</span>
<span class="cm"> * invoked. For other frames,</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` is</span>
<span class="cm"> * invoked.</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"> * is invoked.</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_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_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="p">}</span>
</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
which HEADERS we are seeing in the callback. Therefore we just show
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
<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>
@ -555,18 +532,16 @@ its stream ID.</p>
</div>
<p>In this turotial, we just print the name/value pair.</p>
<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>
<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>
<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>
<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_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 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="k">break</span><span class="p">;</span>
<span class="p">}</span>
@ -574,8 +549,10 @@ its stream ID.</p>
<span class="p">}</span>
</pre></div>
</div>
<p>This callback may be called prematurely because of errors (e.g.,
header decompression failure) which is indicated by <tt class="docutils literal"><span class="pre">error_code</span></tt>.</p>
<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>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>
<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="p">}</span>
<span class="cm">/* nghttp2_on_end_headers_callback: Called when nghttp2 library emits</span>
<span class="cm"> all header name/value pairs, or may be called prematurely because</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_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="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="cm">/* nghttp2_on_begin_headers_callback: Called when nghttp2 library gets</span>
<span class="cm"> started to receive header block. */</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="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="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"> 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>
@ -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_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_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="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">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_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="p">}</span>
</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>.
Let&#8217;s describe remaining nghttp2 callbacks we setup in
<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
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>
<p>The <tt class="docutils literal"><span class="pre">on_begin_headers_callback()</span></tt> function is invoked when reception
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_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">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="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>
</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
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
<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>
<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>
@ -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
program, we ignore <tt class="docutils literal"><span class="pre">:method</span></tt> header field and always treat the
request as GET request.</p>
<p>It is ok for the server to start sending response in this callback (or
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
tutorial). In this example, we defer it to
<tt class="docutils literal"><span class="pre">on_request_recv_callback()</span></tt> function.</p>
<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>
<p>The <tt class="docutils literal"><span class="pre">on_frame_recv_callback()</span></tt> function is invoked when a frame is
fully received:</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="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">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="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="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">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">return</span> <span class="mi">0</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;%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="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="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>
</pre></div>
</div>
<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
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
@ -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="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="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>
@ -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="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"> 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>
@ -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="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="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="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="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="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">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="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="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>
@ -1223,13 +1192,40 @@ stream is about to close and we no longer use that object.</p>
<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="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">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="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>
@ -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">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_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="p">}</span>