Update doc

This commit is contained in:
Tatsuhiro Tsujikawa 2014-01-18 00:17:15 +09:00
parent 16bc89e743
commit 8ce9042a25
10 changed files with 321 additions and 222 deletions

View File

@ -836,13 +836,12 @@ Types (structs, unions and typedefs)
If the application uses `nghttp2_session_mem_recv()`, it can return
:macro:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
return without processing further input bytes. The *frame*
parameter is retained until `nghttp2_session_continue()` is
return without processing further input bytes. The memory by
pointed by the *data* is retained until
`nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is
called. The application must retain the input bytes which was used
to produce the *frame* parameter, because it may refer to the
memory region included in the input bytes. The application which
returns :macro:`NGHTTP2_ERR_PAUSE` must call
`nghttp2_session_continue()` before `nghttp2_session_mem_recv()`.
to produce the *data* parameter, because it may refer to the memory
region included in the input bytes.
The implementation of this function must return 0 if it
succeeds. If nonzero is returned, it is treated as fatal error and
@ -1006,14 +1005,12 @@ Types (structs, unions and typedefs)
If the application uses `nghttp2_session_mem_recv()`, it can return
:macro:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
return without processing further input bytes. The *frame*,
*name*, *namelen*, *value* and *valuelen* parameters are retained
until `nghttp2_session_continue()` is called. The application must
retain the input bytes which was used to produce the *frame*
parameter, because it may refer to the memory region included in
the input bytes. The application which returns
:macro:`NGHTTP2_ERR_PAUSE` must call `nghttp2_session_continue()`
before `nghttp2_session_mem_recv()`.
return without processing further input bytes. The memory pointed
by *frame*, *name* and *value* parameters are retained until
`nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is
called. The application must retain the input bytes which was used
to produce these parameters, because it may refer to the memory
region included in the input bytes.
The implementation of this function must return 0 if it
succeeds. It may return :macro:`NGHTTP2_ERR_PAUSE`. If the other
@ -1340,7 +1337,7 @@ Functions
In the current implementation, this function always tries to
processes all input data unless either an error occurs or
:macro:`NGHTTP2_ERR_PAUSE` is returned from
:member:`nghttp2_session_callbacks.on_frame_recv_callback` or
:member:`nghttp2_session_callbacks.on_header_callback` or
:member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`.
If :macro:`NGHTTP2_ERR_PAUSE` is used, the return value includes the
number of bytes which was used to produce the data or frame for the
@ -1354,31 +1351,6 @@ Functions
:macro:`NGHTTP2_ERR_CALLBACK_FAILURE`
The callback function failed.
.. function:: int nghttp2_session_continue(nghttp2_session *session)
Perform post-processing after `nghttp2_session_mem_recv()` was
paused by :macro:`NGHTTP2_ERR_PAUSE` from
:member:`nghttp2_session_callbacks.on_frame_recv_callback` or
:member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`.
This function frees resources associated with paused frames. It
may also call additional callbacks, such as
:member:`nghttp2_session_callbacks.on_stream_close_callback`.
If this function succeeds, the application can call
`nghttp2_session_mem_recv()` again.
This function returns 0 if it succeeds, or one of the following
negative error codes:
:macro:`NGHTTP2_ERR_NOMEM`
Out of memory.
:macro:`NGHTTP2_ERR_CALLBACK_FAILURE`
The callback function failed.
.. function:: int nghttp2_session_resume_data(nghttp2_session *session, int32_t stream_id)
@ -1642,8 +1614,7 @@ Functions
negative error codes:
:macro:`NGHTTP2_ERR_INVALID_ARGUMENT`
The *pri* is invalid; or the *nva* includes empty name, or name
which contains invalid characters.
The *pri* is invalid
:macro:`NGHTTP2_ERR_NOMEM`
Out of memory.
@ -1681,9 +1652,6 @@ Functions
This function returns 0 if it succeeds, or one of the following
negative error codes:
:macro:`NGHTTP2_ERR_INVALID_ARGUMENT`
The *nva* includes empty name or name which contains invalid
characters.
:macro:`NGHTTP2_ERR_NOMEM`
Out of memory.
@ -1733,8 +1701,7 @@ Functions
negative error codes:
:macro:`NGHTTP2_ERR_INVALID_ARGUMENT`
The *pri* is invalid; or the *nva* includes empty name, or name
which contains invalid characters.
The *pri* is invalid
:macro:`NGHTTP2_ERR_NOMEM`
Out of memory.
@ -1855,9 +1822,6 @@ Functions
This function returns 0 if it succeeds, or one of the following
negative error codes:
:macro:`NGHTTP2_ERR_INVALID_ARGUMENT`
The *nva* includes empty name, or name which contains invalid
characters.
:macro:`NGHTTP2_ERR_NOMEM`
Out of memory.

