Update doc

This commit is contained in:
Tatsuhiro Tsujikawa 2013-12-28 22:12:05 +09:00
parent 72ba3397bb
commit d813ae89f6
8 changed files with 123 additions and 114 deletions

View File

@ -12,7 +12,7 @@ resource denoted by the URI. Its synopsis is like this::
$ libevent-client HTTPS_URI
We use libevent in this tutorial to handle networking I/O. Please
note that nghttp2 iteself does not depends on libevent.
note that nghttp2 itself does not depend on libevent.
First we do some setup routine for libevent and OpenSSL library in
function ``main()`` and ``run()``, which is not so relevant to nghttp2
@ -119,8 +119,8 @@ We set 3 callbacks for the bufferevent: ``reacb``, ``writecb`` and
``eventcb``.
The ``eventcb()`` is invoked by libevent event loop when an event
(e.g., connection established, timeout, etc) happens on the underlying
network socket::
(e.g., connection has been established, timeout, etc) happens on the
underlying network socket::
static void eventcb(struct bufferevent *bev, short events, void *ptr)
{
@ -281,8 +281,8 @@ frames. The ``session_send()`` function is defined as follows::
}
The `nghttp2_session_send()` function serializes the frame into wire
format and call :member:`nghttp2_callbacks.nghttp2_send_callback` with
it. We set ``send_callback()`` function as
format and call :member:`nghttp2_session_callbacks.send_callback` with
it. We set ``send_callback()`` function to
:member:`nghttp2_session_callbacks.send_callback` in
``initialize_nghttp2_session()`` function described earlier. It is
defined as follows::
@ -332,7 +332,7 @@ conditions as well. Using these information, nghttp2 session object
will tell whether the connection should be dropped or not. More
specifically, both `nghttp2_session_want_read()` and
`nghttp2_session_want_write()` return 0, we have no business in the
connection. But since we have using bufferevent and its deferred
connection. But since we are using bufferevent and its deferred
callback option, the bufferevent output buffer may contain the pending
data when the ``writecb()`` is called. To handle this situation, we
also check whether the output buffer is empty or not. If these

View File

