Update doc
This commit is contained in:
parent
72ba3397bb
commit
d813ae89f6
|
@ -12,7 +12,7 @@ resource denoted by the URI. Its synopsis is like this::
|
||||||
$ libevent-client HTTPS_URI
|
$ libevent-client HTTPS_URI
|
||||||
|
|
||||||
We use libevent in this tutorial to handle networking I/O. Please
|
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
|
First we do some setup routine for libevent and OpenSSL library in
|
||||||
function ``main()`` and ``run()``, which is not so relevant to nghttp2
|
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``.
|
``eventcb``.
|
||||||
|
|
||||||
The ``eventcb()`` is invoked by libevent event loop when an event
|
The ``eventcb()`` is invoked by libevent event loop when an event
|
||||||
(e.g., connection established, timeout, etc) happens on the underlying
|
(e.g., connection has been established, timeout, etc) happens on the
|
||||||
network socket::
|
underlying network socket::
|
||||||
|
|
||||||
static void eventcb(struct bufferevent *bev, short events, void *ptr)
|
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
|
The `nghttp2_session_send()` function serializes the frame into wire
|
||||||
format and call :member:`nghttp2_callbacks.nghttp2_send_callback` with
|
format and call :member:`nghttp2_session_callbacks.send_callback` with
|
||||||
it. We set ``send_callback()`` function as
|
it. We set ``send_callback()`` function to
|
||||||
:member:`nghttp2_session_callbacks.send_callback` in
|
:member:`nghttp2_session_callbacks.send_callback` in
|
||||||
``initialize_nghttp2_session()`` function described earlier. It is
|
``initialize_nghttp2_session()`` function described earlier. It is
|
||||||
defined as follows::
|
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
|
will tell whether the connection should be dropped or not. More
|
||||||
specifically, both `nghttp2_session_want_read()` and
|
specifically, both `nghttp2_session_want_read()` and
|
||||||
`nghttp2_session_want_write()` return 0, we have no business in the
|
`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
|
callback option, the bufferevent output buffer may contain the pending
|
||||||
data when the ``writecb()`` is called. To handle this situation, we
|
data when the ``writecb()`` is called. To handle this situation, we
|
||||||
also check whether the output buffer is empty or not. If these
|
also check whether the output buffer is empty or not. If these
|
||||||
|
|
|
@ -2,10 +2,10 @@ Tutorial: HTTP/2.0 server
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
In this tutorial, we are going to write single-threaded, event-based
|
In this tutorial, we are going to write single-threaded, event-based
|
||||||
HTTP/2.0 web server, which supports HTTPS. It can handle concurrent
|
HTTP/2.0 web server, which supports HTTPS only. It can handle
|
||||||
multiple requests, but only GET method is supported. The complete
|
concurrent multiple requests, but only GET method is supported. The
|
||||||
source code, `libevent-server.c`_, is attached at the end of this
|
complete source code, `libevent-server.c`_, is attached at the end of
|
||||||
page. It also resides in examples directory in the archive or
|
this page. It also resides in examples directory in the archive or
|
||||||
repository.
|
repository.
|
||||||
|
|
||||||
This simple server takes 3 arguments, a port number to listen to, a
|
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
|
$ libevent-server PORT /path/to/server.key /path/to/server.crt
|
||||||
|
|
||||||
We use libevent in this tutorial to handle networking I/O. Please
|
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
|
First we do some setup routine for libevent and OpenSSL library in
|
||||||
function ``main()`` and ``run()``, which is not so relevant to nghttp2
|
function ``main()`` and ``run()``, which is not so relevant to nghttp2
|
||||||
library use. The one thing you should look at is setup NPN callback.
|
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
|
The NPN callback is used for the server to advertise the application
|
||||||
protocols the server supports to a client. In this example program,
|
protocols the server supports to a client. In this example program,
|
||||||
when creating SSL_CTX object, we stores the application protocol name
|
when creating ``SSL_CTX`` object, we stores the application protocol
|
||||||
in the wire format of NPN in statically allocated buffer. This is safe
|
name in the wire format of NPN in statically allocated buffer. This is
|
||||||
because we only create 1 SSL_CTX object in the entire program life
|
safe because we only create 1 ``SSL_CTX`` object in the entire program
|
||||||
time::
|
life time::
|
||||||
|
|
||||||
static unsigned char next_proto_list[256];
|
static unsigned char next_proto_list[256];
|
||||||
static size_t next_proto_list_len;
|
static size_t next_proto_list_len;
|
||||||
|
@ -55,14 +55,14 @@ time::
|
||||||
return ssl_ctx;
|
return ssl_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
The wire format of NPN is array of length prefixed string. The exactly
|
The wire format of NPN is a sequence of length prefixed string. The
|
||||||
one byte is used to specify the length of the protocol identifier. In
|
exactly one byte is used to specify the length of each protocol
|
||||||
this tutorial, we advertise the HTTP/2.0 protocol the nghttp2 library
|
identifier. In this tutorial, we advertise the HTTP/2.0 protocol the
|
||||||
supports. We export its identifier in
|
nghttp2 library supports. The nghttp2 library exports its identifier
|
||||||
:macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function is
|
in :macro:`NGHTTP2_PROTO_VERSION_ID`. The ``next_proto_cb()`` function
|
||||||
the server-side NPN callback. In OpenSSL implementation, We just
|
is the server-side NPN callback. In OpenSSL implementation, we just
|
||||||
assign the pointer to the NPN buffers we filled earlier. The NPN
|
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()``.
|
``SSL_CTX_set_next_protos_advertised_cb()``.
|
||||||
|
|
||||||
We use ``app_content`` structure to store the application-wide data::
|
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``
|
``root->next`` in ``http2_session_data``. Initially, ``root->next``
|
||||||
is ``NULL``. The ``handshake_leftlen`` member of
|
is ``NULL``. The ``handshake_leftlen`` member of
|
||||||
``http2_session_data`` is used to track the number of bytes remaining
|
``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
|
libevent's bufferevent structure to perform network I/O. Notice that
|
||||||
bufferevent object is in ``http2_session_data`` and not in
|
bufferevent object is in ``http2_session_data`` and not in
|
||||||
``http2_stream_data``. This is because ``http2_stream_data`` is just a
|
``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``.
|
for the bufferevent: ``handshake_readcb`` and ``eventcb``.
|
||||||
|
|
||||||
The ``eventcb()`` is invoked by libevent event loop when an event
|
The ``eventcb()`` is invoked by libevent event loop when an event
|
||||||
(e.g., connection established, timeout, etc) happens on the underlying
|
(e.g., connection has been established, timeout, etc) happens on the
|
||||||
network socket::
|
underlying network socket::
|
||||||
|
|
||||||
static void eventcb(struct bufferevent *bev, short events, void *ptr)
|
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
|
We check that the received byte string matches
|
||||||
and expected one :macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`. When
|
:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`. When they match, the
|
||||||
whole magic byte string is received, the connection state is ready for
|
connection state is ready for starting HTTP/2.0 communication. First
|
||||||
starting HTTP/2.0 communication. First we change the callback
|
we change the callback functions for the bufferevent object. We use
|
||||||
functions for the bufferevent object. We use same ``eventcb`` as
|
same ``eventcb`` as before. But we specify new ``readcb`` and
|
||||||
before. But we specify new ``readcb`` and ``writecb`` function to
|
``writecb`` function to handle HTTP/2.0 communication. We describe
|
||||||
handle HTTP/2.0 communication. We describe these 2 functions later.
|
these 2 functions later.
|
||||||
|
|
||||||
We initialize nghttp2 session object which is done in
|
We initialize nghttp2 session object which is done in
|
||||||
``initialize_nghttp2_session()``::
|
``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
|
In this function, we feed all unprocessed, received data to nghttp2
|
||||||
session object using `nghttp2_session_mem_recv()` function. The
|
session object using `nghttp2_session_mem_recv()` function. The
|
||||||
`nghttp2_session_mem_recv()` processes the received data and may
|
`nghttp2_session_mem_recv()` processes the received data and may
|
||||||
invoke nghttp2 callbacks and also queue frames. Since there may be
|
invoke nghttp2 callbacks and also queue outgoing frames. Since there
|
||||||
pending frames, we call ``session_send()`` function to send those
|
may be pending frames, we call ``session_send()`` function to send
|
||||||
frames. The ``session_send()`` function is defined as follows::
|
those frames. The ``session_send()`` function is defined as follows::
|
||||||
|
|
||||||
static int session_send(http2_session_data *session_data)
|
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
|
The `nghttp2_session_send()` function serializes the frame into wire
|
||||||
format and call :member:`nghttp2_callbacks.nghttp2_send_callback` with
|
format and call :member:`nghttp2_session_callbacks.send_callback` with
|
||||||
it. We set ``send_callback()`` function as
|
it. We set ``send_callback()`` function to
|
||||||
:member:`nghttp2_session_callbacks.send_callback` in
|
:member:`nghttp2_session_callbacks.send_callback` in
|
||||||
``initialize_nghttp2_session()`` function described earlier. It is
|
``initialize_nghttp2_session()`` function described earlier. It is
|
||||||
defined as follows::
|
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
|
nghttp2 session object will tell whether the connection should be
|
||||||
dropped or not. More specifically, both `nghttp2_session_want_read()`
|
dropped or not. More specifically, both `nghttp2_session_want_read()`
|
||||||
and `nghttp2_session_want_write()` return 0, we have no business in
|
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
|
callback option, the bufferevent output buffer may contain the pending
|
||||||
data when the ``writecb()`` is called. To handle this situation, we
|
data when the ``writecb()`` is called. To handle this situation, we
|
||||||
also check whether the output buffer is empty or not. If these
|
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
|
Otherwise, we call ``session_send()`` to process pending output
|
||||||
data. Remember that in ``send_callback()``, we may not write all data
|
data. Remember that in ``send_callback()``, we may not write all data
|
||||||
to bufferevent to avoid excessive buffering. We continue process
|
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()``.
|
We have already described about nghttp2 callback ``send_callback()``.
|
||||||
Let's describe remaining nghttp2 callbacks we setup in
|
Let's describe remaining nghttp2 callbacks we setup in
|
||||||
|
@ -447,17 +448,17 @@ received from the remote peer::
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
We only interested HEADERS frame in this function. Since HEADERS frame
|
We only interested in HEADERS frame in this function. Since HEADERS
|
||||||
has several roles in HTTP/2.0 protocol, we check that it is a request
|
frame has several roles in HTTP/2.0 protocol, we check that it is a
|
||||||
HEADERS, which opens new stream. If frame is request HEADERS, then we
|
request HEADERS, which opens new stream. If frame is request HEADERS,
|
||||||
create ``http2_stream_data`` object to store stream related data. We
|
then we create ``http2_stream_data`` object to store stream related
|
||||||
associate created ``http2_stream_data`` object to the stream in
|
data. We associate created ``http2_stream_data`` object to the stream
|
||||||
nghttp2 session object using `nghttp2_set_stream_user_data()` in order
|
in nghttp2 session object using `nghttp2_set_stream_user_data()` in
|
||||||
to get the object without searching through doubly linked list.
|
order to get the object without searching through doubly linked list.
|
||||||
|
|
||||||
In this example server, we want to server static file relative to the
|
In this example server, we want to serve files relative to the current
|
||||||
current working directory the program was invoked. We search ``:path``
|
working directory the program was invoked. We search ``:path`` header
|
||||||
header field in request headers and keep the requested path in
|
field in request headers and keep the requested path in
|
||||||
``http2_stream_data`` object. In this example program, we ignore
|
``http2_stream_data`` object. In this example program, we ignore
|
||||||
``:method`` header field and always treat the request as GET request.
|
``: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
|
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
|
libevent-server.c
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
* Copyright 2011, The Dojo Foundation
|
* Copyright 2011, The Dojo Foundation
|
||||||
* Released under the MIT, BSD, and GPL Licenses.
|
* 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 ) {
|
(function( window, undefined ) {
|
||||||
|
|
||||||
|
|
|
@ -239,8 +239,13 @@ var Search = {
|
||||||
},
|
},
|
||||||
|
|
||||||
loadIndex : function(url) {
|
loadIndex : function(url) {
|
||||||
$.ajax({type: "GET", url: url, data: null, success: null,
|
$.ajax({type: "GET", url: url, data: null,
|
||||||
dataType: "script", cache: true});
|
dataType: "script", cache: true,
|
||||||
|
complete: function(jqxhr, textstatus) {
|
||||||
|
if (textstatus != "success") {
|
||||||
|
document.getElementById("searchindexloader").src = url;
|
||||||
|
}
|
||||||
|
}});
|
||||||
},
|
},
|
||||||
|
|
||||||
setIndex : function(index) {
|
setIndex : function(index) {
|
||||||
|
@ -457,16 +462,18 @@ var Search = {
|
||||||
displayNextItem();
|
displayNextItem();
|
||||||
});
|
});
|
||||||
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
} else if (DOCUMENTATION_OPTIONS.HAS_SOURCE) {
|
||||||
$.get(DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' +
|
$.ajax({url: DOCUMENTATION_OPTIONS.URL_ROOT + '_sources/' + item[0] + '.txt',
|
||||||
item[0] + '.txt', function(data) {
|
dataType: "text",
|
||||||
if (data != '') {
|
complete: function(jqxhr, textstatus) {
|
||||||
listItem.append($.makeSearchSummary(data, searchterms, hlterms));
|
var data = jqxhr.responseText;
|
||||||
Search.output.append(listItem);
|
if (data !== '') {
|
||||||
}
|
listItem.append($.makeSearchSummary(data, searchterms, hlterms));
|
||||||
listItem.slideDown(5, function() {
|
}
|
||||||
displayNextItem();
|
Search.output.append(listItem);
|
||||||
});
|
listItem.slideDown(5, function() {
|
||||||
}, "text");
|
displayNextItem();
|
||||||
|
});
|
||||||
|
}});
|
||||||
} else {
|
} else {
|
||||||
// no source available, just display title
|
// no source available, just display title
|
||||||
Search.output.append(listItem);
|
Search.output.append(listItem);
|
||||||
|
|
BIN
objects.inv
BIN
objects.inv
Binary file not shown.
File diff suppressed because one or more lines are too long
|
@ -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 class="highlight-c"><pre>$ libevent-client HTTPS_URI</pre>
|
||||||
</div>
|
</div>
|
||||||
<p>We use libevent in this tutorial to handle networking I/O. Please
|
<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
|
<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
|
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.
|
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
|
<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>
|
<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
|
<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
|
(e.g., connection has been established, timeout, etc) happens on the
|
||||||
network socket:</p>
|
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>
|
<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="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>
|
<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>
|
</pre></div>
|
||||||
</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
|
<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
|
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 as
|
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
|
<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
|
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt> function described earlier. It is
|
||||||
defined as follows:</p>
|
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
|
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
|
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
|
<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
|
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
|
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
|
also check whether the output buffer is empty or not. If these
|
||||||
|
|
|
@ -136,10 +136,10 @@
|
||||||
<div class="section" id="tutorial-http-2-0-server">
|
<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>
|
<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
|
<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
|
HTTP/2.0 web server, which supports HTTPS only. It can handle
|
||||||
multiple requests, but only GET method is supported. The complete
|
concurrent multiple requests, but only GET method is supported. The
|
||||||
source code, <a class="reference internal" href="#libevent-server-c">libevent-server.c</a>, is attached at the end of this
|
complete source code, <a class="reference internal" href="#libevent-server-c">libevent-server.c</a>, is attached at the end of
|
||||||
page. It also resides in examples directory in the archive or
|
this page. It also resides in examples directory in the archive or
|
||||||
repository.</p>
|
repository.</p>
|
||||||
<p>This simple server takes 3 arguments, a port number to listen to, a
|
<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
|
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 class="highlight-c"><pre>$ libevent-server PORT /path/to/server.key /path/to/server.crt</pre>
|
||||||
</div>
|
</div>
|
||||||
<p>We use libevent in this tutorial to handle networking I/O. Please
|
<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
|
<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
|
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.
|
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
|
The NPN callback is used for the server to advertise the application
|
||||||
protocols the server supports to a client. In this example program,
|
protocols the server supports to a client. In this example program,
|
||||||
when creating SSL_CTX object, we stores the application protocol name
|
when creating <tt class="docutils literal"><span class="pre">SSL_CTX</span></tt> object, we stores the application protocol
|
||||||
in the wire format of NPN in statically allocated buffer. This is safe
|
name in the wire format of NPN in statically allocated buffer. This is
|
||||||
because we only create 1 SSL_CTX object in the entire program life
|
safe because we only create 1 <tt class="docutils literal"><span class="pre">SSL_CTX</span></tt> object in the entire program
|
||||||
time:</p>
|
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>
|
<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>
|
<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>
|
<span class="p">}</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>The wire format of NPN is array of length prefixed string. The exactly
|
<p>The wire format of NPN is a sequence of length prefixed string. The
|
||||||
one byte is used to specify the length of the protocol identifier. In
|
exactly one byte is used to specify the length of each protocol
|
||||||
this tutorial, we advertise the HTTP/2.0 protocol the nghttp2 library
|
identifier. In this tutorial, we advertise the HTTP/2.0 protocol the
|
||||||
supports. We export its identifier in
|
nghttp2 library supports. The nghttp2 library exports its identifier
|
||||||
<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
|
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
|
||||||
the server-side NPN callback. In OpenSSL implementation, We just
|
is the server-side NPN callback. In OpenSSL implementation, we just
|
||||||
assign the pointer to the NPN buffers we filled earlier. The NPN
|
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>
|
<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>
|
<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>
|
<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->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->next</span></tt>
|
<tt class="docutils literal"><span class="pre">root->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->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
|
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
|
<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’s bufferevent structure to perform network I/O. Notice that
|
libevent’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
|
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
|
<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
|
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>
|
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
|
<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
|
(e.g., connection has been established, timeout, etc) happens on the
|
||||||
network socket:</p>
|
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>
|
<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="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>
|
<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>
|
<span class="p">}</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>Nothing special here, we just compare the magic byte string received
|
<p>We check that the received byte string matches
|
||||||
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
|
<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
|
||||||
whole magic byte string is received, the connection state is ready for
|
connection state is ready for starting HTTP/2.0 communication. First
|
||||||
starting HTTP/2.0 communication. First we change the callback
|
we change the callback functions for the bufferevent object. We use
|
||||||
functions for the bufferevent object. We use same <tt class="docutils literal"><span class="pre">eventcb</span></tt> as
|
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
|
||||||
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
|
<tt class="docutils literal"><span class="pre">writecb</span></tt> function to handle HTTP/2.0 communication. We describe
|
||||||
handle HTTP/2.0 communication. We describe these 2 functions later.</p>
|
these 2 functions later.</p>
|
||||||
<p>We initialize nghttp2 session object which is done in
|
<p>We initialize nghttp2 session object which is done in
|
||||||
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt>:</p>
|
<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>
|
<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
|
<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
|
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
|
<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
|
invoke nghttp2 callbacks and also queue outgoing frames. Since there
|
||||||
pending frames, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> function to send those
|
may be pending frames, we call <tt class="docutils literal"><span class="pre">session_send()</span></tt> function to send
|
||||||
frames. The <tt class="docutils literal"><span class="pre">session_send()</span></tt> function is defined as follows:</p>
|
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>
|
<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="p">{</span>
|
||||||
<span class="kt">int</span> <span class="n">rv</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>
|
</pre></div>
|
||||||
</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
|
<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
|
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 as
|
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
|
<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
|
<tt class="docutils literal"><span class="pre">initialize_nghttp2_session()</span></tt> function described earlier. It is
|
||||||
defined as follows:</p>
|
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
|
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>
|
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
|
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
|
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
|
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
|
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
|
<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
|
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
|
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>.
|
<p>We have already described about nghttp2 callback <tt class="docutils literal"><span class="pre">send_callback()</span></tt>.
|
||||||
Let’s describe remaining nghttp2 callbacks we setup in
|
Let’s describe remaining nghttp2 callbacks we setup in
|
||||||
<tt class="docutils literal"><span class="pre">initialize_nghttp2_setup()</span></tt> function.</p>
|
<tt class="docutils literal"><span class="pre">initialize_nghttp2_setup()</span></tt> function.</p>
|
||||||
|
@ -566,16 +567,16 @@ received from the remote peer:</p>
|
||||||
<span class="p">}</span>
|
<span class="p">}</span>
|
||||||
</pre></div>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>We only interested HEADERS frame in this function. Since HEADERS frame
|
<p>We only interested in HEADERS frame in this function. Since HEADERS
|
||||||
has several roles in HTTP/2.0 protocol, we check that it is a request
|
frame has several roles in HTTP/2.0 protocol, we check that it is a
|
||||||
HEADERS, which opens new stream. If frame is request HEADERS, then we
|
request HEADERS, which opens new stream. If frame is request HEADERS,
|
||||||
create <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object to store stream related data. We
|
then we create <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object to store stream related
|
||||||
associate created <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object to the stream in
|
data. We associate created <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object to the stream
|
||||||
nghttp2 session object using <tt class="xref c c-func docutils literal"><span class="pre">nghttp2_set_stream_user_data()</span></tt> in order
|
in nghttp2 session object using <tt class="xref c c-func docutils literal"><span class="pre">nghttp2_set_stream_user_data()</span></tt> in
|
||||||
to get the object without searching through doubly linked list.</p>
|
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
|
<p>In this example server, we want to serve files relative to the current
|
||||||
current working directory the program was invoked. We search <tt class="docutils literal"><span class="pre">:path</span></tt>
|
working directory the program was invoked. We search <tt class="docutils literal"><span class="pre">:path</span></tt> header
|
||||||
header field in request headers and keep the requested path in
|
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">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>
|
<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
|
<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>
|
</pre></div>
|
||||||
</div>
|
</div>
|
||||||
<p>We destroy <tt class="docutils literal"><span class="pre">http2_stream_data</span></tt> object in this function since the
|
<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">
|
<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>
|
<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>
|
<div class="highlight-c"><div class="highlight"><pre><span class="cm">/*</span>
|
||||||
|
|
Loading…
Reference in New Issue