View File

@ -163,11 +163,13 @@ finished successfully. We first initialize nghttp2 session object in
callbacks.on_frame_recv_callback = on_frame_recv_callback;
callbacks.on_data_chunk_recv_callback = on_data_chunk_recv_callback;
callbacks.on_stream_close_callback = on_stream_close_callback;
callbacks.on_header_callback = on_header_callback;
callbacks.on_end_headers_callback = on_end_headers_callback;
nghttp2_session_client_new(&session_data->session, &callbacks, session_data);
}
Since we are creating client, we use `nghttp2_session_client_new()` to
initialize nghttp2 session object. We setup 5 callbacks for the
initialize nghttp2 session object. We setup 7 callbacks for the
nghttp2 session. We'll explain these callbacks later.
The `delete_http2_session_data()` destroys ``session_data`` and frees
@ -395,9 +397,8 @@ received from the remote peer::
case NGHTTP2_HEADERS:
if(frame->headers.cat == NGHTTP2_HCAT_RESPONSE &&
session_data->stream_data->stream_id == frame->hd.stream_id) {
/* Print response headers for the initiated request. */
fprintf(stderr, "Response headers:\n");
print_headers(stderr, frame->headers.nva, frame->headers.nvlen);
fprintf(stderr, "Response headers for stream ID=%d:\n",
frame->hd.stream_id);
}
break;
}
@ -409,6 +410,53 @@ 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::
static int 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)
{
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) {
/* Print response headers for the initiated request. */
print_header(stderr, name, namelen, value, valuelen);
break;
}
}
return 0;
}
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::
static int on_end_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame,
nghttp2_error_code error_code,
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);
}
break;
}
return 0;
}
This callback may be called prematurely because of errors (e.g.,
header decompression failure) which is indicated by ``error_code``.
The ``on_data_chunk_recv_callback()`` function is invoked when a chunk
of data is received from the remote peer::

View File

@ -243,11 +243,12 @@ We initialize nghttp2 session object which is done in
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;
nghttp2_session_server_new(&session_data->session, &callbacks, session_data);
}
Since we are creating server, nghttp2 session object is created using
`nghttp2_session_server_new()` function. We registers 4 callbacks to
`nghttp2_session_server_new()` function. We registers 5 callbacks to
nghttp2 session object. We'll talk about these callbacks later.
After initialization of nghttp2 session object, we are going to send
@ -421,8 +422,6 @@ received from the remote peer::
{
http2_session_data *session_data = (http2_session_data*)user_data;
http2_stream_data *stream_data;
size_t i;
const char PATH[] = ":path";
switch(frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
@ -431,16 +430,6 @@ received from the remote peer::
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);
for(i = 0; i < frame->headers.nvlen; ++i) {
nghttp2_nv *nv = &frame->headers.nva[i];
if(nv->namelen == sizeof(PATH) - 1 &&
memcmp(PATH, nv->name, nv->namelen) == 0) {
size_t j;
for(j = 0; j < nv->valuelen && nv->value[j] != '?'; ++j);
stream_data->request_path = percent_decode(nv->value, j);
break;
}
}
break;
default:
break;
@ -457,13 +446,47 @@ in nghttp2 session object using `nghttp2_set_stream_user_data()` in
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. We search ``:path`` header
field in request headers and keep the requested path in
``http2_stream_data`` object. In this example program, we ignore
``:method`` header field and always treat the request as GET request.
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()``::
It is ok for the server to start sending response in this callback. In
this example, we defer it to ``on_request_recv_callback()`` function.
static int 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)
{
http2_stream_data *stream_data;
const char PATH[] = ":path";
switch(frame->hd.type) {
case NGHTTP2_HEADERS:
if(frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
break;
}
stream_data = nghttp2_session_get_stream_user_data(session,
frame->hd.stream_id);
if(stream_data->request_path) {
break;
}
if(namelen == sizeof(PATH) - 1 && memcmp(PATH, name, namelen) == 0) {
size_t j;
for(j = 0; j < valuelen && value[j] != '?'; ++j);
stream_data->request_path = percent_decode(value, j);
}
break;
}
return 0;
}
We search ``:path`` header field in request headers and keep the
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_request_recv_callback()`` function is invoked when all HTTP
request, including entity body, was received::