@ -2,10 +2,10 @@ Tutorial: HTTP/2.0 server
=========================
In this tutorial, we are going to write single-threaded, event-based
HTTP/2.0 web server, which supports HTTPS. It can handle concurrent
multiple requests, but only GET method is supported. The complete
source code, `libevent-server.c`_, is attached at the end of this
page. It also resides in examples directory in the archive or
HTTP/2.0 web server, which supports HTTPS only. It can handle
concurrent multiple requests, but only GET method is supported. The
complete source code, `libevent-server.c`_, is attached at the end of
this page. It also resides in examples directory in the archive or
repository.
This simple server takes 3 arguments, a port number to listen to, a
@ -15,17 +15,17 @@ is like this::
$ libevent-server PORT /path/to/server.key /path/to/server.crt
We use libevent in this tutorial to handle networking I/O. Please
note that nghttp2 iteself does not depends on libevent.
note that nghttp2 itself does not depend on libevent.
First we do some setup routine for libevent and OpenSSL library in
function ``main()`` and ``run()``, which is not so relevant to nghttp2
library use. The one thing you should look at is setup NPN callback.
The NPN callback is used for the server to advertise the application
protocols the server supports to a client. In this example program,
when creating SSL_CTX object, we stores the application protocol name
in the wire format of NPN in statically allocated buffer. This is safe
because we only create 1 SSL_CTX object in the entire program life
time::
when creating ``SSL_CTX`` object, we stores the application protocol
name in the wire format of NPN in statically allocated buffer. This is
safe because we only create 1 ``SSL_CTX`` object in the entire program
life time::
static unsigned char next_proto_list[256];
static size_t next_proto_list_len;
@ -55,14 +55,14 @@ time::
return ssl_ctx;
}
The wire format of NPN is array of length prefixed string. The exactly
one byte is used to specify the length of the protocol identifier. In
this tutorial, we advertise the HTTP/2.0 protocol the nghttp2 library
supports. We export its identifier in
:macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function is
the server-side NPN callback. In OpenSSL implementation, We just
The wire format of NPN is a sequence of length prefixed string. The
exactly one byte is used to specify the length of each protocol
identifier. In this tutorial, we advertise the HTTP/2.0 protocol the
nghttp2 library supports. The nghttp2 library exports its identifier
in :macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function
is the server-side NPN callback. In OpenSSL implementation, we just
assign the pointer to the NPN buffers we filled earlier. The NPN
callback function is set to SSL_CTX object using
callback function is set to ``SSL_CTX`` object using
``SSL_CTX_set_next_protos_advertised_cb()``.
We use ``app_content`` structure to store the application-wide data::
@ -100,7 +100,8 @@ object in O(1). The first element of this list is pointed by the
``root->next`` in ``http2_session_data``. Initially, ``root->next``
is ``NULL``. The ``handshake_leftlen`` member of
``http2_session_data`` is used to track the number of bytes remaining
when receiving first 24 bytes magic values from the client. We use
when receiving first 24 bytes magic value
(:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`) from the client. We use
libevent's bufferevent structure to perform network I/O. Notice that
bufferevent object is in ``http2_session_data`` and not in
``http2_stream_data``. This is because ``http2_stream_data`` is just a
@ -161,8 +162,8 @@ connection is also initialized at this time. We specify 2 callbacks
for the bufferevent: ``handshake_readcb`` and ``eventcb``.
The ``eventcb()`` is invoked by libevent event loop when an event
(e.g., connection established, timeout, etc) happens on the underlying
network socket::
(e.g., connection has been established, timeout, etc) happens on the
underlying network socket::
static void eventcb(struct bufferevent *bev, short events, void *ptr)
{
@ -223,13 +224,13 @@ it::
}
}
Nothing special here, we just compare the magic byte string received
and expected one :macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`. When
whole magic byte string is received, the connection state is ready for
starting HTTP/2.0 communication. First we change the callback
functions for the bufferevent object. We use same ``eventcb`` as
before. But we specify new ``readcb`` and ``writecb`` function to
handle HTTP/2.0 communication. We describe these 2 functions later.
We check that the received byte string matches
:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`. When they match, the
connection state is ready for starting HTTP/2.0 communication. First
we change the callback functions for the bufferevent object. We use
same ``eventcb`` as before. But we specify new ``readcb`` and
``writecb`` function to handle HTTP/2.0 communication. We describe
these 2 functions later.
We initialize nghttp2 session object which is done in
``initialize_nghttp2_session()``::
@ -303,9 +304,9 @@ functions for these pending data. To process received data, we call
In this function, we feed all unprocessed, received data to nghttp2
session object using `nghttp2_session_mem_recv()` function. The
`nghttp2_session_mem_recv()` processes the received data and may
invoke nghttp2 callbacks and also queue frames. Since there may be
pending frames, we call ``session_send()`` function to send those
frames. The ``session_send()`` function is defined as follows::
invoke nghttp2 callbacks and also queue outgoing frames. Since there
may be pending frames, we call ``session_send()`` function to send
those frames. The ``session_send()`` function is defined as follows::
static int session_send(http2_session_data *session_data)
{
@ -319,8 +320,8 @@ frames. The ``session_send()`` function is defined as follows::
}
The `nghttp2_session_send()` function serializes the frame into wire
format and call :member:`nghttp2_callbacks.nghttp2_send_callback` with
it. We set ``send_callback()`` function as
format and call :member:`nghttp2_session_callbacks.send_callback` with
it. We set ``send_callback()`` function to
:member:`nghttp2_session_callbacks.send_callback` in
``initialize_nghttp2_session()`` function described earlier. It is
defined as follows::
@ -397,7 +398,7 @@ frame and other error conditions as well. Using these information,
nghttp2 session object will tell whether the connection should be
dropped or not. More specifically, both `nghttp2_session_want_read()`
and `nghttp2_session_want_write()` return 0, we have no business in
the connection. But since we have using bufferevent and its deferred
the connection. But since we are using bufferevent and its deferred
callback option, the bufferevent output buffer may contain the pending
data when the ``writecb()`` is called. To handle this situation, we
also check whether the output buffer is empty or not. If these
@ -406,7 +407,7 @@ conditions are met, we drop connection.
Otherwise, we call ``session_send()`` to process pending output
data. Remember that in ``send_callback()``, we may not write all data
to bufferevent to avoid excessive buffering. We continue process
pending data if output buffer becomes empty.
pending data when output buffer becomes empty.
We have already described about nghttp2 callback ``send_callback()``.
Let's describe remaining nghttp2 callbacks we setup in
@ -447,17 +448,17 @@ received from the remote peer::
return 0;
}
We only interested HEADERS frame in this function. Since HEADERS frame
has several roles in HTTP/2.0 protocol, we check that it is a request
HEADERS, which opens new stream. If frame is request HEADERS, then we
create ``http2_stream_data`` object to store stream related data. We
associate created ``http2_stream_data`` object to the stream in
nghttp2 session object using `nghttp2_set_stream_user_data()` in order
to get the object without searching through doubly linked list.
We only interested in HEADERS frame in this function. Since HEADERS
frame has several roles in HTTP/2.0 protocol, we check that it is a
request HEADERS, which opens new stream. If frame is request HEADERS,
then we create ``http2_stream_data`` object to store stream related
data. We associate created ``http2_stream_data`` object to the stream
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 server static file relative to the
current working directory the program was invoked. We search ``:path``
header field in request headers and keep the requested path in
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.
@ -588,7 +589,7 @@ is about to close::
}
We destroy ``http2_stream_data`` object in this function since the
stream is about to close and we no longer to use that object.
stream is about to close and we no longer use that object.
libevent-server.c

2
_static/jquery.js vendored
View File

@ -11,7 +11,7 @@
* Copyright 2011, The Dojo Foundation
* Released under the MIT, BSD, and GPL Licenses.
*
* Date: Thu Aug 1 23:20:30 BRT 2013
* Date: Fri Jul 5 14:07:58 UTC 2013
*/
(function( window, undefined ) {

View File

@ -239,8 +239,13 @@ var Search = {
},
loadIndex : function(url) {
$.ajax({type: "GET", url: url, data: null, success: null,
dataType: "script", cache: true});
$.ajax({type: "GET", url: url, data: null,
dataType: "script", cache: true,
complete: function(jqxhr, textstatus) {
if (textstatus != "success") {
document.getElementById("searchindexloader").src = url;
}
}});
},
setIndex : function(index) {
@ -457,16 +462,18 @@ var Search = {
displayNextItem();
});
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
$.get(DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' +
item[0] + '.txt', function(data) {
if (data != '') {
listItem.append($.makeSearchSummary(data, searchterms, hlterms));
Search.output.append(listItem);
}
listItem.slideDown(5, function() {
displayNextItem();
});
}, "text");
$.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
dataType: "text",
complete: function(jqxhr, textstatus) {
var data = jqxhr.responseText;
if (data !== '') {
listItem.append($.makeSearchSummary(data, searchterms, hlterms));
}
Search.output.append(listItem);
listItem.slideDown(5, function() {
displayNextItem();
});
}});
} else {
// no source available, just display title
Search.output.append(listItem);

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -144,7 +144,7 @@ resource denoted by the URI. Its synopsis is like this:</p>
<div class="highlight-c"><pre>$ libevent-client HTTPS_URI</pre>
</div>
<p>We use libevent in this tutorial to handle networking I/O. Please
note that nghttp2 iteself does not depends on libevent.</p>
note that nghttp2 itself does not depend on libevent.</p>
<p>First we do some setup routine for libevent and OpenSSL library in
function <tt class="docutils literal"><span class="pre">main()</span></tt> and <tt class="docutils literal"><span class="pre">run()</span></tt>, which is not so relevant to nghttp2
library use. The one thing you should look at is setup NPN callback.
@ -248,8 +248,8 @@ the remote server:</p>
<p>We set 3 callbacks for the bufferevent: <tt class="docutils literal"><span class="pre">reacb</span></tt>, <tt class="docutils literal"><span class="pre">writecb</span></tt> and
<tt class="docutils literal"><span class="pre">eventcb</span></tt>.</p>
<p>The <tt class="docutils literal"><span class="pre">eventcb()</span></tt> is invoked by libevent event loop when an event
(e.g., connection established, timeout, etc) happens on the underlying
network socket:</p>
(e.g., connection has been established, timeout, etc) happens on the
underlying network socket:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">eventcb</span><span class="p">(</span><span class="k">struct</span> <span class="n">bufferevent</span> <span class="o">*</span><span class="n">bev</span><span class="p">,</span> <span class="kt">short</span> <span class="n">events</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</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">ptr</span><span class="p">;</span>
@ -406,8 +406,8 @@ frames. The <tt class="docutils literal"><span class="pre">session_send()</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="apiref.html#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> function serializes the frame into wire
format and call <tt class="xref c c-member docutils literal"><span class="pre">nghttp2_callbacks.nghttp2_send_callback</span></tt> with
it. We set <tt class="docutils literal"><span class="pre">send_callback()</span></tt> function as
format and call <a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> with
it. We set <tt class="docutils literal"><span class="pre">send_callback()</span></tt> function to
<a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> in
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt> function described earlier. It is
defined as follows:</p>
@ -456,7 +456,7 @@ conditions as well. Using these information, nghttp2 session object
will tell whether the connection should be dropped or not. More
specifically, both <a class="reference internal" href="apiref.html#nghttp2_session_want_read" title="nghttp2_session_want_read"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_read()</span></tt></a> and
<a class="reference internal" href="apiref.html#nghttp2_session_want_write" title="nghttp2_session_want_write"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_write()</span></tt></a> return 0, we have no business in the
connection. But since we have using bufferevent and its deferred
connection. But since we are using bufferevent and its deferred
callback option, the bufferevent output buffer may contain the pending
data when the <tt class="docutils literal"><span class="pre">writecb()</span></tt> is called. To handle this situation, we
also check whether the output buffer is empty or not. If these

View File

@ -136,10 +136,10 @@
<div class="section" id="tutorial-http-2-0-server">
<h1>Tutorial: HTTP/2.0 server<a class="headerlink" href="#tutorial-http-2-0-server" title="Permalink to this headline"></a></h1>
<p>In this tutorial, we are going to write single-threaded, event-based
HTTP/2.0 web server, which supports HTTPS. It can handle concurrent
multiple requests, but only GET method is supported. The complete
source code, <a class="reference internal" href="#libevent-server-c">libevent-server.c</a>, is attached at the end of this
page. It also resides in examples directory in the archive or
HTTP/2.0 web server, which supports HTTPS only. It can handle
concurrent multiple requests, but only GET method is supported. The
complete source code, <a class="reference internal" href="#libevent-server-c">libevent-server.c</a>, is attached at the end of
this page. It also resides in examples directory in the archive or
repository.</p>
<p>This simple server takes 3 arguments, a port number to listen to, a
path to SSL/TLS private key file and certificate file. Its synopsis
@ -147,16 +147,16 @@ is like this:</p>
<div class="highlight-c"><pre>$ libevent-server PORT /path/to/server.key /path/to/server.crt</pre>
</div>
<p>We use libevent in this tutorial to handle networking I/O. Please
note that nghttp2 iteself does not depends on libevent.</p>
note that nghttp2 itself does not depend on libevent.</p>
<p>First we do some setup routine for libevent and OpenSSL library in
function <tt class="docutils literal"><span class="pre">main()</span></tt> and <tt class="docutils literal"><span class="pre">run()</span></tt>, which is not so relevant to nghttp2
library use. The one thing you should look at is setup NPN callback.
The NPN callback is used for the server to advertise the application
protocols the server supports to a client. In this example program,
when creating SSL_CTX object, we stores the application protocol name
in the wire format of NPN in statically allocated buffer. This is safe
because we only create 1 SSL_CTX object in the entire program life
time:</p>
when creating <tt class="docutils literal"><span class="pre">SSL_CTX</span></tt> object, we stores the application protocol
name in the wire format of NPN in statically allocated buffer. This is
safe because we only create 1 <tt class="docutils literal"><span class="pre">SSL_CTX</span></tt> object in the entire program
life time:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">next_proto_list</span><span class="p">[</span><span class="mi">256</span><span class="p">];</span>
<span class="k">static</span> <span class="kt">size_t</span> <span class="n">next_proto_list_len</span><span class="p">;</span>
@ -186,14 +186,14 @@ time:</p>
<span class="p">}</span>
</pre></div>
</div>
<p>The wire format of NPN is array of length prefixed string. The exactly
one byte is used to specify the length of the protocol identifier. In
this tutorial, we advertise the HTTP/2.0 protocol the nghttp2 library
supports. We export its identifier in
<a class="reference internal" href="apiref.html#NGHTTP2_PROTO_VERSION_ID" title="NGHTTP2_PROTO_VERSION_ID"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_PROTO_VERSION_ID</span></tt></a>. The <tt class="docutils literal"><span class="pre">next_proto_cb()</span></tt> function is
the server-side NPN callback. In OpenSSL implementation, We just
<p>The wire format of NPN is a sequence of length prefixed string. The
exactly one byte is used to specify the length of each protocol
identifier. In this tutorial, we advertise the HTTP/2.0 protocol the
nghttp2 library supports. The nghttp2 library exports its identifier
in <a class="reference internal" href="apiref.html#NGHTTP2_PROTO_VERSION_ID" title="NGHTTP2_PROTO_VERSION_ID"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_PROTO_VERSION_ID</span></tt></a>. The <tt class="docutils literal"><span class="pre">next_proto_cb()</span></tt> function
is the server-side NPN callback. In OpenSSL implementation, we just
assign the pointer to the NPN buffers we filled earlier. The NPN
callback function is set to SSL_CTX object using
callback function is set to <tt class="docutils literal"><span class="pre">SSL_CTX</span></tt> object using
<tt class="docutils literal"><span class="pre">SSL_CTX_set_next_protos_advertised_cb()</span></tt>.</p>
<p>We use <tt class="docutils literal"><span class="pre">app_content</span></tt> structure to store the application-wide data:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">struct</span> <span class="n">app_context</span> <span class="p">{</span>
@ -230,7 +230,8 @@ object in O(1). The first element of this list is pointed by the
<tt class="docutils literal"><span class="pre">root-&gt;next</span></tt> in <tt class="docutils literal"><span class="pre">http2_session_data</span></tt>. Initially, <tt class="docutils literal"><span class="pre">root-&gt;next</span></tt>
is <tt class="docutils literal"><span class="pre">NULL</span></tt>. The <tt class="docutils literal"><span class="pre">handshake_leftlen</span></tt> member of
<tt class="docutils literal"><span class="pre">http2_session_data</span></tt> is used to track the number of bytes remaining
when receiving first 24 bytes magic values from the client. We use
when receiving first 24 bytes magic value
(<a class="reference internal" href="apiref.html#NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>) from the client. We use
libevent&#8217;s bufferevent structure to perform network I/O. Notice that
bufferevent object is in <tt class="docutils literal"><span class="pre">http2_session_data</span></tt> and not in
<tt class="docutils literal"><span class="pre">http2_stream_data</span></tt>. This is because <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> is just a
@ -289,8 +290,8 @@ is accepted:</p>
connection is also initialized at this time. We specify 2 callbacks
for the bufferevent: <tt class="docutils literal"><span class="pre">handshake_readcb</span></tt> and <tt class="docutils literal"><span class="pre">eventcb</span></tt>.</p>
<p>The <tt class="docutils literal"><span class="pre">eventcb()</span></tt> is invoked by libevent event loop when an event
(e.g., connection established, timeout, etc) happens on the underlying
network socket:</p>
(e.g., connection has been established, timeout, etc) happens on the
underlying network socket:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">eventcb</span><span class="p">(</span><span class="k">struct</span> <span class="n">bufferevent</span> <span class="o">*</span><span class="n">bev</span><span class="p">,</span> <span class="kt">short</span> <span class="n">events</span><span class="p">,</span> <span class="kt">void</span> <span class="o">*</span><span class="n">ptr</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">ptr</span><span class="p">;</span>
@ -350,13 +351,13 @@ it:</p>
<span class="p">}</span>
</pre></div>
</div>
<p>Nothing special here, we just compare the magic byte string received
and expected one <a class="reference internal" href="apiref.html#NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>. When
whole magic byte string is received, the connection state is ready for
starting HTTP/2.0 communication. First we change the callback
functions for the bufferevent object. We use same <tt class="docutils literal"><span class="pre">eventcb</span></tt> as
before. But we specify new <tt class="docutils literal"><span class="pre">readcb</span></tt> and <tt class="docutils literal"><span class="pre">writecb</span></tt> function to
handle HTTP/2.0 communication. We describe these 2 functions later.</p>
<p>We check that the received byte string matches
<a class="reference internal" href="apiref.html#NGHTTP2_CLIENT_CONNECTION_HEADER" title="NGHTTP2_CLIENT_CONNECTION_HEADER"><tt class="xref c c-macro docutils literal"><span class="pre">NGHTTP2_CLIENT_CONNECTION_HEADER</span></tt></a>. When they match, the
connection state is ready for starting HTTP/2.0 communication. First
we change the callback functions for the bufferevent object. We use
same <tt class="docutils literal"><span class="pre">eventcb</span></tt> as before. But we specify new <tt class="docutils literal"><span class="pre">readcb</span></tt> and
<tt class="docutils literal"><span class="pre">writecb</span></tt> function to handle HTTP/2.0 communication. We describe
these 2 functions later.</p>
<p>We initialize nghttp2 session object which is done in
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt>:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">void</span> <span class="nf">initialize_nghttp2_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>
@ -427,9 +428,9 @@ functions for these pending data. To process received data, we call
<p>In this function, we feed all unprocessed, received data to nghttp2
session object using <a class="reference internal" href="apiref.html#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. The
<a class="reference internal" href="apiref.html#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> processes the received data and may
invoke nghttp2 callbacks and also queue frames. Since there may be
pending frames, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> function to send those
frames. The <tt class="docutils literal"><span class="pre">session_send()</span></tt> function is defined as follows:</p>
invoke nghttp2 callbacks and also queue outgoing frames. Since there
may be pending frames, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> function to send
those frames. The <tt class="docutils literal"><span class="pre">session_send()</span></tt> function is defined as follows:</p>
<div class="highlight-c"><div class="highlight"><pre><span class="k">static</span> <span class="kt">int</span> <span class="nf">session_send</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="p">{</span>
<span class="kt">int</span> <span class="n">rv</span><span class="p">;</span>
@ -443,8 +444,8 @@ frames. The <tt class="docutils literal"><span class="pre">session_send()</span>
</pre></div>
</div>
<p>The <a class="reference internal" href="apiref.html#nghttp2_session_send" title="nghttp2_session_send"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_send()</span></tt></a> function serializes the frame into wire
format and call <tt class="xref c c-member docutils literal"><span class="pre">nghttp2_callbacks.nghttp2_send_callback</span></tt> with
it. We set <tt class="docutils literal"><span class="pre">send_callback()</span></tt> function as
format and call <a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> with
it. We set <tt class="docutils literal"><span class="pre">send_callback()</span></tt> function to
<a class="reference internal" href="apiref.html#nghttp2_session_callbacks.send_callback" title="nghttp2_session_callbacks.send_callback"><tt class="xref c c-member docutils literal"><span class="pre">nghttp2_session_callbacks.send_callback</span></tt></a> in
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt> function described earlier. It is
defined as follows:</p>
@ -519,7 +520,7 @@ frame and other error conditions as well. Using these information,
nghttp2 session object will tell whether the connection should be
dropped or not. More specifically, both <a class="reference internal" href="apiref.html#nghttp2_session_want_read" title="nghttp2_session_want_read"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_read()</span></tt></a>
and <a class="reference internal" href="apiref.html#nghttp2_session_want_write" title="nghttp2_session_want_write"><tt class="xref c c-func docutils literal"><span class="pre">nghttp2_session_want_write()</span></tt></a> return 0, we have no business in
the connection. But since we have using bufferevent and its deferred
the connection. But since we are using bufferevent and its deferred
callback option, the bufferevent output buffer may contain the pending
data when the <tt class="docutils literal"><span class="pre">writecb()</span></tt> is called. To handle this situation, we
also check whether the output buffer is empty or not. If these
@ -527,7 +528,7 @@ conditions are met, we drop connection.</p>
<p>Otherwise, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> to process pending output
data. Remember that in <tt class="docutils literal"><span class="pre">send_callback()</span></tt>, we may not write all data
to bufferevent to avoid excessive buffering. We continue process
pending data if output buffer becomes empty.</p>
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>
@ -566,16 +567,16 @@ received from the remote peer:</p>
<span class="p">}</span>
</pre></div>
</div>
<p>We only interested HEADERS frame in this function. Since HEADERS frame
has several roles in HTTP/2.0 protocol, we check that it is a request
HEADERS, which opens new stream. If frame is request HEADERS, then we
create <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object to store stream related data. We
associate created <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object to the stream 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 server static file 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
<p>We only interested in HEADERS frame in this function. Since HEADERS
frame has several roles in HTTP/2.0 protocol, we check that it is a
request HEADERS, which opens new stream. If frame is request HEADERS,
then we create <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object to store stream related
data. We associate created <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object to the stream
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
@ -701,7 +702,7 @@ is about to close:</p>
</pre></div>
</div>
<p>We destroy <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object in this function since the
stream is about to close and we no longer to use that object.</p>
stream is about to close and we no longer use that object.</p>
<div class="section" id="libevent-server-c">
<h2>libevent-server.c<a class="headerlink" href="#libevent-server-c" title="Permalink to this headline"></a></h2>
<div class="highlight-c"><div class="highlight"><pre><span class="cm">/*</span>