Update tutorial

This commit is contained in:
Tatsuhiro Tsujikawa 2014-03-30 21:08:04 +09:00
parent 60a2c260a5
commit 334658044e
2 changed files with 21 additions and 20 deletions

View File

@ -176,10 +176,10 @@ The `delete_http2_session_data()` destroys ``session_data`` and frees
its bufferevent, so it closes underlying connection as well. It also its bufferevent, so it closes underlying connection as well. It also
calls `nghttp2_session_del()` to delete nghttp2 session object. calls `nghttp2_session_del()` to delete nghttp2 session object.
We begin HTTP/2 communication by sending client connection header, We begin HTTP/2 communication by sending client connection preface,
which is 24 bytes magic byte sequence which is 24 bytes magic byte sequence
(:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`) followed by SETTINGS (:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`) and SETTINGS frame. The
frame. The transmission of client connection header is done in transmission of client connection header is done in
``send_client_connection_header()``:: ``send_client_connection_header()``::
static void send_client_connection_header(http2_session_data *session_data) static void send_client_connection_header(http2_session_data *session_data)
@ -190,8 +190,8 @@ frame. The transmission of client connection header is done in
int rv; int rv;
bufferevent_write(session_data->bev, bufferevent_write(session_data->bev,
NGHTTP2_CLIENT_CONNECTION_HEADER, NGHTTP2_CLIENT_CONNECTION_PREFACE,
NGHTTP2_CLIENT_CONNECTION_HEADER_LEN); NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN);
rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE, rv = nghttp2_submit_settings(session_data->session, NGHTTP2_FLAG_NONE,
iv, ARRLEN(iv)); iv, ARRLEN(iv));
if(rv != 0) { if(rv != 0) {
@ -226,7 +226,7 @@ request in ``submit_request()`` function::
}; };
fprintf(stderr, "Request headers:\n"); fprintf(stderr, "Request headers:\n");
print_headers(stderr, hdrs, ARRLEN(hdrs)); print_headers(stderr, hdrs, ARRLEN(hdrs));
rv = nghttp2_submit_request(session_data->session, NGHTTP2_PRI_DEFAULT, rv = nghttp2_submit_request(session_data->session, NULL,
hdrs, ARRLEN(hdrs), NULL, stream_data); hdrs, ARRLEN(hdrs), NULL, stream_data);
if(rv != 0) { if(rv != 0) {
errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(rv)); errx(1, "Could not submit HTTP request: %s", nghttp2_strerror(rv));

View File

@ -94,19 +94,20 @@ data::
int fd; int fd;
} http2_stream_data; } http2_stream_data;
1 HTTP/2 session can have multiple streams. We manage these 1 HTTP/2 session can have multiple streams. We manage these multiple
multiple streams by intrusive doubly linked list to add and remove the streams by intrusive doubly linked list to add and remove the object
object in O(1). The first element of this list is pointed by the 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 value when receiving first client connection preface
(:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`) from the client. We use (:macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`), which is 24 bytes magic
libevent's bufferevent structure to perform network I/O. Notice that byte string, from the client. We use libevent's bufferevent structure
bufferevent object is in ``http2_session_data`` and not in to perform network I/O. Notice that bufferevent object is in
``http2_stream_data``. This is because ``http2_stream_data`` is just a ``http2_session_data`` and not in ``http2_stream_data``. This is
logical stream multiplexed over the single connection managed by because ``http2_stream_data`` is just a logical stream multiplexed
bufferevent in ``http2_session_data``. over the single connection managed by bufferevent in
``http2_session_data``.
We first create listener object to accept incoming connections. We first create listener object to accept incoming connections.
We use libevent's ``struct evconnlistener`` for this purpose:: We use libevent's ``struct evconnlistener`` for this purpose::
@ -200,9 +201,9 @@ it::
uint8_t data[24]; uint8_t data[24];
struct evbuffer *input = bufferevent_get_input(session_data->bev); struct evbuffer *input = bufferevent_get_input(session_data->bev);
int readlen = evbuffer_remove(input, data, session_data->handshake_leftlen); int readlen = evbuffer_remove(input, data, session_data->handshake_leftlen);
const char *conhead = NGHTTP2_CLIENT_CONNECTION_HEADER; const char *conhead = NGHTTP2_CLIENT_CONNECTION_PREFACE;
if(memcmp(conhead + NGHTTP2_CLIENT_CONNECTION_HEADER_LEN if(memcmp(conhead + NGHTTP2_CLIENT_CONNECTION_PREFACE_LEN
- session_data->handshake_leftlen, data, readlen) != 0) { - session_data->handshake_leftlen, data, readlen) != 0) {
delete_http2_session_data(session_data); delete_http2_session_data(session_data);
return; return;
@ -225,7 +226,7 @@ it::
} }
We check that the received byte string matches We check that the received byte string matches
:macro:`NGHTTP2_CLIENT_CONNECTION_HEADER`. When they match, the :macro:`NGHTTP2_CLIENT_CONNECTION_PREFACE`. When they match, the
connection state is ready for starting HTTP/2 communication. First connection state is ready for starting HTTP/2 communication. First
we change the callback functions for the bufferevent object. We use we change the callback functions for the bufferevent object. We use
same ``eventcb`` as before. But we specify new ``readcb`` and same ``eventcb`` as before. But we specify new ``readcb`` and