View File

@ -1343,13 +1343,12 @@ 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>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
<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> to make <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>
return without processing further input bytes. The <em>frame</em>
parameter is retained until <a class="reference internal" href="#nghttp2_session_continue" title="nghttp2_session_continue"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_continue()</span></tt></a> is
return without processing further input bytes. The memory by
pointed by the <em>data</em> is retained until
<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> or <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> is
called. The application must retain the input bytes which was used
to produce the <em>frame</em> parameter, because it may refer to the
memory region included in the input bytes. The application which
returns <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> must call
<a class="reference internal" href="#nghttp2_session_continue" title="nghttp2_session_continue"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_continue()</span></tt></a> before <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>.</p>
to produce the <em>data</em> parameter, because it may refer to the memory
region included in the input bytes.</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_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
@ -1511,14 +1510,12 @@ application returns nonzero value from this callback.</p>
can be said about the <em>value</em>.</p>
<p>If the application uses <a class="reference internal" href="#nghttp2_session_mem_recv" title="nghttp2_session_mem_recv"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_mem_recv()</span></tt></a>, it can return
<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> to make <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>
return without processing further input bytes. The <em>frame</em>,
<em>name</em>, <em>namelen</em>, <em>value</em> and <em>valuelen</em> parameters are retained
until <a class="reference internal" href="#nghttp2_session_continue" title="nghttp2_session_continue"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_continue()</span></tt></a> is called. The application must
retain the input bytes which was used to produce the <em>frame</em>
parameter, because it may refer to the memory region included in
the input bytes. The application which returns
<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> must call <a class="reference internal" href="#nghttp2_session_continue" title="nghttp2_session_continue"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_continue()</span></tt></a>
before <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>.</p>
return without processing further input bytes. The memory pointed
by <em>frame</em>, <em>name</em> and <em>value</em> parameters are retained until
<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> or <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> is
called. The application must retain the input bytes which was used
to produce these parameters, because it may refer to the memory
region included in the input bytes.</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>. If the other
nonzero value is returned, it is treated as fatal error and
@ -1901,7 +1898,7 @@ other callbacks are called in the same way as they are in
<p>In the current implementation, this function always tries to
processes all input data unless either an error occurs or
<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> is returned from
<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> or
<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> or
<a class="reference internal" href="#nghttp2_session_callbacks.on_data_chunk_recv_callback" title="nghttp2_session_callbacks.on_data_chunk_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_data_chunk_recv_callback</span></tt></a>.
If <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> is used, the return value includes the
number of bytes which was used to produce the data or frame for the
@ -1916,28 +1913,6 @@ following negative error codes:</p>
</dl>
</dd></dl>
<dl class="function">
<dt id="nghttp2_session_continue">
int <tt class="descname">nghttp2_session_continue</tt><big>(</big><a class="reference internal" href="#nghttp2_session" title="nghttp2_session">nghttp2_session</a><em>&nbsp;*session</em><big>)</big><a class="headerlink" href="#nghttp2_session_continue" title="Permalink to this definition"></a></dt>
<dd><p>Perform post-processing after <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> was
paused by <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> from
<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> or
<a class="reference internal" href="#nghttp2_session_callbacks.on_data_chunk_recv_callback" title="nghttp2_session_callbacks.on_data_chunk_recv_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.on_data_chunk_recv_callback</span></tt></a>.</p>
<p>This function frees resources associated with paused frames. It
may also call additional callbacks, such as
<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>.</p>
<p>If this function succeeds, the application can call
<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> again.</p>
<p>This function returns 0 if it succeeds, or one of the following
negative error codes:</p>
<dl class="docutils">
<dt><a class="reference internal" href="#NGHTTP2_ERR_NOMEM" title="NGHTTP2_ERR_NOMEM"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_NOMEM</span></tt></a></dt>
<dd>Out of memory.</dd>
<dt><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></dt>
<dd>The callback function failed.</dd>
</dl>
</dd></dl>
<dl class="function">
<dt id="nghttp2_session_resume_data">
int <tt class="descname">nghttp2_session_resume_data</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><big>)</big><a class="headerlink" href="#nghttp2_session_resume_data" title="Permalink to this definition"></a></dt>
@ -2194,8 +2169,7 @@ the stream is already opened,
negative error codes:</p>
<dl class="docutils">
<dt><a class="reference internal" href="#NGHTTP2_ERR_INVALID_ARGUMENT" title="NGHTTP2_ERR_INVALID_ARGUMENT"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_INVALID_ARGUMENT</span></tt></a></dt>
<dd>The <em>pri</em> is invalid; or the <em>nva</em> includes empty name, or name
which contains invalid characters.</dd>
<dd>The <em>pri</em> is invalid</dd>
<dt><a class="reference internal" href="#NGHTTP2_ERR_NOMEM" title="NGHTTP2_ERR_NOMEM"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_NOMEM</span></tt></a></dt>
<dd>Out of memory.</dd>
</dl>
@ -2229,9 +2203,6 @@ must be reserved using <a class="reference internal" href="#nghttp2_submit_push_
<p>This function returns 0 if it succeeds, or one of the following
negative error codes:</p>
<dl class="docutils">
<dt><a class="reference internal" href="#NGHTTP2_ERR_INVALID_ARGUMENT" title="NGHTTP2_ERR_INVALID_ARGUMENT"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_INVALID_ARGUMENT</span></tt></a></dt>
<dd>The <em>nva</em> includes empty name or name which contains invalid
characters.</dd>
<dt><a class="reference internal" href="#NGHTTP2_ERR_NOMEM" title="NGHTTP2_ERR_NOMEM"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_NOMEM</span></tt></a></dt>
<dd>Out of memory.</dd>
</dl>
@ -2276,8 +2247,7 @@ specify flags directly. For usual HTTP request,
negative error codes:</p>
<dl class="docutils">
<dt><a class="reference internal" href="#NGHTTP2_ERR_INVALID_ARGUMENT" title="NGHTTP2_ERR_INVALID_ARGUMENT"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_INVALID_ARGUMENT</span></tt></a></dt>
<dd>The <em>pri</em> is invalid; or the <em>nva</em> includes empty name, or name
which contains invalid characters.</dd>
<dd>The <em>pri</em> is invalid</dd>
<dt><a class="reference internal" href="#NGHTTP2_ERR_NOMEM" title="NGHTTP2_ERR_NOMEM"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_NOMEM</span></tt></a></dt>
<dd>Out of memory.</dd>
</dl>
@ -2391,9 +2361,6 @@ server. But in normal HTTP usage, the server may treat it error.</p>
<p>This function returns 0 if it succeeds, or one of the following
negative error codes:</p>
<dl class="docutils">
<dt><a class="reference internal" href="#NGHTTP2_ERR_INVALID_ARGUMENT" title="NGHTTP2_ERR_INVALID_ARGUMENT"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_INVALID_ARGUMENT</span></tt></a></dt>
<dd>The <em>nva</em> includes empty name, or name which contains invalid
characters.</dd>
<dt><a class="reference internal" href="#NGHTTP2_ERR_NOMEM" title="NGHTTP2_ERR_NOMEM"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_ERR_NOMEM</span></tt></a></dt>
<dd>Out of memory.</dd>
</dl>

View File

@ -614,12 +614,12 @@
<dt><a href="apiref.html#nghttp2_on_frame_not_send_callback">nghttp2_on_frame_not_send_callback (C type)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="apiref.html#nghttp2_on_frame_recv_callback">nghttp2_on_frame_recv_callback (C type)</a>
</dt>
</dl></td>
<td style="width: 33%" valign="top"><dl>
<dt><a href="apiref.html#nghttp2_on_frame_recv_parse_error_callback">nghttp2_on_frame_recv_parse_error_callback (C type)</a>
</dt>
@ -869,10 +869,6 @@
</dt>
<dt><a href="apiref.html#nghttp2_session_continue">nghttp2_session_continue (C function)</a>
</dt>
<dt><a href="apiref.html#nghttp2_session_del">nghttp2_session_del (C function)</a>
</dt>

View File

@ -1051,13 +1051,12 @@
<span class="cm"> *</span>
<span class="cm"> * If the application uses `nghttp2_session_mem_recv()`, it can return</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`</span>
<span class="cm"> * return without processing further input bytes. The |frame|</span>
<span class="cm"> * parameter is retained until `nghttp2_session_continue()` is</span>
<span class="cm"> * return without processing further input bytes. The memory by</span>
<span class="cm"> * pointed by the |data| is retained until</span>
<span class="cm"> * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is</span>
<span class="cm"> * called. The application must retain the input bytes which was used</span>
<span class="cm"> * to produce the |frame| parameter, because it may refer to the</span>
<span class="cm"> * memory region included in the input bytes. The application which</span>
<span class="cm"> * returns :enum:`NGHTTP2_ERR_PAUSE` must call</span>
<span class="cm"> * `nghttp2_session_continue()` before `nghttp2_session_mem_recv()`.</span>
<span class="cm"> * to produce the |data| parameter, because it may refer to the memory</span>
<span class="cm"> * region included in the input bytes.</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>
@ -1262,14 +1261,12 @@
<span class="cm"> *</span>
<span class="cm"> * If the application uses `nghttp2_session_mem_recv()`, it can return</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`</span>
<span class="cm"> * return without processing further input bytes. The |frame|,</span>
<span class="cm"> * |name|, |namelen|, |value| and |valuelen| parameters are retained</span>
<span class="cm"> * until `nghttp2_session_continue()` is called. The application must</span>
<span class="cm"> * retain the input bytes which was used to produce the |frame|</span>
<span class="cm"> * parameter, because it may refer to the memory region included in</span>
<span class="cm"> * the input bytes. The application which returns</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_PAUSE` must call `nghttp2_session_continue()`</span>
<span class="cm"> * before `nghttp2_session_mem_recv()`.</span>
<span class="cm"> * return without processing further input bytes. The memory pointed</span>
<span class="cm"> * by |frame|, |name| and |value| parameters are retained until</span>
<span class="cm"> * `nghttp2_session_mem_recv()` or `nghttp2_session_recv()` is</span>
<span class="cm"> * called. The application must retain the input bytes which was used</span>
<span class="cm"> * to produce these parameters, because it may refer to the memory</span>
<span class="cm"> * region included in the input bytes.</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`. If the other</span>
@ -1686,7 +1683,7 @@
<span class="cm"> * In the current implementation, this function always tries to</span>
<span class="cm"> * processes all input data unless either an error occurs or</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_PAUSE` is returned from</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` or</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_header_callback` or</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`.</span>
<span class="cm"> * If :enum:`NGHTTP2_ERR_PAUSE` is used, the return value includes the</span>
<span class="cm"> * number of bytes which was used to produce the data or frame for the</span>
@ -1703,33 +1700,6 @@
<span class="kt">ssize_t</span> <span class="nf">nghttp2_session_mem_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="k">const</span> <span class="kt">uint8_t</span> <span class="o">*</span><span class="n">in</span><span class="p">,</span> <span class="kt">size_t</span> <span class="n">inlen</span><span class="p">);</span>
<span class="cm">/**</span>
<span class="cm"> * @function</span>
<span class="cm"> *</span>
<span class="cm"> * Perform post-processing after `nghttp2_session_mem_recv()` was</span>
<span class="cm"> * paused by :enum:`NGHTTP2_ERR_PAUSE` from</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_frame_recv_callback` or</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`.</span>
<span class="cm"> *</span>
<span class="cm"> * This function frees resources associated with paused frames. It</span>
<span class="cm"> * may also call additional callbacks, such as</span>
<span class="cm"> * :member:`nghttp2_session_callbacks.on_stream_close_callback`.</span>
<span class="cm"> *</span>
<span class="cm"> * If this function succeeds, the application can call</span>
<span class="cm"> * `nghttp2_session_mem_recv()` again.</span>
<span class="cm"> *</span>
<span class="cm"> * This function returns 0 if it succeeds, or one of the following</span>
<span class="cm"> * negative error codes:</span>
<span class="cm"> *</span>
<span class="cm"> *</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_NOMEM`</span>
<span class="cm"> * Out of memory.</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`</span>
<span class="cm"> * The callback function failed.</span>
<span class="cm"> *</span>
<span class="cm"> */</span>
<span class="kt">int</span> <span class="nf">nghttp2_session_continue</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="cm">/**</span>
<span class="cm"> * @function</span>
<span class="cm"> *</span>
@ -2035,8 +2005,7 @@
<span class="cm"> * negative error codes:</span>
<span class="cm"> *</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`</span>
<span class="cm"> * The |pri| is invalid; or the |nva| includes empty name, or name</span>
<span class="cm"> * which contains invalid characters.</span>
<span class="cm"> * The |pri| is invalid</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_NOMEM`</span>
<span class="cm"> * Out of memory.</span>
<span class="cm"> */</span>
@ -2079,9 +2048,6 @@
<span class="cm"> * This function returns 0 if it succeeds, or one of the following</span>
<span class="cm"> * negative error codes:</span>
<span class="cm"> *</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`</span>
<span class="cm"> * The |nva| includes empty name or name which contains invalid</span>
<span class="cm"> * characters.</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_NOMEM`</span>
<span class="cm"> * Out of memory.</span>
<span class="cm"> */</span>
@ -2136,8 +2102,7 @@
<span class="cm"> * negative error codes:</span>
<span class="cm"> *</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`</span>
<span class="cm"> * The |pri| is invalid; or the |nva| includes empty name, or name</span>
<span class="cm"> * which contains invalid characters.</span>
<span class="cm"> * The |pri| is invalid</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_NOMEM`</span>
<span class="cm"> * Out of memory.</span>
<span class="cm"> */</span>
@ -2278,9 +2243,6 @@
<span class="cm"> * This function returns 0 if it succeeds, or one of the following</span>
<span class="cm"> * negative error codes:</span>
<span class="cm"> *</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_INVALID_ARGUMENT`</span>
<span class="cm"> * The |nva| includes empty name, or name which contains invalid</span>
<span class="cm"> * characters.</span>
<span class="cm"> * :enum:`NGHTTP2_ERR_NOMEM`</span>
<span class="cm"> * Out of memory.</span>
<span class="cm"> */</span>

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -292,12 +292,14 @@ finished successfully. We first initialize nghttp2 session object in
<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_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">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>
</div>
<p>Since we are creating client, we use <a class="reference internal" href="apiref.html#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> to
initialize nghttp2 session object. We setup 5 callbacks for the
initialize nghttp2 session object. We setup 7 callbacks for the
nghttp2 session. We&#8217;ll explain these callbacks later.</p>
<p>The <tt class="xref c c-func docutils literal"><span class="pre">delete_http2_session_data()</span></tt> destroys <tt class="docutils literal"><span class="pre">session_data</span></tt> and frees
its bufferevent, so it closes underlying connection as well. It also
@ -516,9 +518,8 @@ received from the remote peer:</p>
<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="cm">/* Print response headers for the initiated request. */</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:</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">print_headers</span><span class="p">(</span><span class="n">stderr</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">nva</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">nvlen</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>
@ -530,6 +531,51 @@ received from the remote peer:</p>
HEADERS. We check te frame type and its category (it should be
<a class="reference internal" href="apiref.html#NGHTTP2_HCAT_RESPONSE" title="NGHTTP2_HCAT_RESPONSE"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_HCAT_RESPONSE</span></tt></a> for HTTP response HEADERS). Also check
its stream ID.</p>
<p>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>
<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_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="cm">/* Print response headers for the initiated request. */</span>
<span class="n">print_header</span><span class="p">(</span><span class="n">stderr</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="n">value</span><span class="p">,</span> <span class="n">valuelen</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
</pre></div>
</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>
<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>
</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>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>
@ -733,6 +779,16 @@ here.</p>
<span class="n">free</span><span class="p">(</span><span class="n">session_data</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">static</span> <span class="kt">void</span> <span class="nf">print_header</span><span class="p">(</span><span class="kt">FILE</span> <span class="o">*</span><span class="n">f</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="p">{</span>
<span class="n">fwrite</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="mi">1</span><span class="p">,</span> <span class="n">f</span><span class="p">);</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="s">&quot;: &quot;</span><span class="p">);</span>
<span class="n">fwrite</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">valuelen</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">f</span><span class="p">);</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* Print HTTP headers to |f|. Please note that this function does not</span>
<span class="cm"> take into account that header name and value are sequence of</span>
<span class="cm"> octets, therefore they may contain non-printable characters. */</span>
@ -740,12 +796,11 @@ here.</p>
<span class="p">{</span>
<span class="kt">size_t</span> <span class="n">i</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">nvlen</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
<span class="n">fwrite</span><span class="p">(</span><span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">name</span><span class="p">,</span> <span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">namelen</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">stderr</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;: &quot;</span><span class="p">);</span>
<span class="n">fwrite</span><span class="p">(</span><span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span><span class="p">,</span> <span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">valuelen</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="n">stderr</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;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">print_header</span><span class="p">(</span><span class="n">f</span><span class="p">,</span>
<span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">name</span><span class="p">,</span> <span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">namelen</span><span class="p">,</span>
<span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">value</span><span class="p">,</span> <span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">valuelen</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;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">fprintf</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="s">&quot;</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/* nghttp2_send_callback. Here we transmit the |data|, |length| bytes,</span>
@ -783,6 +838,47 @@ 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_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_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="cm">/* Print response headers for the initiated request. */</span>
<span class="n">print_header</span><span class="p">(</span><span class="n">stderr</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="n">value</span><span class="p">,</span> <span class="n">valuelen</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="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>
@ -793,9 +889,8 @@ here.</p>
<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="cm">/* Print response headers for the initiated request. */</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:</span><span class="se">\n</span><span class="s">&quot;</span><span class="p">);</span>
<span class="n">print_headers</span><span class="p">(</span><span class="n">stderr</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">nva</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">nvlen</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>
@ -893,6 +988,8 @@ here.</p>
<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_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">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

@ -369,12 +369,13 @@ these 2 functions later.</p>
<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">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>
</div>
<p>Since we are creating server, nghttp2 session object is created using
<a class="reference internal" href="apiref.html#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> function. We registers 4 callbacks to
<a class="reference internal" href="apiref.html#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> function. We registers 5 callbacks to
nghttp2 session object. We&#8217;ll talk about these callbacks later.</p>
<p>After initialization of nghttp2 session object, we are going to send
server connection header in <tt class="docutils literal"><span class="pre">send_server_connection_header()</span></tt>:</p>
@ -540,8 +541,6 @@ received from the remote peer:</p>
<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="kt">size_t</span> <span class="n">i</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>
@ -550,16 +549,6 @@ received from the remote peer:</p>
<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">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">nvlen</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
<span class="n">nghttp2_nv</span> <span class="o">*</span><span class="n">nv</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="n">nv</span><span class="o">-&gt;</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">nv</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> <span class="n">nv</span><span class="o">-&gt;</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">nv</span><span class="o">-&gt;</span><span class="n">valuelen</span> <span class="o">&amp;&amp;</span> <span class="n">nv</span><span class="o">-&gt;</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">nv</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">,</span> <span class="n">j</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</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>
@ -576,12 +565,46 @@ data. We associate created <tt class="docutils literal"><span class="pre">http2_
in nghttp2 session object using <tt class="xref c c-func docutils literal"><span class="pre">nghttp2_set_stream_user_data()</span></tt> in
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. We search <tt class="docutils literal"><span class="pre">:path</span></tt> header
field in request headers and keep the 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. In
this example, we defer it to <tt class="docutils literal"><span class="pre">on_request_recv_callback()</span></tt> function.</p>
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>
<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>
<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>
</pre></div>
</div>
<p>We search <tt class="docutils literal"><span class="pre">:path</span></tt> header field in request headers and keep the
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>
@ -1033,13 +1056,41 @@ 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="kt">size_t</span> <span class="n">i</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>
@ -1048,16 +1099,6 @@ stream is about to close and we no longer use that object.</p>
<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">for</span><span class="p">(</span><span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">nvlen</span><span class="p">;</span> <span class="o">++</span><span class="n">i</span><span class="p">)</span> <span class="p">{</span>
<span class="n">nghttp2_nv</span> <span class="o">*</span><span class="n">nv</span> <span class="o">=</span> <span class="o">&amp;</span><span class="n">frame</span><span class="o">-&gt;</span><span class="n">headers</span><span class="p">.</span><span class="n">nva</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="n">nv</span><span class="o">-&gt;</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">nv</span><span class="o">-&gt;</span><span class="n">name</span><span class="p">,</span> <span class="n">nv</span><span class="o">-&gt;</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">nv</span><span class="o">-&gt;</span><span class="n">valuelen</span> <span class="o">&amp;&amp;</span> <span class="n">nv</span><span class="o">-&gt;</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">nv</span><span class="o">-&gt;</span><span class="n">value</span><span class="p">,</span> <span class="n">j</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</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>
@ -1211,6 +1252,7 @@ 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">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">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>