Remove deprecated libnghttp2_asio

This commit is contained in:
Tatsuhiro Tsujikawa 2022-12-24 16:49:02 +09:00
parent 00a33281be
commit e6d608b522
78 changed files with 19 additions and 7926 deletions

View File

@ -243,10 +243,6 @@ endif()
# jemalloc
set(HAVE_JEMALLOC ${JEMALLOC_FOUND})
if(ENABLE_ASIO_LIB)
find_package(Boost 1.54.0 REQUIRED system thread)
endif()
# libbpf (for bpf)
set(HAVE_LIBBPF ${LIBBPF_FOUND})
if(LIBBPF_FOUND)
@ -277,13 +273,13 @@ if(ENABLE_HPACK_TOOLS AND NOT HAVE_JANSSON)
message(FATAL_ERROR "HPACK tools were requested (ENABLE_HPACK_TOOLS=1) but dependencies are not met.")
endif()
# C++ library libnghttp2_asio
# examples
if(ENABLE_EXAMPLES AND NOT (OPENSSL_FOUND AND LIBEVENT_OPENSSL_FOUND))
message(FATAL_ERROR "examples were requested (ENABLE_EXAMPLES=1) but dependencies are not met.")
endif()
# third-party http-parser only be built when needed
if(ENABLE_EXAMPLES OR ENABLE_APP OR ENABLE_HPACK_TOOLS OR ENABLE_ASIO_LIB)
if(ENABLE_EXAMPLES OR ENABLE_APP OR ENABLE_HPACK_TOOLS)
set(ENABLE_THIRD_PARTY 1)
# mruby (for src/nghttpx)
set(HAVE_MRUBY ${WITH_MRUBY})
@ -467,7 +463,6 @@ set(sbindir "${CMAKE_INSTALL_FULL_SBINDIR}")
foreach(name
lib/libnghttp2.pc
lib/includes/nghttp2/nghttp2ver.h
src/libnghttp2_asio.pc
python/setup.py
integration-tests/config.go
integration-tests/setenv
@ -479,14 +474,10 @@ foreach(name
doc/tutorial-hpack.rst
doc/nghttpx-howto.rst
doc/h2load-howto.rst
doc/libnghttp2_asio.rst
doc/python-apiref.rst
doc/building-android-binary.rst
doc/nghttp2.h.rst
doc/nghttp2ver.h.rst
doc/asio_http2.h.rst
doc/asio_http2_server.h.rst
doc/asio_http2_client.h.rst
doc/contribute.rst
)
configure_file("${name}.in" "${name}" @ONLY)
@ -560,8 +551,6 @@ message(STATUS "summary of build options:
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
Boost::System: ${Boost_SYSTEM_LIBRARY}
Boost::Thread: ${Boost_THREAD_LIBRARY}
Third-party:
http-parser: ${ENABLE_THIRD_PARTY}
MRuby: ${HAVE_MRUBY}
@ -569,7 +558,6 @@ message(STATUS "summary of build options:
Features:
Applications: ${ENABLE_APP}
HPACK tools: ${ENABLE_HPACK_TOOLS}
Libnghttp2_asio:${ENABLE_ASIO_LIB}
Examples: ${ENABLE_EXAMPLES}
Python bindings:${ENABLE_PYTHON_BINDINGS}
Threading: ${ENABLE_THREADS}

View File

@ -7,7 +7,6 @@ option(ENABLE_APP "Build applications (nghttp, nghttpd, nghttpx and h2load
${ENABLE_APP_DEFAULT})
option(ENABLE_HPACK_TOOLS "Build HPACK tools"
${ENABLE_HPACK_TOOLS_DEFAULT})
option(ENABLE_ASIO_LIB "Build C++ libnghttp2_asio library")
option(ENABLE_EXAMPLES "Build examples"
${ENABLE_EXAMPLES_DEFAULT})
option(ENABLE_PYTHON_BINDINGS "Build Python bindings"

View File

@ -103,13 +103,6 @@ To mitigate heap fragmentation in long running server programs
Alpine Linux currently does not support malloc replacement
due to musl limitations. See details in issue `#762 <https://github.com/nghttp2/nghttp2/issues/762>`_.
libnghttp2_asio C++ library (deprecated, has moved to
https://github.com/nghttp2/nghttp2-asio) requires the following
packages:
* libboost-dev >= 1.54.0
* libboost-thread-dev >= 1.54.0
The Python bindings (deprecated) require the following packages:
* cython >= 0.19
@ -1432,106 +1425,6 @@ associated value includes the state of the dynamic header table after the
corresponding header set was processed. The format is the same as
``deflatehd``.
libnghttp2_asio: High level HTTP/2 C++ library
----------------------------------------------
libnghttp2_asio has been deprecated, and moved to
https://github.com/nghttp2/nghttp2-asio.
libnghttp2_asio is C++ library built on top of libnghttp2 and provides
high level abstraction API to build HTTP/2 applications. It depends
on the Boost::ASIO library and OpenSSL. Currently libnghttp2_asio
provides both client and server APIs.
libnghttp2_asio is not built by default. Use the ``--enable-asio-lib``
configure flag to build libnghttp2_asio. The required Boost libraries
are:
* Boost::Asio
* Boost::System
* Boost::Thread
The server API is designed to build an HTTP/2 server very easily to utilize
C++14 anonymous functions and closures. The bare minimum example of
an HTTP/2 server looks like this:
.. code-block:: cpp
#include <iostream>
#include <nghttp2/asio_http2_server.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
http2 server;
server.handle("/", [](const request &req, const response &res) {
res.write_head(200);
res.end("hello, world\n");
});
if (server.listen_and_serve(ec, "localhost", "3000")) {
std::cerr << "error: " << ec.message() << std::endl;
}
}
Here is sample code to use the client API:
.. code-block:: cpp
#include <iostream>
#include <nghttp2/asio_http2_client.h>
using boost::asio::ip::tcp;
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::client;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
boost::asio::io_service io_service;
// connect to localhost:3000
session sess(io_service, "localhost", "3000");
sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
boost::system::error_code ec;
auto req = sess.submit(ec, "GET", "http://localhost:3000/");
req->on_response([](const response &res) {
// print status code and response header fields.
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
for (auto &kv : res.header()) {
std::cerr << kv.first << ": " << kv.second.value << "\n";
}
std::cerr << std::endl;
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
req->on_close([&sess](uint32_t error_code) {
// shutdown session after first request was done.
sess.shutdown();
});
});
sess.on_error([](const boost::system::error_code &ec) {
std::cerr << "error: " << ec.message() << std::endl;
});
io_service.run();
}
For more details, see the documentation of libnghttp2_asio.
Python bindings
---------------

View File

@ -82,11 +82,6 @@ AC_ARG_ENABLE([hpack-tools],
[Build HPACK tools [default=check]])],
[request_hpack_tools=$enableval], [request_hpack_tools=check])
AC_ARG_ENABLE([asio-lib],
[AS_HELP_STRING([--enable-asio-lib],
[Build C++ libnghttp2_asio library [default=no]])],
[request_asio_lib=$enableval], [request_asio_lib=no])
AC_ARG_ENABLE([examples],
[AS_HELP_STRING([--enable-examples],
[Build examples [default=check]])],
@ -763,25 +758,6 @@ if test "x${request_jemalloc}" = "xyes" &&
AC_MSG_ERROR([jemalloc was requested (--with-jemalloc) but not found])
fi
# Check Boost Asio library
have_asio_lib=no
if test "x${request_asio_lib}" = "xyes"; then
AX_BOOST_BASE([1.54.0], [have_boost_base=yes], [have_boost_base=no])
if test "x${have_boost_base}" = "xyes"; then
AX_BOOST_ASIO()
AX_BOOST_SYSTEM()
AX_BOOST_THREAD()
if test "x${ax_cv_boost_asio}" = "xyes" &&
test "x${ax_cv_boost_system}" = "xyes" &&
test "x${ax_cv_boost_thread}" = "xyes"; then
have_asio_lib=yes
fi
fi
fi
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL,
# libev, and libc-ares.
enable_app=no
@ -834,16 +810,6 @@ fi
AM_CONDITIONAL([ENABLE_HPACK_TOOLS], [ test "x${enable_hpack_tools}" = "xyes" ])
# C++ library libnghttp2_asio
enable_asio_lib=no
if test "x${request_asio_lib}" != "xno" &&
test "x${have_asio_lib}" = "xyes"; then
enable_asio_lib=yes
fi
AM_CONDITIONAL([ENABLE_ASIO_LIB], [ test "x${enable_asio_lib}" = "xyes" ])
# The example programs depend on OpenSSL and libevent_openssl
enable_examples=no
if test "x${request_examples}" != "xno" &&
@ -866,8 +832,7 @@ have_mruby=no
have_neverbleed=no
if test "x${enable_examples}" = "xyes" ||
test "x${enable_app}" = "xyes" ||
test "x${enable_hpack_tools}" = "xyes" ||
test "x${enable_asio_lib}" = "xyes"; then
test "x${enable_hpack_tools}" = "xyes"; then
enable_third_party=yes
# mruby (for src/nghttpx)
@ -1159,8 +1124,6 @@ AC_CONFIG_FILES([
tests/testdata/Makefile
third-party/Makefile
src/Makefile
src/includes/Makefile
src/libnghttp2_asio.pc
bpf/Makefile
examples/Makefile
python/Makefile
@ -1177,14 +1140,10 @@ AC_CONFIG_FILES([
doc/tutorial-hpack.rst
doc/nghttpx-howto.rst
doc/h2load-howto.rst
doc/libnghttp2_asio.rst
doc/python-apiref.rst
doc/building-android-binary.rst
doc/nghttp2.h.rst
doc/nghttp2ver.h.rst
doc/asio_http2.h.rst
doc/asio_http2_server.h.rst
doc/asio_http2_client.h.rst
doc/contribute.rst
contrib/Makefile
script/Makefile
@ -1248,11 +1207,6 @@ AC_MSG_NOTICE([summary of build options:
Jemalloc: ${have_jemalloc} (CFLAGS='${JEMALLOC_CFLAGS}' LIBS='${JEMALLOC_LIBS}')
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
Systemd: ${have_libsystemd} (CFLAGS='${SYSTEMD_CFLAGS}' LIBS='${SYSTEMD_LIBS}')
Boost CPPFLAGS: ${BOOST_CPPFLAGS}
Boost LDFLAGS: ${BOOST_LDFLAGS}
Boost::ASIO: ${BOOST_ASIO_LIB}
Boost::System: ${BOOST_SYSTEM_LIB}
Boost::Thread: ${BOOST_THREAD_LIB}
Third-party:
http-parser: ${enable_third_party}
MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}')
@ -1260,7 +1214,6 @@ AC_MSG_NOTICE([summary of build options:
Features:
Applications: ${enable_app}
HPACK tools: ${enable_hpack_tools}
Libnghttp2_asio:${enable_asio_lib}
Examples: ${enable_examples}
Python bindings:${enable_python_bindings}
Threading: ${enable_threads}

4
doc/.gitignore vendored
View File

@ -1,15 +1,11 @@
# generated files
apiref.rst
asio_http2.h.rst
asio_http2_client.h.rst
asio_http2_server.h.rst
building-android-binary.rst
conf.py
contribute.rst
enums.rst
h2load-howto.rst
index.rst
libnghttp2_asio.rst
macros.rst
manual/
nghttp2.h.rst

View File

@ -180,7 +180,6 @@ set(EXTRA_DIST
sources/tutorial-hpack.rst
sources/nghttpx-howto.rst
sources/h2load-howto.rst
sources/libnghttp2_asio.rst
sources/python-apiref.rst
sources/building-android-binary.rst
sources/contribute.rst

View File

@ -206,7 +206,6 @@ EXTRA_DIST = \
sources/tutorial-hpack.rst \
sources/nghttpx-howto.rst \
sources/h2load-howto.rst \
sources/libnghttp2_asio.rst \
sources/python-apiref.rst \
sources/building-android-binary.rst \
sources/contribute.rst \

View File

@ -1,5 +0,0 @@
asio_http2.h
============
.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2.h
:language: cpp

View File

@ -1,5 +0,0 @@
asio_http2_client.h
===================
.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2_client.h
:language: cpp

View File

@ -1,5 +0,0 @@
asio_http2_server.h
===================
.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2_server.h
:language: cpp

View File

@ -1 +0,0 @@
.. include:: @top_srcdir@/doc/sources/libnghttp2_asio.rst

View File

@ -31,13 +31,9 @@ Contents:
h2load-howto
programmers-guide
apiref
libnghttp2_asio
python-apiref
nghttp2.h
nghttp2ver.h
asio_http2_server.h
asio_http2_client.h
asio_http2.h
Source <https://github.com/nghttp2/nghttp2>
Issues <https://github.com/nghttp2/nghttp2/issues>
nghttp2.org <https://nghttp2.org/>

View File

@ -1,439 +0,0 @@
libnghttp2_asio: High level HTTP/2 C++ library
==============================================
.. warning::
libnghttp2_asio has been deprecated in this repository due to
maintenance issue and will be removed at the end of 2022. It has
moved to https://github.com/nghttp2/nghttp2-asio.
libnghttp2_asio is C++ library built on top of libnghttp2 and provides
high level abstraction API to build HTTP/2 applications. It depends
on Boost::ASIO library and OpenSSL. Currently libnghttp2_asio
provides server and client side API.
libnghttp2_asio is not built by default. Use ``--enable-asio-lib``
configure flag to build libnghttp2_asio. The required Boost libraries
are:
* Boost::Asio
* Boost::System
* Boost::Thread
We have 3 header files for this library:
* :doc:`asio_http2_server.h`
* :doc:`asio_http2_client.h`
* :doc:`asio_http2.h`
asio_http2.h is included from the other two files.
To build a program with libnghttp2_asio, link to the following
libraries::
-lnghttp2_asio -lboost_system
If ``boost::asio::ssl`` is used in application code, OpenSSL is also
required in link line::
-lnghttp2_asio -lboost_system -lssl -lcrypto
Server API
----------
To use server API, first include following header file:
.. code-block:: cpp
#include <nghttp2/asio_http2_server.h>
Also take a look at that header file :doc:`asio_http2_server.h`.
Server API is designed to build HTTP/2 server very easily to utilize
C++11 anonymous function and closure. The bare minimum example of
HTTP/2 server looks like this:
.. code-block:: cpp
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
http2 server;
server.handle("/", [](const request &req, const response &res) {
res.write_head(200);
res.end("hello, world\n");
});
if (server.listen_and_serve(ec, "localhost", "3000")) {
std::cerr << "error: " << ec.message() << std::endl;
}
}
First we instantiate ``nghttp2::asio_http2::server::http2`` object.
``nghttp2::asio_http2::server::http2::handle`` function registers
pattern and its handler function. In this example, we register "/" as
pattern, which matches all requests. Then call
``nghttp2::asio_http2::server::http2::listen_and_serve`` function with
address and port to listen to.
The ``req`` and ``res`` represent HTTP request and response
respectively. ``nghttp2::asio_http2_::server::response::write_head``
constructs HTTP response header fields. The first argument is HTTP
status code, in the above example, which is 200. The second argument,
which is omitted in the above example, is additional header fields to
send.
``nghttp2::asio_http2::server::response::end`` sends response body.
In the above example, we send string "hello, world".
The life time of req and res object ends after the callback set by
``nghttp2::asio_http2::server::response::on_close`` function.
Application must not use those objects after this call.
Serving static files and enabling SSL/TLS
+++++++++++++++++++++++++++++++++++++++++
In this example, we serve a couple of static files and also enable
SSL/TLS.
.. code-block:: cpp
#include <nghttp2/asio_http2_server.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
tls.use_private_key_file("server.key", boost::asio::ssl::context::pem);
tls.use_certificate_chain_file("server.crt");
configure_tls_context_easy(ec, tls);
http2 server;
server.handle("/index.html", [](const request &req, const response &res) {
res.write_head(200);
res.end(file_generator("index.html"));
});
if (server.listen_and_serve(ec, tls, "localhost", "3000")) {
std::cerr << "error: " << ec.message() << std::endl;
}
}
We first create ``boost::asio::ssl::context`` object and set path to
private key file and certificate file.
``nghttp2::asio_http2::server::configure_tls_context_easy`` function
configures SSL/TLS context object for HTTP/2 server use, including NPN
callbacks.
In the above example, if request path is "/index.html", we serve
index.html file in the current working directory.
``nghttp2::asio_http2::server::response::end`` has overload to take
function of type ``nghttp2::asio_http2::generator_cb`` and application
pass its implementation to generate response body. For the
convenience, libnghttp2_asio library provides
``nghttp2::asio_http2::file_generator`` function to generate function
to server static file. If other resource is requested, server
automatically responds with 404 status code.
Server push
+++++++++++
Server push is also supported.
.. code-block:: cpp
#include <nghttp2/asio_http2_server.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
tls.use_private_key_file("server.key", boost::asio::ssl::context::pem);
tls.use_certificate_chain_file("server.crt");
configure_tls_context_easy(ec, tls);
http2 server;
std::string style_css = "h1 { color: green; }";
server.handle("/", [&style_css](const request &req, const response &res) {
boost::system::error_code ec;
auto push = res.push(ec, "GET", "/style.css");
push->write_head(200);
push->end(style_css);
res.write_head(200);
res.end(R"(
<!DOCTYPE html><html lang="en">
<title>HTTP/2 FTW</title><body>
<link href="/style.css" rel="stylesheet" type="text/css">
<h1>This should be green</h1>
</body></html>
)");
});
server.handle("/style.css",
[&style_css](const request &req, const response &res) {
res.write_head(200);
res.end(style_css);
});
if (server.listen_and_serve(ec, tls, "localhost", "3000")) {
std::cerr << "error: " << ec.message() << std::endl;
}
}
When client requested any resource other than "/style.css", we push
"/style.css". To push resource, call
``nghttp2::asio_http2::server::response::push`` function with desired
method and path. It returns another response object and use its
functions to send push response.
Enable multi-threading
++++++++++++++++++++++
Enabling multi-threading is very easy. Just call
``nghttp2::asio_http2::server::http2::num_threads`` function with the
desired number of threads:
.. code-block:: cpp
http2 server;
// Use 4 native threads
server.num_threads(4);
Client API
----------
To use client API, first include following header file:
.. code-block:: cpp
#include <nghttp2/asio_http2_client.h>
Also take a look at that header file :doc:`asio_http2_client.h`.
Here is the sample client code to access HTTP/2 server and print out
response header fields and response body to the console screen:
.. code-block:: cpp
#include <iostream>
#include <nghttp2/asio_http2_client.h>
using boost::asio::ip::tcp;
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::client;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
boost::asio::io_service io_service;
// connect to localhost:3000
session sess(io_service, "localhost", "3000");
sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
boost::system::error_code ec;
auto req = sess.submit(ec, "GET", "http://localhost:3000/");
req->on_response([](const response &res) {
// print status code and response header fields.
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
for (auto &kv : res.header()) {
std::cerr << kv.first << ": " << kv.second.value << "\n";
}
std::cerr << std::endl;
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
req->on_close([&sess](uint32_t error_code) {
// shutdown session after first request was done.
sess.shutdown();
});
});
sess.on_error([](const boost::system::error_code &ec) {
std::cerr << "error: " << ec.message() << std::endl;
});
io_service.run();
}
``nghttp2::asio_http2::client::session`` object takes
``boost::asio::io_service`` object and remote server address. When
connection is made, the callback function passed to
``nghttp2::asio_http2::client::on_connect`` is invoked with connected
address as its parameter. After this callback call, use
``nghttp2::asio_http2::session::submit`` to send request to the
server. You can submit multiple requests at once without waiting for
the completion of previous request.
The life time of req and res object ends after the callback set by
``nghttp2::asio_http2::server::request::on_close`` function.
Application must not use those objects after this call.
Normally, client does not stop even after all requests are done unless
connection is lost. To stop client, call
``nghttp2::asio_http2::server::session::shutdown()``.
Receive server push and enable SSL/TLS
++++++++++++++++++++++++++++++++++++++
.. code-block:: cpp
#include <iostream>
#include <nghttp2/asio_http2_client.h>
using boost::asio::ip::tcp;
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::client;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
boost::asio::io_service io_service;
boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
tls.set_default_verify_paths();
// disabled to make development easier...
// tls_ctx.set_verify_mode(boost::asio::ssl::verify_peer);
configure_tls_context(ec, tls);
// connect to localhost:3000
session sess(io_service, tls, "localhost", "3000");
sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
boost::system::error_code ec;
auto req = sess.submit(ec, "GET", "http://localhost:3000/");
req->on_response([&sess](const response &res) {
std::cerr << "response received!" << std::endl;
res.on_data([&sess](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
req->on_push([](const request &push) {
std::cerr << "push request received!" << std::endl;
push.on_response([](const response &res) {
std::cerr << "push response received!" << std::endl;
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
});
});
sess.on_error([](const boost::system::error_code &ec) {
std::cerr << "error: " << ec.message() << std::endl;
});
io_service.run();
}
The above sample code demonstrates how to enable SSL/TLS and receive
server push. Currently,
``nghttp2::asio_http2::client::configure_tls_context`` function setups
NPN callbacks for SSL/TLS context for HTTP/2 use.
To receive server push, use
``nghttp2::asio_http2::client::request::on_push`` function to set
callback function which is invoked when server push request is
arrived. The callback function takes
``nghttp2::asio_http2::client::request`` object, which contains the
pushed request. To get server push response, set callback using
``nghttp2::asio_http2::client::request::on_response``.
As stated in the previous section, client does not stop automatically
as long as HTTP/2 session is fine and connection is alive. We don't
call ``nghttp2::asio_http2::client::session::shutdown`` in this
example, so the program does not terminate after all responses are
received. Hit Ctrl-C to terminate the program.
Multiple concurrent requests
++++++++++++++++++++++++++++
.. code-block:: cpp
#include <iostream>
#include <nghttp2/asio_http2_client.h>
using boost::asio::ip::tcp;
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::client;
int main(int argc, char *argv[]) {
boost::system::error_code ec;
boost::asio::io_service io_service;
// connect to localhost:3000
session sess(io_service, "localhost", "3000");
sess.on_connect([&sess](tcp::resolver::iterator endpoint_it) {
boost::system::error_code ec;
auto printer = [](const response &res) {
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
};
std::size_t num = 3;
auto count = std::make_shared<int>(num);
for (std::size_t i = 0; i < num; ++i) {
auto req = sess.submit(ec, "GET",
"http://localhost:3000/" + std::to_string(i + 1));
req->on_response(printer);
req->on_close([&sess, count](uint32_t error_code) {
if (--*count == 0) {
// shutdown session after |num| requests were done.
sess.shutdown();
}
});
}
});
sess.on_error([](const boost::system::error_code &ec) {
std::cerr << "error: " << ec.message() << std::endl;
});
io_service.run();
}
Here is the sample to send 3 requests at once. Depending on the
server settings, these requests are processed out-of-order. In this
example, we have a trick to shutdown session after all requests were
done. We made ``count`` object which is shared pointer to int and is
initialized to 3. On each request closure (the invocation of the
callback set by ``nghttp2::asio_http2::client::request::on_close``),
we decrement the count. If count becomes 0, we are sure that all
requests have been done and initiate shutdown.

4
examples/.gitignore vendored
View File

@ -3,7 +3,3 @@ libevent-client
libevent-server
deflate
tiny-nghttpd
asio-sv
asio-sv2
asio-cl
asio-cl2

View File

@ -34,24 +34,4 @@ if(ENABLE_EXAMPLES)
add_executable(deflate deflate.c $<TARGET_OBJECTS:llhttp>
$<TARGET_OBJECTS:url-parser>
)
if(ENABLE_ASIO_LIB)
foreach(name asio-sv asio-sv2 asio-cl asio-cl2)
add_executable(${name} ${name}.cc $<TARGET_OBJECTS:llhttp>
$<TARGET_OBJECTS:url-parser>
)
target_include_directories(${name} PRIVATE
${OPENSSL_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
target_link_libraries(${name}
nghttp2
nghttp2_asio
${JEMALLOC_LIBRARIES}
${OPENSSL_LIBRARIES}
${Boost_LIBRARIES}
${APP_LIBRARIES}
)
endforeach()
endif()
endif()

View File

@ -52,40 +52,4 @@ libevent_server_SOURCES = libevent-server.c
deflate_SOURCES = deflate.c
if ENABLE_ASIO_LIB
noinst_PROGRAMS += asio-sv asio-sv2 asio-cl asio-cl2
# AM_CPPFLAGS must be placed first, so that header file (e.g.,
# nghttp2/nghttp2.h) in this package is used rather than installed
# one.
ASIOCPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS}
ASIOLDADD = $(top_builddir)/lib/libnghttp2.la \
$(top_builddir)/src/libnghttp2_asio.la @JEMALLOC_LIBS@ \
$(top_builddir)/third-party/liburl-parser.la \
@OPENSSL_LIBS@ \
${BOOST_LDFLAGS} \
${BOOST_ASIO_LIB} \
${BOOST_THREAD_LIB} \
${BOOST_SYSTEM_LIB} \
@APPLDFLAGS@
asio_sv_SOURCES = asio-sv.cc
asio_sv_CPPFLAGS = ${ASIOCPPFLAGS}
asio_sv_LDADD = ${ASIOLDADD}
asio_sv2_SOURCES = asio-sv2.cc
asio_sv2_CPPFLAGS = ${ASIOCPPFLAGS}
asio_sv2_LDADD = ${ASIOLDADD}
asio_cl_SOURCES = asio-cl.cc
asio_cl_CPPFLAGS = ${ASIOCPPFLAGS}
asio_cl_LDADD = ${ASIOLDADD}
asio_cl2_SOURCES = asio-cl2.cc
asio_cl2_CPPFLAGS = ${ASIOCPPFLAGS}
asio_cl2_LDADD = ${ASIOLDADD}
endif # ENABLE_ASIO_LIB
endif # ENABLE_EXAMPLES

View File

@ -1,96 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <iostream>
#include <nghttp2/asio_http2_client.h>
using boost::asio::ip::tcp;
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::client;
int main(int argc, char *argv[]) {
try {
if (argc < 2) {
std::cerr << "Usage: asio-cl URI" << std::endl;
return 1;
}
boost::system::error_code ec;
boost::asio::io_service io_service;
std::string uri = argv[1];
std::string scheme, host, service;
if (host_service_from_uri(ec, scheme, host, service, uri)) {
std::cerr << "error: bad URI: " << ec.message() << std::endl;
return 1;
}
boost::asio::ssl::context tls_ctx(boost::asio::ssl::context::sslv23);
tls_ctx.set_default_verify_paths();
// disabled to make development easier...
// tls_ctx.set_verify_mode(boost::asio::ssl::verify_peer);
configure_tls_context(ec, tls_ctx);
auto sess = scheme == "https" ? session(io_service, tls_ctx, host, service)
: session(io_service, host, service);
sess.on_connect([&sess, &uri](tcp::resolver::iterator endpoint_it) {
boost::system::error_code ec;
auto req = sess.submit(ec, "GET", uri);
if (ec) {
std::cerr << "error: " << ec.message() << std::endl;
return;
}
req->on_response([](const response &res) {
std::cerr << "HTTP/2 " << res.status_code() << std::endl;
for (auto &kv : res.header()) {
std::cerr << kv.first << ": " << kv.second.value << "\n";
}
std::cerr << std::endl;
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
req->on_close([&sess](uint32_t error_code) { sess.shutdown(); });
});
sess.on_error([](const boost::system::error_code &ec) {
std::cerr << "error: " << ec.message() << std::endl;
});
io_service.run();
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}

View File

@ -1,134 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <iostream>
#include <string>
#include <nghttp2/asio_http2_client.h>
using boost::asio::ip::tcp;
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::client;
void print_header(const header_map &h) {
for (auto &kv : h) {
std::cerr << kv.first << ": " << kv.second.value << "\n";
}
std::cerr << std::endl;
}
void print_header(const response &res) {
std::cerr << "HTTP/2 " << res.status_code() << "\n";
print_header(res.header());
}
void print_header(const request &req) {
auto &uri = req.uri();
std::cerr << req.method() << " " << uri.scheme << "://" << uri.host
<< uri.path;
if (!uri.raw_query.empty()) {
std::cerr << "?" << uri.raw_query;
}
std::cerr << " HTTP/2\n";
print_header(req.header());
}
int main(int argc, char *argv[]) {
try {
if (argc < 2) {
std::cerr << "Usage: asio-cl URI" << std::endl;
return 1;
}
boost::system::error_code ec;
boost::asio::io_service io_service;
std::string uri = argv[1];
std::string scheme, host, service;
if (host_service_from_uri(ec, scheme, host, service, uri)) {
std::cerr << "error: bad URI: " << ec.message() << std::endl;
return 1;
}
boost::asio::ssl::context tls_ctx(boost::asio::ssl::context::sslv23);
tls_ctx.set_default_verify_paths();
// disabled to make development easier...
// tls_ctx.set_verify_mode(boost::asio::ssl::verify_peer);
configure_tls_context(ec, tls_ctx);
auto sess = scheme == "https" ? session(io_service, tls_ctx, host, service)
: session(io_service, host, service);
sess.on_connect([&sess, &uri](tcp::resolver::iterator endpoint_it) {
std::cerr << "connected to " << (*endpoint_it).endpoint() << std::endl;
boost::system::error_code ec;
auto req = sess.submit(ec, "GET", uri, {{"cookie", {"foo=bar", true}}});
if (ec) {
std::cerr << "error: " << ec.message() << std::endl;
return;
}
req->on_response([](const response &res) {
std::cerr << "response header was received" << std::endl;
print_header(res);
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
req->on_close([](uint32_t error_code) {
std::cerr << "request done with error_code=" << error_code << std::endl;
});
req->on_push([](const request &push_req) {
std::cerr << "push request was received" << std::endl;
print_header(push_req);
push_req.on_response([](const response &res) {
std::cerr << "push response header was received" << std::endl;
res.on_data([](const uint8_t *data, std::size_t len) {
std::cerr.write(reinterpret_cast<const char *>(data), len);
std::cerr << std::endl;
});
});
});
});
sess.on_error([](const boost::system::error_code &ec) {
std::cerr << "error: " << ec.message() << std::endl;
});
io_service.run();
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}

View File

@ -1,149 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// main.cpp
// ~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <iostream>
#include <string>
#include <nghttp2/asio_http2_server.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
try {
// Check command line arguments.
if (argc < 4) {
std::cerr
<< "Usage: asio-sv <address> <port> <threads> [<private-key-file> "
<< "<cert-file>]\n";
return 1;
}
boost::system::error_code ec;
std::string addr = argv[1];
std::string port = argv[2];
std::size_t num_threads = std::stoi(argv[3]);
http2 server;
server.num_threads(num_threads);
server.handle("/", [](const request &req, const response &res) {
res.write_head(200, {{"foo", {"bar"}}});
res.end("hello, world\n");
});
server.handle("/secret/", [](const request &req, const response &res) {
res.write_head(200);
res.end("under construction!\n");
});
server.handle("/push", [](const request &req, const response &res) {
boost::system::error_code ec;
auto push = res.push(ec, "GET", "/push/1");
if (!ec) {
push->write_head(200);
push->end("server push FTW!\n");
}
res.write_head(200);
res.end("you'll receive server push!\n");
});
server.handle("/delay", [](const request &req, const response &res) {
res.write_head(200);
auto timer = std::make_shared<boost::asio::deadline_timer>(
res.io_service(), boost::posix_time::seconds(3));
auto closed = std::make_shared<bool>();
res.on_close([timer, closed](uint32_t error_code) {
timer->cancel();
*closed = true;
});
timer->async_wait([&res, closed](const boost::system::error_code &ec) {
if (ec || *closed) {
return;
}
res.end("finally!\n");
});
});
server.handle("/trailer", [](const request &req, const response &res) {
// send trailer part.
res.write_head(200, {{"trailers", {"digest"}}});
std::string body = "nghttp2 FTW!\n";
auto left = std::make_shared<size_t>(body.size());
res.end([&res, body, left](uint8_t *dst, std::size_t len,
uint32_t *data_flags) {
auto n = std::min(len, *left);
std::copy_n(body.c_str() + (body.size() - *left), n, dst);
*left -= n;
if (*left == 0) {
*data_flags |=
NGHTTP2_DATA_FLAG_EOF | NGHTTP2_DATA_FLAG_NO_END_STREAM;
// RFC 3230 Instance Digests in HTTP. The digest value is
// SHA-256 message digest of body.
res.write_trailer(
{{"digest",
{"SHA-256=qqXqskW7F3ueBSvmZRCiSwl2ym4HRO0M/pvQCBlSDis="}}});
}
return n;
});
});
if (argc >= 6) {
boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
tls.use_private_key_file(argv[4], boost::asio::ssl::context::pem);
tls.use_certificate_chain_file(argv[5]);
configure_tls_context_easy(ec, tls);
if (server.listen_and_serve(ec, tls, addr, port)) {
std::cerr << "error: " << ec.message() << std::endl;
}
} else {
if (server.listen_and_serve(ec, addr, port)) {
std::cerr << "error: " << ec.message() << std::endl;
}
}
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}

View File

@ -1,125 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// main.cpp
// ~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif // HAVE_UNISTD_H
#ifdef HAVE_FCNTL_H
# include <fcntl.h>
#endif // HAVE_FCNTL_H
#include <iostream>
#include <string>
#include <nghttp2/asio_http2_server.h>
using namespace nghttp2::asio_http2;
using namespace nghttp2::asio_http2::server;
int main(int argc, char *argv[]) {
try {
// Check command line arguments.
if (argc < 5) {
std::cerr << "Usage: asio-sv2 <address> <port> <threads> <doc-root> "
<< "[<private-key-file> <cert-file>]\n";
return 1;
}
boost::system::error_code ec;
std::string addr = argv[1];
std::string port = argv[2];
std::size_t num_threads = std::stoi(argv[3]);
std::string docroot = argv[4];
http2 server;
server.num_threads(num_threads);
server.handle("/", [&docroot](const request &req, const response &res) {
auto path = percent_decode(req.uri().path);
if (!check_path(path)) {
res.write_head(404);
res.end();
return;
}
if (path == "/") {
path = "/index.html";
}
path = docroot + path;
auto fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
res.write_head(404);
res.end();
return;
}
auto header = header_map();
struct stat stbuf;
if (stat(path.c_str(), &stbuf) == 0) {
header.emplace("content-length",
header_value{std::to_string(stbuf.st_size)});
header.emplace("last-modified",
header_value{http_date(stbuf.st_mtime)});
}
res.write_head(200, std::move(header));
res.end(file_generator_from_fd(fd));
});
if (argc >= 7) {
boost::asio::ssl::context tls(boost::asio::ssl::context::sslv23);
tls.use_private_key_file(argv[5], boost::asio::ssl::context::pem);
tls.use_certificate_chain_file(argv[6]);
configure_tls_context_easy(ec, tls);
if (server.listen_and_serve(ec, tls, addr, port)) {
std::cerr << "error: " << ec.message() << std::endl;
}
} else {
if (server.listen_and_serve(ec, addr, port)) {
std::cerr << "error: " << ec.message() << std::endl;
}
}
} catch (std::exception &e) {
std::cerr << "exception: " << e.what() << "\n";
}
return 0;
}

View File

@ -1,110 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_asio.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_ASIO
#
# DESCRIPTION
#
# Test for Asio library from the Boost C++ libraries. The macro requires a
# preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_ASIO_LIB)
#
# And sets:
#
# HAVE_BOOST_ASIO
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2008 Pete Greenwell <pete@mu.org>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 16
AC_DEFUN([AX_BOOST_ASIO],
[
AC_ARG_WITH([boost-asio],
AS_HELP_STRING([--with-boost-asio@<:@=special-lib@:>@],
[use the ASIO library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-asio=boost_system-gcc41-mt-1_34 ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_asio_lib=""
else
want_boost="yes"
ax_boost_user_asio_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::ASIO library is available,
ax_cv_boost_asio,
[AC_LANG_PUSH([C++])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ @%:@include <boost/asio.hpp>
]],
[[
boost::asio::io_service io;
boost::system::error_code timer_result;
boost::asio::deadline_timer t(io);
t.cancel();
io.run_one();
return 0;
]])],
ax_cv_boost_asio=yes, ax_cv_boost_asio=no)
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_asio" = "xyes"; then
AC_DEFINE(HAVE_BOOST_ASIO,,[define if the Boost::ASIO library is available])
BN=boost_system
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
if test "x$ax_boost_user_asio_lib" = "x"; then
for ax_lib in `ls $BOOSTLIBDIR/libboost_system*.so* $BOOSTLIBDIR/libboost_system*.dylib* $BOOSTLIBDIR/libboost_system*.a* 2>/dev/null | sed 's,.*/,,' | sed -e 's;^lib\(boost_system.*\)\.so.*$;\1;' -e 's;^lib\(boost_system.*\)\.dylib.*$;\1;' -e 's;^lib\(boost_system.*\)\.a.*$;\1;' ` ; do
AC_CHECK_LIB($ax_lib, main, [BOOST_ASIO_LIB="-l$ax_lib" AC_SUBST(BOOST_ASIO_LIB) link_thread="yes" break],
[link_thread="no"])
done
else
for ax_lib in $ax_boost_user_asio_lib $BN-$ax_boost_user_asio_lib; do
AC_CHECK_LIB($ax_lib, main,
[BOOST_ASIO_LIB="-l$ax_lib" AC_SUBST(BOOST_ASIO_LIB) link_asio="yes" break],
[link_asio="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_asio" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View File

@ -1,275 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
#
# DESCRIPTION
#
# Test for the Boost C++ libraries of a particular version (or newer)
#
# If no path to the installed boost library is given the macro searchs
# under /usr, /usr/local, /opt and /opt/local and evaluates the
# $BOOST_ROOT environment variable. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
#
# And sets:
#
# HAVE_BOOST
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2009 Peter Adolphs
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 25
AC_DEFUN([AX_BOOST_BASE],
[
AC_ARG_WITH([boost],
[AS_HELP_STRING([--with-boost@<:@=ARG@:>@],
[use Boost library from a standard location (ARG=yes),
from the specified location (ARG=<path>),
or disable it (ARG=no)
@<:@ARG=yes@:>@ ])],
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ac_boost_path=""
else
want_boost="yes"
ac_boost_path="$withval"
fi
],
[want_boost="yes"])
AC_ARG_WITH([boost-libdir],
AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
[Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]),
[
if test -d "$withval"
then
ac_boost_lib_path="$withval"
else
AC_MSG_ERROR(--with-boost-libdir expected directory name)
fi
],
[ac_boost_lib_path=""]
)
if test "x$want_boost" = "xyes"; then
boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'`
boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
if test "x$boost_lib_version_req_sub_minor" = "x" ; then
boost_lib_version_req_sub_minor="0"
fi
WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
succeeded=no
dnl On 64-bit systems check for system libraries in both lib64 and lib.
dnl The former is specified by FHS, but e.g. Debian does not adhere to
dnl this (as it rises problems for generic multi-arch support).
dnl The last entry in the list is chosen by default when no libraries
dnl are found, e.g. when only header-only libraries are installed!
libsubdirs="lib"
ax_arch=`uname -m`
case $ax_arch in
x86_64)
libsubdirs="lib64 libx32 lib lib64"
;;
ppc64|s390x|sparc64|aarch64|ppc64le)
libsubdirs="lib64 lib lib64 ppc64le"
;;
esac
dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give
dnl them priority over the other paths since, if libs are found there, they
dnl are almost assuredly the ones desired.
AC_REQUIRE([AC_CANONICAL_HOST])
libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs"
case ${host_cpu} in
i?86)
libsubdirs="lib/i386-${host_os} $libsubdirs"
;;
esac
dnl first we check the system location for boost libraries
dnl this location ist chosen if boost libraries are installed with the --layout=system option
dnl or if you install boost with RPM
if test "$ac_boost_path" != ""; then
BOOST_CPPFLAGS="-I$ac_boost_path/include"
for ac_boost_path_tmp in $libsubdirs; do
if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then
BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp"
break
fi
done
elif test "$cross_compiling" != yes; then
for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then
for libsubdir in $libsubdirs ; do
if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir"
BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
break;
fi
done
fi
dnl overwrite ld flags if we have required special directory with
dnl --with-boost-libdir parameter
if test "$ac_boost_lib_path" != ""; then
BOOST_LDFLAGS="-L$ac_boost_lib_path"
fi
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_REQUIRE([AC_PROG_CXX])
AC_LANG_PUSH(C++)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@%:@include <boost/version.hpp>
]], [[
#if BOOST_VERSION >= $WANT_BOOST_VERSION
// Everything is okay
#else
# error Boost version is too old
#endif
]])],[
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
],[
])
AC_LANG_POP([C++])
dnl if we found no boost with system layout we search for boost libraries
dnl built and installed without the --layout=system option or for a staged(not installed) version
if test "x$succeeded" != "xyes"; then
_version=0
if test "$ac_boost_path" != ""; then
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
V_CHECK=`expr $_version_tmp \> $_version`
if test "$V_CHECK" = "1" ; then
_version=$_version_tmp
fi
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
done
fi
else
if test "$cross_compiling" != yes; then
for ac_boost_path in /usr /usr/local /opt /opt/local ; do
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
V_CHECK=`expr $_version_tmp \> $_version`
if test "$V_CHECK" = "1" ; then
_version=$_version_tmp
best_path=$ac_boost_path
fi
done
fi
done
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
if test "$ac_boost_lib_path" = ""; then
for libsubdir in $libsubdirs ; do
if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
BOOST_LDFLAGS="-L$best_path/$libsubdir"
fi
fi
if test "x$BOOST_ROOT" != "x"; then
for libsubdir in $libsubdirs ; do
if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
done
if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then
version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'`
stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
V_CHECK=`expr $stage_version_shorten \>\= $_version`
if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then
AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
BOOST_CPPFLAGS="-I$BOOST_ROOT"
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir"
fi
fi
fi
fi
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_LANG_PUSH(C++)
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
@%:@include <boost/version.hpp>
]], [[
#if BOOST_VERSION >= $WANT_BOOST_VERSION
// Everything is okay
#else
# error Boost version is too old
#endif
]])],[
AC_MSG_RESULT(yes)
succeeded=yes
found_system=yes
],[
])
AC_LANG_POP([C++])
fi
if test "$succeeded" != "yes" ; then
if test "$_version" = "0" ; then
AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
else
AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])
fi
# execute ACTION-IF-NOT-FOUND (if present):
ifelse([$3], , :, [$3])
else
AC_SUBST(BOOST_CPPFLAGS)
AC_SUBST(BOOST_LDFLAGS)
AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
# execute ACTION-IF-FOUND (if present):
ifelse([$2], , :, [$2])
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View File

@ -1,120 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_system.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_SYSTEM
#
# DESCRIPTION
#
# Test for System library from the Boost C++ libraries. The macro requires
# a preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_SYSTEM_LIB)
#
# And sets:
#
# HAVE_BOOST_SYSTEM
#
# LICENSE
#
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2008 Michael Tindal
# Copyright (c) 2008 Daniel Casimiro <dan.casimiro@gmail.com>
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 17
AC_DEFUN([AX_BOOST_SYSTEM],
[
AC_ARG_WITH([boost-system],
AS_HELP_STRING([--with-boost-system@<:@=special-lib@:>@],
[use the System library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-system=boost_system-gcc-mt ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_system_lib=""
else
want_boost="yes"
ax_boost_user_system_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::System library is available,
ax_cv_boost_system,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/system/error_code.hpp>]],
[[boost::system::system_category]])],
ax_cv_boost_system=yes, ax_cv_boost_system=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_system" = "xyes"; then
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_SYSTEM,,[define if the Boost::System library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
if test "x$ax_boost_user_system_lib" = "x"; then
for libextension in `ls -r $BOOSTLIBDIR/libboost_system* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
[link_system="no"])
done
if test "x$link_system" != "xyes"; then
for libextension in `ls -r $BOOSTLIBDIR/boost_system* 2>/dev/null | sed 's,.*/,,' | sed -e 's,\..*,,'` ; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
[link_system="no"])
done
fi
else
for ax_lib in $ax_boost_user_system_lib boost_system-$ax_boost_user_system_lib; do
AC_CHECK_LIB($ax_lib, exit,
[BOOST_SYSTEM_LIB="-l$ax_lib"; AC_SUBST(BOOST_SYSTEM_LIB) link_system="yes"; break],
[link_system="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_system" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View File

@ -1,149 +0,0 @@
# ===========================================================================
# http://www.gnu.org/software/autoconf-archive/ax_boost_thread.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_BOOST_THREAD
#
# DESCRIPTION
#
# Test for Thread library from the Boost C++ libraries. The macro requires
# a preceding call to AX_BOOST_BASE. Further documentation is available at
# <http://randspringer.de/boost/index.html>.
#
# This macro calls:
#
# AC_SUBST(BOOST_THREAD_LIB)
#
# And sets:
#
# HAVE_BOOST_THREAD
#
# LICENSE
#
# Copyright (c) 2009 Thomas Porschberg <thomas@randspringer.de>
# Copyright (c) 2009 Michael Tindal
#
# Copying and distribution of this file, with or without modification, are
# permitted in any medium without royalty provided the copyright notice
# and this notice are preserved. This file is offered as-is, without any
# warranty.
#serial 27
AC_DEFUN([AX_BOOST_THREAD],
[
AC_ARG_WITH([boost-thread],
AS_HELP_STRING([--with-boost-thread@<:@=special-lib@:>@],
[use the Thread library from boost - it is possible to specify a certain library for the linker
e.g. --with-boost-thread=boost_thread-gcc-mt ]),
[
if test "$withval" = "no"; then
want_boost="no"
elif test "$withval" = "yes"; then
want_boost="yes"
ax_boost_user_thread_lib=""
else
want_boost="yes"
ax_boost_user_thread_lib="$withval"
fi
],
[want_boost="yes"]
)
if test "x$want_boost" = "xyes"; then
AC_REQUIRE([AC_PROG_CC])
AC_REQUIRE([AC_CANONICAL_BUILD])
CPPFLAGS_SAVED="$CPPFLAGS"
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
export CPPFLAGS
LDFLAGS_SAVED="$LDFLAGS"
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
export LDFLAGS
AC_CACHE_CHECK(whether the Boost::Thread library is available,
ax_cv_boost_thread,
[AC_LANG_PUSH([C++])
CXXFLAGS_SAVE=$CXXFLAGS
if test "x$host_os" = "xsolaris" ; then
CXXFLAGS="-pthreads $CXXFLAGS"
elif test "x$host_os" = "xmingw32" ; then
CXXFLAGS="-mthreads $CXXFLAGS"
else
CXXFLAGS="-pthread $CXXFLAGS"
fi
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@include <boost/thread/thread.hpp>]],
[[boost::thread_group thrds;
return 0;]])],
ax_cv_boost_thread=yes, ax_cv_boost_thread=no)
CXXFLAGS=$CXXFLAGS_SAVE
AC_LANG_POP([C++])
])
if test "x$ax_cv_boost_thread" = "xyes"; then
if test "x$host_os" = "xsolaris" ; then
BOOST_CPPFLAGS="-pthreads $BOOST_CPPFLAGS"
elif test "x$host_os" = "xmingw32" ; then
BOOST_CPPFLAGS="-mthreads $BOOST_CPPFLAGS"
else
BOOST_CPPFLAGS="-pthread $BOOST_CPPFLAGS"
fi
AC_SUBST(BOOST_CPPFLAGS)
AC_DEFINE(HAVE_BOOST_THREAD,,[define if the Boost::Thread library is available])
BOOSTLIBDIR=`echo $BOOST_LDFLAGS | sed -e 's/@<:@^\/@:>@*//'`
LDFLAGS_SAVE=$LDFLAGS
case "x$host_os" in
*bsd* )
LDFLAGS="-pthread $LDFLAGS"
break;
;;
esac
if test "x$ax_boost_user_thread_lib" = "x"; then
for libextension in `ls -r $BOOSTLIBDIR/libboost_thread* 2>/dev/null | sed 's,.*/lib,,' | sed 's,\..*,,'`; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
[link_thread="no"])
done
if test "x$link_thread" != "xyes"; then
for libextension in `ls -r $BOOSTLIBDIR/boost_thread* 2>/dev/null | sed 's,.*/,,' | sed 's,\..*,,'`; do
ax_lib=${libextension}
AC_CHECK_LIB($ax_lib, exit,
[BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
[link_thread="no"])
done
fi
else
for ax_lib in $ax_boost_user_thread_lib boost_thread-$ax_boost_user_thread_lib; do
AC_CHECK_LIB($ax_lib, exit,
[BOOST_THREAD_LIB="-l$ax_lib"; AC_SUBST(BOOST_THREAD_LIB) link_thread="yes"; break],
[link_thread="no"])
done
fi
if test "x$ax_lib" = "x"; then
AC_MSG_ERROR(Could not find a version of the library!)
fi
if test "x$link_thread" = "xno"; then
AC_MSG_ERROR(Could not link against $ax_lib !)
else
case "x$host_os" in
*bsd* )
BOOST_LDFLAGS="-pthread $BOOST_LDFLAGS"
break;
;;
esac
fi
fi
CPPFLAGS="$CPPFLAGS_SAVED"
LDFLAGS="$LDFLAGS_SAVED"
fi
])

View File

@ -2,5 +2,5 @@
autoreconf -i
git submodule update --init
./configure --with-mruby --with-neverbleed --enable-asio-lib
make -j8 distcheck DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --enable-asio-lib --enable-werror"
./configure --with-mruby --with-neverbleed
make -j8 distcheck DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --enable-werror"

3
src/.gitignore vendored
View File

@ -1,6 +1,3 @@
# generated files
libnghttp2_asio.pc
# programs
deflatehd
h2load

View File

@ -1,5 +1,3 @@
add_subdirectory(includes)
file(GLOB c_sources *.c)
set_source_files_properties(${c_sources} PROPERTIES
COMPILE_FLAGS "${WARNCFLAGS}")
@ -243,65 +241,3 @@ if(ENABLE_HPACK_TOOLS)
install(TARGETS inflatehd deflatehd
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
endif()
if(ENABLE_ASIO_LIB)
set(NGHTTP2_ASIO_SOURCES
util.cc http2.cc
tls.cc
timegm.c
asio_common.cc
asio_io_service_pool.cc
asio_server_http2.cc
asio_server_http2_impl.cc
asio_server.cc
asio_server_http2_handler.cc
asio_server_request.cc
asio_server_request_impl.cc
asio_server_response.cc
asio_server_response_impl.cc
asio_server_stream.cc
asio_server_serve_mux.cc
asio_server_request_handler.cc
asio_server_tls_context.cc
asio_client_session.cc
asio_client_session_impl.cc
asio_client_session_tcp_impl.cc
asio_client_session_tls_impl.cc
asio_client_response.cc
asio_client_response_impl.cc
asio_client_request.cc
asio_client_request_impl.cc
asio_client_stream.cc
asio_client_tls_context.cc
)
add_library(nghttp2_asio SHARED
${NGHTTP2_ASIO_SOURCES}
$<TARGET_OBJECTS:llhttp>
$<TARGET_OBJECTS:url-parser>
)
target_include_directories(nghttp2_asio PRIVATE
${OPENSSL_INCLUDE_DIRS}
${Boost_INCLUDE_DIRS}
)
target_include_directories(nghttp2_asio INTERFACE
"${CMAKE_CURRENT_BINARY_DIR}/../lib/includes"
"${CMAKE_CURRENT_SOURCE_DIR}/../lib/includes"
"${CMAKE_CURRENT_SOURCE_DIR}/includes"
)
target_link_libraries(nghttp2_asio
nghttp2
${OPENSSL_LIBRARIES}
${Boost_LIBRARIES}
)
set_target_properties(nghttp2_asio PROPERTIES
VERSION 1.0.0 SOVERSION 1)
install(TARGETS nghttp2_asio
ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"
LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2_asio.pc"
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
endif()

View File

@ -20,8 +20,6 @@
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
SUBDIRS = includes
EXTRA_DIST = \
CMakeLists.txt \
test.example.com.pem \
@ -95,10 +93,10 @@ endif # HAVE_LIBXML2
nghttp_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttp.cc nghttp.h \
${HTML_PARSER_OBJECTS} ${HTML_PARSER_HFILES} \
tls.cc tls.h
tls.cc tls.h ssl_compat.h
nghttpd_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttpd.cc \
tls.cc tls.h \
tls.cc tls.h ssl_compat.h \
HttpServer.cc HttpServer.h
bin_PROGRAMS += h2load
@ -106,7 +104,7 @@ bin_PROGRAMS += h2load
h2load_SOURCES = util.cc util.h \
http2.cc http2.h h2load.cc h2load.h \
timegm.c timegm.h \
tls.cc tls.h \
tls.cc tls.h ssl_compat.h \
h2load_session.h \
h2load_http2_session.cc h2load_http2_session.h \
h2load_http1_session.cc h2load_http1_session.h
@ -121,7 +119,7 @@ endif # ENABLE_HTTP3
NGHTTPX_SRCS = \
util.cc util.h http2.cc http2.h timegm.c timegm.h base64.h \
app_helper.cc app_helper.h \
tls.cc tls.h \
tls.cc tls.h ssl_compat.h \
shrpx_config.cc shrpx_config.h \
shrpx_error.h \
shrpx_accept_handler.cc shrpx_accept_handler.h \
@ -256,56 +254,3 @@ inflatehd_SOURCES = inflatehd.cc $(HPACK_TOOLS_COMMON_SRCS)
deflatehd_SOURCES = deflatehd.cc $(HPACK_TOOLS_COMMON_SRCS)
endif # ENABLE_HPACK_TOOLS
if ENABLE_ASIO_LIB
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = libnghttp2_asio.pc
DISTCLEANFILES = $(pkgconfig_DATA)
lib_LTLIBRARIES = libnghttp2_asio.la
libnghttp2_asio_la_SOURCES = \
util.cc util.h http2.cc http2.h \
tls.cc tls.h \
ssl_compat.h \
timegm.c timegm.h \
asio_common.cc asio_common.h \
asio_io_service_pool.cc asio_io_service_pool.h \
asio_server_http2.cc \
asio_server_http2_impl.cc asio_server_http2_impl.h \
asio_server.cc asio_server.h \
asio_server_http2_handler.cc asio_server_http2_handler.h \
asio_server_connection.h \
asio_server_request.cc \
asio_server_request_impl.cc asio_server_request_impl.h \
asio_server_response.cc \
asio_server_response_impl.cc asio_server_response_impl.h \
asio_server_stream.cc asio_server_stream.h \
asio_server_serve_mux.cc asio_server_serve_mux.h \
asio_server_request_handler.cc asio_server_request_handler.h \
asio_server_tls_context.cc asio_server_tls_context.h \
asio_client_session.cc \
asio_client_session_impl.cc asio_client_session_impl.h \
asio_client_session_tcp_impl.cc asio_client_session_tcp_impl.h \
asio_client_session_tls_impl.cc asio_client_session_tls_impl.h \
asio_client_response.cc \
asio_client_response_impl.cc asio_client_response_impl.h \
asio_client_request.cc \
asio_client_request_impl.cc asio_client_request_impl.h \
asio_client_stream.cc asio_client_stream.h \
asio_client_tls_context.cc asio_client_tls_context.h
libnghttp2_asio_la_CPPFLAGS = ${AM_CPPFLAGS} ${BOOST_CPPFLAGS}
libnghttp2_asio_la_LDFLAGS = $(AM_LDFLAGS) -no-undefined -version-info 1:0:0
libnghttp2_asio_la_LIBADD = \
$(top_builddir)/lib/libnghttp2.la \
$(top_builddir)/third-party/liburl-parser.la \
$(top_builddir)/third-party/libllhttp.la \
@OPENSSL_LIBS@ \
${BOOST_LDFLAGS} \
${BOOST_ASIO_LIB} \
${BOOST_THREAD_LIB} \
${BOOST_SYSTEM_LIB}
endif # ENABLE_ASIO_LIB

View File

@ -1,67 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_client.h>
#include "asio_client_request_impl.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
request::request() : impl_(std::make_unique<request_impl>()) {}
request::~request() {}
void request::write_trailer(header_map h) const {
impl_->write_trailer(std::move(h));
}
void request::cancel(uint32_t error_code) const { impl_->cancel(error_code); }
void request::on_response(response_cb cb) const {
impl_->on_response(std::move(cb));
}
void request::on_push(request_cb cb) const { impl_->on_push(std::move(cb)); }
void request::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); }
const uri_ref &request::uri() const { return impl_->uri(); }
const std::string &request::method() const { return impl_->method(); }
const header_map &request::header() const { return impl_->header(); }
void request::resume() const { impl_->resume(); }
request_impl &request::impl() const { return *impl_; }
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,116 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_client_request_impl.h"
#include "asio_client_stream.h"
#include "asio_client_session_impl.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
request_impl::request_impl() : strm_(nullptr), header_buffer_size_(0) {}
void request_impl::write_trailer(header_map h) {
auto sess = strm_->session();
sess->write_trailer(*strm_, std::move(h));
}
void request_impl::cancel(uint32_t error_code) {
auto sess = strm_->session();
sess->cancel(*strm_, error_code);
}
void request_impl::on_response(response_cb cb) { response_cb_ = std::move(cb); }
void request_impl::call_on_response(response &res) {
if (response_cb_) {
response_cb_(res);
}
}
void request_impl::on_push(request_cb cb) { push_request_cb_ = std::move(cb); }
void request_impl::call_on_push(request &push_req) {
if (push_request_cb_) {
push_request_cb_(push_req);
}
};
void request_impl::on_close(close_cb cb) { close_cb_ = std::move(cb); }
void request_impl::call_on_close(uint32_t error_code) {
if (close_cb_) {
close_cb_(error_code);
}
}
void request_impl::on_read(generator_cb cb) { generator_cb_ = std::move(cb); }
generator_cb::result_type request_impl::call_on_read(uint8_t *buf,
std::size_t len,
uint32_t *data_flags) {
if (generator_cb_) {
return generator_cb_(buf, len, data_flags);
}
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
return 0;
}
void request_impl::resume() {
auto sess = strm_->session();
sess->resume(*strm_);
}
void request_impl::header(header_map h) { header_ = std::move(h); }
header_map &request_impl::header() { return header_; }
const header_map &request_impl::header() const { return header_; }
void request_impl::stream(class stream *strm) { strm_ = strm; }
void request_impl::uri(uri_ref uri) { uri_ = std::move(uri); }
const uri_ref &request_impl::uri() const { return uri_; }
uri_ref &request_impl::uri() { return uri_; }
void request_impl::method(std::string s) { method_ = std::move(s); }
const std::string &request_impl::method() const { return method_; }
size_t request_impl::header_buffer_size() const { return header_buffer_size_; }
void request_impl::update_header_buffer_size(size_t len) {
header_buffer_size_ += len;
}
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,97 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_CLIENT_REQUEST_IMPL_H
#define ASIO_CLIENT_REQUEST_IMPL_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_client.h>
namespace nghttp2 {
namespace asio_http2 {
namespace client {
class response;
class stream;
class request_impl {
public:
request_impl();
request_impl(const request_impl &) = delete;
request_impl &operator=(const request_impl &) = delete;
void write_trailer(header_map h);
void cancel(uint32_t error_code);
void on_response(response_cb cb);
void call_on_response(response &res);
void on_push(request_cb cb);
void call_on_push(request &push_req);
void on_close(close_cb cb);
void call_on_close(uint32_t error_code);
void on_read(generator_cb cb);
generator_cb::result_type call_on_read(uint8_t *buf, std::size_t len,
uint32_t *data_flags);
void resume();
void header(header_map h);
header_map &header();
const header_map &header() const;
void stream(class stream *strm);
void uri(uri_ref uri);
const uri_ref &uri() const;
uri_ref &uri();
void method(std::string s);
const std::string &method() const;
size_t header_buffer_size() const;
void update_header_buffer_size(size_t len);
private:
header_map header_;
response_cb response_cb_;
request_cb push_request_cb_;
close_cb close_cb_;
generator_cb generator_cb_;
class stream *strm_;
uri_ref uri_;
std::string method_;
size_t header_buffer_size_;
};
} // namespace client
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_CLIENT_REQUEST_IMPL_H

View File

@ -1,53 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_client.h>
#include "asio_client_response_impl.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
response::response() : impl_(std::make_unique<response_impl>()) {}
response::~response() {}
void response::on_data(data_cb cb) const { impl_->on_data(std::move(cb)); }
int response::status_code() const { return impl_->status_code(); }
int64_t response::content_length() const { return impl_->content_length(); }
const header_map &response::header() const { return impl_->header(); }
response_impl &response::impl() const { return *impl_; }
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,64 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_client_response_impl.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
response_impl::response_impl()
: content_length_(-1), header_buffer_size_(0), status_code_(0) {}
void response_impl::on_data(data_cb cb) { data_cb_ = std::move(cb); }
void response_impl::call_on_data(const uint8_t *data, std::size_t len) {
if (data_cb_) {
data_cb_(data, len);
}
}
void response_impl::status_code(int sc) { status_code_ = sc; }
int response_impl::status_code() const { return status_code_; }
void response_impl::content_length(int64_t n) { content_length_ = n; }
int64_t response_impl::content_length() const { return content_length_; }
header_map &response_impl::header() { return header_; }
const header_map &response_impl::header() const { return header_; }
size_t response_impl::header_buffer_size() const { return header_buffer_size_; }
void response_impl::update_header_buffer_size(size_t len) {
header_buffer_size_ += len;
}
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,73 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_CLIENT_RESPONSE_IMPL_H
#define ASIO_CLIENT_RESPONSE_IMPL_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_client.h>
namespace nghttp2 {
namespace asio_http2 {
namespace client {
class response_impl {
public:
response_impl();
response_impl(const response_impl &) = delete;
response_impl &operator=(const response_impl &) = delete;
void on_data(data_cb cb);
void call_on_data(const uint8_t *data, std::size_t len);
void status_code(int sc);
int status_code() const;
void content_length(int64_t n);
int64_t content_length() const;
header_map &header();
const header_map &header() const;
size_t header_buffer_size() const;
void update_header_buffer_size(size_t len);
private:
data_cb data_cb_;
header_map header_;
int64_t content_length_;
size_t header_buffer_size_;
int status_code_;
};
} // namespace client
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_CLIENT_RESPONSE_IMPL_H

View File

@ -1,161 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_client.h>
#include "asio_client_session_tcp_impl.h"
#include "asio_client_session_tls_impl.h"
#include "asio_common.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
using boost::asio::ip::tcp;
session::session(boost::asio::io_service &io_service, const std::string &host,
const std::string &service)
: impl_(std::make_shared<session_tcp_impl>(
io_service, host, service, boost::posix_time::seconds(60))) {
impl_->start_resolve(host, service);
}
session::session(boost::asio::io_service &io_service,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host, const std::string &service)
: impl_(std::make_shared<session_tcp_impl>(
io_service, local_endpoint, host, service,
boost::posix_time::seconds(60))) {
impl_->start_resolve(host, service);
}
session::session(boost::asio::io_service &io_service, const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout)
: impl_(std::make_shared<session_tcp_impl>(io_service, host, service,
connect_timeout)) {
impl_->start_resolve(host, service);
}
session::session(boost::asio::io_service &io_service,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host, const std::string &service,
const boost::posix_time::time_duration &connect_timeout)
: impl_(std::make_shared<session_tcp_impl>(io_service, local_endpoint, host,
service, connect_timeout)) {
impl_->start_resolve(host, service);
}
session::session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_ctx, const std::string &host,
const std::string &service)
: impl_(std::make_shared<session_tls_impl>(
io_service, tls_ctx, host, service, boost::posix_time::seconds(60))) {
impl_->start_resolve(host, service);
}
session::session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_ctx, const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout)
: impl_(std::make_shared<session_tls_impl>(io_service, tls_ctx, host,
service, connect_timeout)) {
impl_->start_resolve(host, service);
}
session::~session() {}
session::session(session &&other) noexcept : impl_(std::move(other.impl_)) {}
session &session::operator=(session &&other) noexcept {
if (this == &other) {
return *this;
}
impl_ = std::move(other.impl_);
return *this;
}
void session::on_connect(connect_cb cb) const {
impl_->on_connect(std::move(cb));
}
void session::on_error(error_cb cb) const { impl_->on_error(std::move(cb)); }
void session::shutdown() const { impl_->shutdown(); }
boost::asio::io_service &session::io_service() const {
return impl_->io_service();
}
const request *session::submit(boost::system::error_code &ec,
const std::string &method,
const std::string &uri, header_map h,
priority_spec prio) const {
return impl_->submit(ec, method, uri, generator_cb(), std::move(h),
std::move(prio));
}
const request *session::submit(boost::system::error_code &ec,
const std::string &method,
const std::string &uri, std::string data,
header_map h, priority_spec prio) const {
return impl_->submit(ec, method, uri, string_generator(std::move(data)),
std::move(h), std::move(prio));
}
const request *session::submit(boost::system::error_code &ec,
const std::string &method,
const std::string &uri, generator_cb cb,
header_map h, priority_spec prio) const {
return impl_->submit(ec, method, uri, std::move(cb), std::move(h),
std::move(prio));
}
void session::read_timeout(const boost::posix_time::time_duration &t) {
impl_->read_timeout(t);
}
priority_spec::priority_spec(const int32_t stream_id, const int32_t weight,
const bool exclusive)
: valid_(true) {
nghttp2_priority_spec_init(&spec_, stream_id, weight, exclusive);
}
const nghttp2_priority_spec *priority_spec::get() const {
if (!valid_) {
return nullptr;
}
return &spec_;
}
bool priority_spec::valid() const { return valid_; }
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,759 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_client_session_impl.h"
#include <iostream>
#include "asio_client_stream.h"
#include "asio_client_request_impl.h"
#include "asio_client_response_impl.h"
#include "asio_common.h"
#include "template.h"
#include "util.h"
#include "http2.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
session_impl::session_impl(
boost::asio::io_service &io_service,
const boost::posix_time::time_duration &connect_timeout)
: wblen_(0),
io_service_(io_service),
resolver_(io_service),
deadline_(io_service),
connect_timeout_(connect_timeout),
read_timeout_(boost::posix_time::seconds(60)),
ping_(io_service),
session_(nullptr),
data_pending_(nullptr),
data_pendinglen_(0),
writing_(false),
inside_callback_(false),
stopped_(false) {}
session_impl::~session_impl() {
// finish up all active stream
for (auto &p : streams_) {
auto &strm = p.second;
auto &req = strm->request().impl();
req.call_on_close(NGHTTP2_INTERNAL_ERROR);
}
nghttp2_session_del(session_);
}
void session_impl::start_resolve(const std::string &host,
const std::string &service) {
deadline_.expires_from_now(connect_timeout_);
auto self = shared_from_this();
resolver_.async_resolve({host, service},
[self](const boost::system::error_code &ec,
tcp::resolver::iterator endpoint_it) {
if (ec) {
self->not_connected(ec);
return;
}
self->start_connect(endpoint_it);
});
deadline_.async_wait(std::bind(&session_impl::handle_deadline, self));
}
void session_impl::handle_deadline() {
if (stopped_) {
return;
}
if (deadline_.expires_at() <=
boost::asio::deadline_timer::traits_type::now()) {
call_error_cb(boost::asio::error::timed_out);
stop();
deadline_.expires_at(boost::posix_time::pos_infin);
return;
}
deadline_.async_wait(
std::bind(&session_impl::handle_deadline, this->shared_from_this()));
}
void handle_ping2(const boost::system::error_code &ec, int) {}
void session_impl::start_ping() {
ping_.expires_from_now(boost::posix_time::seconds(30));
ping_.async_wait(std::bind(&session_impl::handle_ping, shared_from_this(),
std::placeholders::_1));
}
void session_impl::handle_ping(const boost::system::error_code &ec) {
if (stopped_ || ec == boost::asio::error::operation_aborted ||
!streams_.empty()) {
return;
}
nghttp2_submit_ping(session_, NGHTTP2_FLAG_NONE, nullptr);
signal_write();
start_ping();
}
void session_impl::connected(tcp::resolver::iterator endpoint_it) {
if (!setup_session()) {
return;
}
socket().set_option(boost::asio::ip::tcp::no_delay(true));
do_write();
do_read();
start_ping();
auto &connect_cb = on_connect();
if (connect_cb) {
connect_cb(endpoint_it);
}
}
void session_impl::not_connected(const boost::system::error_code &ec) {
call_error_cb(ec);
stop();
}
void session_impl::on_connect(connect_cb cb) { connect_cb_ = std::move(cb); }
void session_impl::on_error(error_cb cb) { error_cb_ = std::move(cb); }
const connect_cb &session_impl::on_connect() const { return connect_cb_; }
const error_cb &session_impl::on_error() const { return error_cb_; }
void session_impl::call_error_cb(const boost::system::error_code &ec) {
if (stopped_) {
return;
}
auto &error_cb = on_error();
if (!error_cb) {
return;
}
error_cb(ec);
}
namespace {
int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data) {
if (frame->hd.type != NGHTTP2_PUSH_PROMISE) {
return 0;
}
auto sess = static_cast<session_impl *>(user_data);
sess->create_push_stream(frame->push_promise.promised_stream_id);
return 0;
}
} // namespace
namespace {
int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen, uint8_t flags,
void *user_data) {
auto sess = static_cast<session_impl *>(user_data);
stream *strm;
switch (frame->hd.type) {
case NGHTTP2_HEADERS: {
strm = sess->find_stream(frame->hd.stream_id);
if (!strm) {
return 0;
}
// ignore trailers
if (frame->headers.cat == NGHTTP2_HCAT_HEADERS &&
!strm->expect_final_response()) {
return 0;
}
auto token = http2::lookup_token(name, namelen);
auto &res = strm->response().impl();
if (token == http2::HD__STATUS) {
res.status_code(util::parse_uint(value, valuelen));
} else {
if (res.header_buffer_size() + namelen + valuelen > 64_k) {
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR);
break;
}
res.update_header_buffer_size(namelen + valuelen);
if (token == http2::HD_CONTENT_LENGTH) {
res.content_length(util::parse_uint(value, valuelen));
}
res.header().emplace(
std::string(name, name + namelen),
header_value{std::string(value, value + valuelen),
(flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0});
}
break;
}
case NGHTTP2_PUSH_PROMISE: {
strm = sess->find_stream(frame->push_promise.promised_stream_id);
if (!strm) {
return 0;
}
auto &req = strm->request().impl();
auto &uri = req.uri();
switch (http2::lookup_token(name, namelen)) {
case http2::HD__METHOD:
req.method(std::string(value, value + valuelen));
break;
case http2::HD__SCHEME:
uri.scheme.assign(value, value + valuelen);
break;
case http2::HD__PATH:
split_path(uri, value, value + valuelen);
break;
case http2::HD__AUTHORITY:
uri.host.assign(value, value + valuelen);
break;
case http2::HD_HOST:
if (uri.host.empty()) {
uri.host.assign(value, value + valuelen);
}
// fall through
default:
if (req.header_buffer_size() + namelen + valuelen > 64_k) {
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE,
frame->hd.stream_id, NGHTTP2_INTERNAL_ERROR);
break;
}
req.update_header_buffer_size(namelen + valuelen);
req.header().emplace(
std::string(name, name + namelen),
header_value{std::string(value, value + valuelen),
(flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0});
}
break;
}
default:
return 0;
}
return 0;
}
} // namespace
namespace {
int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
void *user_data) {
auto sess = static_cast<session_impl *>(user_data);
auto strm = sess->find_stream(frame->hd.stream_id);
switch (frame->hd.type) {
case NGHTTP2_DATA: {
if (!strm) {
return 0;
}
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
strm->response().impl().call_on_data(nullptr, 0);
}
break;
}
case NGHTTP2_HEADERS: {
if (!strm) {
return 0;
}
// ignore trailers
if (frame->headers.cat == NGHTTP2_HCAT_HEADERS &&
!strm->expect_final_response()) {
return 0;
}
if (strm->expect_final_response()) {
// wait for final response
return 0;
}
auto &req = strm->request().impl();
req.call_on_response(strm->response());
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
strm->response().impl().call_on_data(nullptr, 0);
}
break;
}
case NGHTTP2_PUSH_PROMISE: {
if (!strm) {
return 0;
}
auto push_strm = sess->find_stream(frame->push_promise.promised_stream_id);
if (!push_strm) {
return 0;
}
strm->request().impl().call_on_push(push_strm->request());
break;
}
}
return 0;
}
} // namespace
namespace {
int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
auto sess = static_cast<session_impl *>(user_data);
auto strm = sess->find_stream(stream_id);
if (!strm) {
return 0;
}
auto &res = strm->response().impl();
res.call_on_data(data, len);
return 0;
}
} // namespace
namespace {
int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, void *user_data) {
auto sess = static_cast<session_impl *>(user_data);
auto strm = sess->pop_stream(stream_id);
if (!strm) {
return 0;
}
strm->request().impl().call_on_close(error_code);
return 0;
}
} // namespace
bool session_impl::setup_session() {
nghttp2_session_callbacks *callbacks;
nghttp2_session_callbacks_new(&callbacks);
auto cb_del = defer(nghttp2_session_callbacks_del, callbacks);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
auto rv = nghttp2_session_client_new(&session_, callbacks, this);
if (rv != 0) {
call_error_cb(make_error_code(static_cast<nghttp2_error>(rv)));
return false;
}
const uint32_t window_size = 256_m;
std::array<nghttp2_settings_entry, 2> iv{
{{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100},
// typically client is just a *sink* and just process data as
// much as possible. Use large window size by default.
{NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE, window_size}}};
nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, iv.data(), iv.size());
// increase connection window size up to window_size
nghttp2_session_set_local_window_size(session_, NGHTTP2_FLAG_NONE, 0,
window_size);
return true;
}
int session_impl::write_trailer(stream &strm, header_map h) {
int rv;
auto nva = std::vector<nghttp2_nv>();
nva.reserve(h.size());
for (auto &hd : h) {
nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value,
hd.second.sensitive));
}
rv = nghttp2_submit_trailer(session_, strm.stream_id(), nva.data(),
nva.size());
if (rv != 0) {
return -1;
}
signal_write();
return 0;
}
void session_impl::cancel(stream &strm, uint32_t error_code) {
if (stopped_) {
return;
}
nghttp2_submit_rst_stream(session_, NGHTTP2_FLAG_NONE, strm.stream_id(),
error_code);
signal_write();
}
void session_impl::resume(stream &strm) {
if (stopped_) {
return;
}
nghttp2_session_resume_data(session_, strm.stream_id());
signal_write();
}
stream *session_impl::find_stream(int32_t stream_id) {
auto it = streams_.find(stream_id);
if (it == std::end(streams_)) {
return nullptr;
}
return (*it).second.get();
}
std::unique_ptr<stream> session_impl::pop_stream(int32_t stream_id) {
auto it = streams_.find(stream_id);
if (it == std::end(streams_)) {
return nullptr;
}
auto strm = std::move((*it).second);
streams_.erase(it);
if (streams_.empty()) {
start_ping();
}
return strm;
}
stream *session_impl::create_push_stream(int32_t stream_id) {
auto strm = create_stream();
strm->stream_id(stream_id);
auto p = streams_.emplace(stream_id, std::move(strm));
assert(p.second);
ping_.cancel();
return (*p.first).second.get();
}
std::unique_ptr<stream> session_impl::create_stream() {
return std::make_unique<stream>(this);
}
const request *session_impl::submit(boost::system::error_code &ec,
const std::string &method,
const std::string &uri, generator_cb cb,
header_map h, priority_spec prio) {
ec.clear();
if (stopped_) {
ec = make_error_code(static_cast<nghttp2_error>(NGHTTP2_INTERNAL_ERROR));
return nullptr;
}
http_parser_url u{};
// TODO Handle CONNECT method
if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) {
ec = make_error_code(boost::system::errc::invalid_argument);
return nullptr;
}
if ((u.field_set & (1 << UF_SCHEMA)) == 0 ||
(u.field_set & (1 << UF_HOST)) == 0) {
ec = make_error_code(boost::system::errc::invalid_argument);
return nullptr;
}
auto strm = create_stream();
auto &req = strm->request().impl();
auto &uref = req.uri();
http2::copy_url_component(uref.scheme, &u, UF_SCHEMA, uri.c_str());
http2::copy_url_component(uref.host, &u, UF_HOST, uri.c_str());
http2::copy_url_component(uref.raw_path, &u, UF_PATH, uri.c_str());
http2::copy_url_component(uref.raw_query, &u, UF_QUERY, uri.c_str());
if (util::ipv6_numeric_addr(uref.host.c_str())) {
uref.host = "[" + uref.host;
uref.host += ']';
}
if (u.field_set & (1 << UF_PORT)) {
uref.host += ':';
uref.host += util::utos(u.port);
}
if (uref.raw_path.empty()) {
uref.raw_path = "/";
}
uref.path = percent_decode(uref.raw_path);
auto path = uref.raw_path;
if (u.field_set & (1 << UF_QUERY)) {
path += '?';
path += uref.raw_query;
}
auto nva = std::vector<nghttp2_nv>();
nva.reserve(4 + h.size());
nva.push_back(http2::make_nv_ls(":method", method));
nva.push_back(http2::make_nv_ls(":scheme", uref.scheme));
nva.push_back(http2::make_nv_ls(":path", path));
nva.push_back(http2::make_nv_ls(":authority", uref.host));
for (auto &kv : h) {
nva.push_back(
http2::make_nv(kv.first, kv.second.value, kv.second.sensitive));
}
req.header(std::move(h));
nghttp2_data_provider *prdptr = nullptr;
nghttp2_data_provider prd;
if (cb) {
strm->request().impl().on_read(std::move(cb));
prd.source.ptr = strm.get();
prd.read_callback = [](nghttp2_session *session, int32_t stream_id,
uint8_t *buf, size_t length, uint32_t *data_flags,
nghttp2_data_source *source,
void *user_data) -> ssize_t {
auto strm = static_cast<stream *>(source->ptr);
return strm->request().impl().call_on_read(buf, length, data_flags);
};
prdptr = &prd;
}
auto stream_id = nghttp2_submit_request(session_, prio.get(), nva.data(),
nva.size(), prdptr, strm.get());
if (stream_id < 0) {
ec = make_error_code(static_cast<nghttp2_error>(stream_id));
return nullptr;
}
signal_write();
strm->stream_id(stream_id);
auto p = streams_.emplace(stream_id, std::move(strm));
assert(p.second);
ping_.cancel();
return &(*p.first).second->request();
}
void session_impl::shutdown() {
if (stopped_) {
return;
}
nghttp2_session_terminate_session(session_, NGHTTP2_NO_ERROR);
signal_write();
}
boost::asio::io_service &session_impl::io_service() { return io_service_; }
void session_impl::signal_write() {
if (!inside_callback_) {
do_write();
}
}
bool session_impl::should_stop() const {
return !writing_ && !nghttp2_session_want_read(session_) &&
!nghttp2_session_want_write(session_);
}
namespace {
struct callback_guard {
callback_guard(session_impl &sess) : sess(sess) { sess.enter_callback(); }
~callback_guard() { sess.leave_callback(); }
session_impl &sess;
};
} // namespace
void session_impl::enter_callback() {
assert(!inside_callback_);
inside_callback_ = true;
}
void session_impl::leave_callback() {
assert(inside_callback_);
inside_callback_ = false;
}
void session_impl::do_read() {
if (stopped_) {
return;
}
deadline_.expires_from_now(read_timeout_);
auto self = this->shared_from_this();
read_socket([self](const boost::system::error_code &ec,
std::size_t bytes_transferred) {
if (ec) {
if (!self->should_stop()) {
self->call_error_cb(ec);
}
self->stop();
return;
}
{
callback_guard cg(*self);
auto rv = nghttp2_session_mem_recv(self->session_, self->rb_.data(),
bytes_transferred);
if (rv != static_cast<ssize_t>(bytes_transferred)) {
self->call_error_cb(make_error_code(
static_cast<nghttp2_error>(rv < 0 ? rv : NGHTTP2_ERR_PROTO)));
self->stop();
return;
}
}
self->do_write();
if (self->should_stop()) {
self->stop();
return;
}
self->do_read();
});
}
void session_impl::do_write() {
if (stopped_) {
return;
}
if (writing_) {
return;
}
if (data_pending_) {
std::copy_n(data_pending_, data_pendinglen_, std::begin(wb_) + wblen_);
wblen_ += data_pendinglen_;
data_pending_ = nullptr;
data_pendinglen_ = 0;
}
{
callback_guard cg(*this);
for (;;) {
const uint8_t *data;
auto n = nghttp2_session_mem_send(session_, &data);
if (n < 0) {
call_error_cb(make_error_code(static_cast<nghttp2_error>(n)));
stop();
return;
}
if (n == 0) {
break;
}
if (wblen_ + n > wb_.size()) {
data_pending_ = data;
data_pendinglen_ = n;
break;
}
std::copy_n(data, n, std::begin(wb_) + wblen_);
wblen_ += n;
}
}
if (wblen_ == 0) {
if (should_stop()) {
stop();
}
return;
}
writing_ = true;
// Reset read deadline here, because normally client is sending
// something, it does not expect timeout while doing it.
deadline_.expires_from_now(read_timeout_);
auto self = this->shared_from_this();
write_socket([self](const boost::system::error_code &ec, std::size_t n) {
if (ec) {
self->call_error_cb(ec);
self->stop();
return;
}
self->wblen_ = 0;
self->writing_ = false;
self->do_write();
});
}
void session_impl::stop() {
if (stopped_) {
return;
}
shutdown_socket();
deadline_.cancel();
ping_.cancel();
stopped_ = true;
}
bool session_impl::stopped() const { return stopped_; }
void session_impl::read_timeout(const boost::posix_time::time_duration &t) {
read_timeout_ = t;
}
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,143 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_CLIENT_SESSION_IMPL_H
#define ASIO_CLIENT_SESSION_IMPL_H
#include "nghttp2_config.h"
#include <boost/array.hpp>
#include <nghttp2/asio_http2_client.h>
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
class stream;
using boost::asio::ip::tcp;
class session_impl : public std::enable_shared_from_this<session_impl> {
public:
session_impl(boost::asio::io_service &io_service,
const boost::posix_time::time_duration &connect_timeout);
virtual ~session_impl();
void start_resolve(const std::string &host, const std::string &service);
void connected(tcp::resolver::iterator endpoint_it);
void not_connected(const boost::system::error_code &ec);
void on_connect(connect_cb cb);
void on_error(error_cb cb);
const connect_cb &on_connect() const;
const error_cb &on_error() const;
int write_trailer(stream &strm, header_map h);
void cancel(stream &strm, uint32_t error_code);
void resume(stream &strm);
std::unique_ptr<stream> create_stream();
std::unique_ptr<stream> pop_stream(int32_t stream_id);
stream *create_push_stream(int32_t stream_id);
stream *find_stream(int32_t stream_id);
const request *submit(boost::system::error_code &ec,
const std::string &method, const std::string &uri,
generator_cb cb, header_map h, priority_spec spec);
virtual void start_connect(tcp::resolver::iterator endpoint_it) = 0;
virtual tcp::socket &socket() = 0;
virtual void read_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h) = 0;
virtual void write_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h) = 0;
virtual void shutdown_socket() = 0;
void shutdown();
boost::asio::io_service &io_service();
void signal_write();
void enter_callback();
void leave_callback();
void do_read();
void do_write();
void read_timeout(const boost::posix_time::time_duration &t);
void stop();
bool stopped() const;
protected:
boost::array<uint8_t, 8_k> rb_;
boost::array<uint8_t, 64_k> wb_;
std::size_t wblen_;
private:
bool should_stop() const;
bool setup_session();
void call_error_cb(const boost::system::error_code &ec);
void handle_deadline();
void start_ping();
void handle_ping(const boost::system::error_code &ec);
boost::asio::io_service &io_service_;
tcp::resolver resolver_;
std::map<int32_t, std::unique_ptr<stream>> streams_;
connect_cb connect_cb_;
error_cb error_cb_;
boost::asio::deadline_timer deadline_;
boost::posix_time::time_duration connect_timeout_;
boost::posix_time::time_duration read_timeout_;
boost::asio::deadline_timer ping_;
nghttp2_session *session_;
const uint8_t *data_pending_;
std::size_t data_pendinglen_;
bool writing_;
bool inside_callback_;
bool stopped_;
};
} // namespace client
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_CLIENT_SESSION_IMPL_H

View File

@ -1,87 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_client_session_tcp_impl.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
session_tcp_impl::session_tcp_impl(
boost::asio::io_service &io_service, const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout)
: session_impl(io_service, connect_timeout), socket_(io_service) {}
session_tcp_impl::session_tcp_impl(
boost::asio::io_service &io_service,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host, const std::string &service,
const boost::posix_time::time_duration &connect_timeout)
: session_impl(io_service, connect_timeout), socket_(io_service) {
socket_.open(local_endpoint.protocol());
boost::asio::socket_base::reuse_address option(true);
socket_.set_option(option);
socket_.bind(local_endpoint);
}
session_tcp_impl::~session_tcp_impl() {}
void session_tcp_impl::start_connect(tcp::resolver::iterator endpoint_it) {
auto self = shared_from_this();
socket_.async_connect(
*endpoint_it, [self, endpoint_it](const boost::system::error_code &ec) {
if (self->stopped()) {
return;
}
if (ec) {
self->not_connected(ec);
return;
}
self->connected(endpoint_it);
});
}
tcp::socket &session_tcp_impl::socket() { return socket_; }
void session_tcp_impl::read_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)> h) {
socket_.async_read_some(boost::asio::buffer(rb_), h);
}
void session_tcp_impl::write_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)> h) {
boost::asio::async_write(socket_, boost::asio::buffer(wb_, wblen_), h);
}
void session_tcp_impl::shutdown_socket() {
boost::system::error_code ignored_ec;
socket_.close(ignored_ec);
}
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,67 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_CLIENT_SESSION_TCP_IMPL_H
#define ASIO_CLIENT_SESSION_TCP_IMPL_H
#include "asio_client_session_impl.h"
#include <nghttp2/asio_http2_client.h>
namespace nghttp2 {
namespace asio_http2 {
namespace client {
using boost::asio::ip::tcp;
class session_tcp_impl : public session_impl {
public:
session_tcp_impl(boost::asio::io_service &io_service, const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout);
session_tcp_impl(boost::asio::io_service &io_service,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host, const std::string &service,
const boost::posix_time::time_duration &connect_timeout);
virtual ~session_tcp_impl();
virtual void start_connect(tcp::resolver::iterator endpoint_it);
virtual tcp::socket &socket();
virtual void read_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h);
virtual void write_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h);
virtual void shutdown_socket();
private:
tcp::socket socket_;
};
} // namespace client
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_CLIENT_SESSION_TCP_IMPL_H

View File

@ -1,106 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_client_session_tls_impl.h"
#include "asio_common.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
session_tls_impl::session_tls_impl(
boost::asio::io_service &io_service, boost::asio::ssl::context &tls_ctx,
const std::string &host, const std::string &service,
const boost::posix_time::time_duration &connect_timeout)
: session_impl(io_service, connect_timeout), socket_(io_service, tls_ctx) {
// this callback setting is no effect is
// ssl::context::set_verify_mode(boost::asio::ssl::verify_peer) is
// not used, which is what we want.
socket_.set_verify_callback(boost::asio::ssl::rfc2818_verification(host));
auto ssl = socket_.native_handle();
if (!util::numeric_host(host.c_str())) {
SSL_set_tlsext_host_name(ssl, host.c_str());
}
}
session_tls_impl::~session_tls_impl() {}
void session_tls_impl::start_connect(tcp::resolver::iterator endpoint_it) {
auto self = std::static_pointer_cast<session_tls_impl>(shared_from_this());
boost::asio::async_connect(
socket(), endpoint_it,
[self](const boost::system::error_code &ec,
tcp::resolver::iterator endpoint_it) {
if (self->stopped()) {
return;
}
if (ec) {
self->not_connected(ec);
return;
}
self->socket_.async_handshake(
boost::asio::ssl::stream_base::client,
[self, endpoint_it](const boost::system::error_code &ec) {
if (self->stopped()) {
return;
}
if (ec) {
self->not_connected(ec);
return;
}
if (!tls_h2_negotiated(self->socket_)) {
self->not_connected(make_error_code(
NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED));
return;
}
self->connected(endpoint_it);
});
});
}
tcp::socket &session_tls_impl::socket() { return socket_.next_layer(); }
void session_tls_impl::read_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)> h) {
socket_.async_read_some(boost::asio::buffer(rb_), h);
}
void session_tls_impl::write_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)> h) {
boost::asio::async_write(socket_, boost::asio::buffer(wb_, wblen_), h);
}
void session_tls_impl::shutdown_socket() {
boost::system::error_code ignored_ec;
socket_.lowest_layer().close(ignored_ec);
}
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,66 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_CLIENT_SESSION_TLS_IMPL_H
#define ASIO_CLIENT_SESSION_TLS_IMPL_H
#include "asio_client_session_impl.h"
#include <nghttp2/asio_http2_client.h>
namespace nghttp2 {
namespace asio_http2 {
namespace client {
using boost::asio::ip::tcp;
using ssl_socket = boost::asio::ssl::stream<tcp::socket>;
class session_tls_impl : public session_impl {
public:
session_tls_impl(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_ctx, const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout);
virtual ~session_tls_impl();
virtual void start_connect(tcp::resolver::iterator endpoint_it);
virtual tcp::socket &socket();
virtual void read_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h);
virtual void write_socket(
std::function<void(const boost::system::error_code &ec, std::size_t n)>
h);
virtual void shutdown_socket();
private:
ssl_socket socket_;
};
} // namespace client
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_CLIENT_SESSION_TLS_IMPL_H

View File

@ -1,59 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_client_stream.h"
#include "asio_client_request_impl.h"
#include "asio_client_response_impl.h"
#include "asio_client_session_impl.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
stream::stream(session_impl *sess) : sess_(sess), stream_id_(0) {
request_.impl().stream(this);
}
void stream::stream_id(int32_t stream_id) { stream_id_ = stream_id; }
int32_t stream::stream_id() const { return stream_id_; }
class request &stream::request() {
return request_;
}
class response &stream::response() {
return response_;
}
session_impl *stream::session() const { return sess_; }
bool stream::expect_final_response() const {
return response_.status_code() / 100 == 1;
}
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,68 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_CLIENT_STREAM_H
#define ASIO_CLIENT_STREAM_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_client.h>
namespace nghttp2 {
namespace asio_http2 {
namespace client {
class request;
class response;
class session_impl;
class stream {
public:
stream(session_impl *sess);
stream(const stream &) = delete;
stream &operator=(const stream &) = delete;
void stream_id(int32_t stream_id);
int32_t stream_id() const;
class request &request();
class response &response();
session_impl *session() const;
bool expect_final_response() const;
private:
nghttp2::asio_http2::client::request request_;
nghttp2::asio_http2::client::response response_;
session_impl *sess_;
uint32_t stream_id_;
};
} // namespace client
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_CLIENT_STREAM_H

View File

@ -1,74 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_client_tls_context.h"
#include <openssl/ssl.h>
#include <boost/asio/ssl.hpp>
#include "tls.h"
#include "util.h"
namespace nghttp2 {
namespace asio_http2 {
namespace client {
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
int client_select_next_proto_cb(SSL *ssl, unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
if (!util::select_h2(const_cast<const unsigned char **>(out), outlen, in,
inlen)) {
return SSL_TLSEXT_ERR_NOACK;
}
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
boost::system::error_code
configure_tls_context(boost::system::error_code &ec,
boost::asio::ssl::context &tls_ctx) {
ec.clear();
auto ctx = tls_ctx.native_handle();
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_proto_select_cb(ctx, client_select_next_proto_cb, nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
auto proto_list = util::get_default_alpn();
SSL_CTX_set_alpn_protos(ctx, proto_list.data(), proto_list.size());
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return ec;
}
} // namespace client
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,32 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_CLIENT_TLS_CONTEXT_H
#define ASIO_CLIENT_TLS_CONTEXT_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_client.h>
#endif // ASIO_CLIENT_TLS_CONTEXT_H

View File

@ -1,197 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_common.h"
#include <fcntl.h>
#include <memory>
#include "util.h"
#include "template.h"
#include "http2.h"
namespace nghttp2 {
namespace asio_http2 {
class nghttp2_category_impl : public boost::system::error_category {
public:
const char *name() const noexcept { return "nghttp2"; }
std::string message(int ev) const { return nghttp2_strerror(ev); }
};
const boost::system::error_category &nghttp2_category() noexcept {
static nghttp2_category_impl cat;
return cat;
}
boost::system::error_code make_error_code(nghttp2_error ev) {
return boost::system::error_code(static_cast<int>(ev), nghttp2_category());
}
class nghttp2_asio_category_impl : public boost::system::error_category {
public:
const char *name() const noexcept { return "nghttp2_asio"; }
std::string message(int ev) const {
switch (ev) {
case NGHTTP2_ASIO_ERR_NO_ERROR:
return "no error";
case NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED:
return "tls: no application protocol negotiated";
default:
return "unknown";
}
}
};
const boost::system::error_category &nghttp2_asio_category() noexcept {
static nghttp2_asio_category_impl cat;
return cat;
}
boost::system::error_code make_error_code(nghttp2_asio_error ev) {
return boost::system::error_code(static_cast<int>(ev),
nghttp2_asio_category());
}
generator_cb string_generator(std::string data) {
auto strio = std::make_shared<std::pair<std::string, size_t>>(std::move(data),
data.size());
return [strio](uint8_t *buf, size_t len, uint32_t *data_flags) {
auto &data = strio->first;
auto &left = strio->second;
auto n = std::min(len, left);
std::copy_n(data.c_str() + data.size() - left, n, buf);
left -= n;
if (left == 0) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
}
return n;
};
}
generator_cb deferred_generator() {
return [](uint8_t *buf, size_t len, uint32_t *data_flags) {
return NGHTTP2_ERR_DEFERRED;
};
}
template <typename F, typename... T>
std::shared_ptr<Defer<F, T...>> defer_shared(F &&f, T &&...t) {
return std::make_shared<Defer<F, T...>>(std::forward<F>(f),
std::forward<T>(t)...);
}
generator_cb file_generator(const std::string &path) {
auto fd = open(path.c_str(), O_RDONLY);
if (fd == -1) {
return generator_cb();
}
return file_generator_from_fd(fd);
}
generator_cb file_generator_from_fd(int fd) {
auto d = defer_shared(close, fd);
return [fd, d](uint8_t *buf, size_t len,
uint32_t *data_flags) -> generator_cb::result_type {
ssize_t n;
while ((n = read(fd, buf, len)) == -1 && errno == EINTR)
;
if (n == -1) {
return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
}
if (n == 0) {
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
}
return n;
};
}
bool check_path(const std::string &path) { return util::check_path(path); }
std::string percent_decode(const std::string &s) {
return util::percent_decode(std::begin(s), std::end(s));
}
std::string http_date(int64_t t) { return util::http_date(t); }
boost::system::error_code host_service_from_uri(boost::system::error_code &ec,
std::string &scheme,
std::string &host,
std::string &service,
const std::string &uri) {
ec.clear();
http_parser_url u{};
if (http_parser_parse_url(uri.c_str(), uri.size(), 0, &u) != 0) {
ec = make_error_code(boost::system::errc::invalid_argument);
return ec;
}
if ((u.field_set & (1 << UF_SCHEMA)) == 0 ||
(u.field_set & (1 << UF_HOST)) == 0) {
ec = make_error_code(boost::system::errc::invalid_argument);
return ec;
}
http2::copy_url_component(scheme, &u, UF_SCHEMA, uri.c_str());
http2::copy_url_component(host, &u, UF_HOST, uri.c_str());
if (u.field_set & (1 << UF_PORT)) {
http2::copy_url_component(service, &u, UF_PORT, uri.c_str());
} else {
service = scheme;
}
return ec;
}
bool tls_h2_negotiated(ssl_socket &socket) {
auto ssl = socket.native_handle();
const unsigned char *next_proto = nullptr;
unsigned int next_proto_len = 0;
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_get0_next_proto_negotiated(ssl, &next_proto, &next_proto_len);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
SSL_get0_alpn_selected(ssl, &next_proto, &next_proto_len);
}
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
if (next_proto == nullptr) {
return false;
}
return util::check_h2_is_selected(StringRef{next_proto, next_proto_len});
}
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,73 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_COMMON_H
#define ASIO_COMMON_H
#include "nghttp2_config.h"
#include <string>
#include <nghttp2/asio_http2.h>
#include "util.h"
namespace nghttp2 {
namespace asio_http2 {
boost::system::error_code make_error_code(nghttp2_error ev);
boost::system::error_code make_error_code(nghttp2_asio_error ev);
generator_cb string_generator(std::string data);
// Returns generator_cb, which just returns NGHTTP2_ERR_DEFERRED
generator_cb deferred_generator();
template <typename InputIt>
void split_path(uri_ref &dst, InputIt first, InputIt last) {
auto path_last = std::find(first, last, '?');
InputIt query_first;
if (path_last == last) {
query_first = path_last = last;
} else {
query_first = path_last + 1;
}
dst.path = util::percent_decode(first, path_last);
dst.raw_path.assign(first, path_last);
dst.raw_query.assign(query_first, last);
}
using boost::asio::ip::tcp;
using ssl_socket = boost::asio::ssl::stream<tcp::socket>;
bool tls_h2_negotiated(ssl_socket &socket);
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_COMMON_H

View File

@ -1,107 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// io_service_pool.cpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "asio_io_service_pool.h"
namespace nghttp2 {
namespace asio_http2 {
io_service_pool::io_service_pool(std::size_t pool_size) : next_io_service_(0) {
if (pool_size == 0) {
throw std::runtime_error("io_service_pool size is 0");
}
// Give all the io_services work to do so that their run() functions will not
// exit until they are explicitly stopped.
for (std::size_t i = 0; i < pool_size; ++i) {
auto io_service = std::make_shared<boost::asio::io_service>();
auto work = std::make_shared<boost::asio::io_service::work>(*io_service);
io_services_.push_back(io_service);
work_.push_back(work);
}
}
void io_service_pool::run(bool asynchronous) {
// Create a pool of threads to run all of the io_services.
for (std::size_t i = 0; i < io_services_.size(); ++i) {
futures_.push_back(std::async(std::launch::async,
(size_t(boost::asio::io_service::*)(void)) &
boost::asio::io_service::run,
io_services_[i]));
}
if (!asynchronous) {
join();
}
}
void io_service_pool::join() {
// Wait for all threads in the pool to exit.
for (auto &fut : futures_) {
fut.get();
}
}
void io_service_pool::force_stop() {
// Explicitly stop all io_services.
for (auto &iosv : io_services_) {
iosv->stop();
}
}
void io_service_pool::stop() {
// Destroy all work objects to signals end of work
work_.clear();
}
boost::asio::io_service &io_service_pool::get_io_service() {
// Use a round-robin scheme to choose the next io_service to use.
auto &io_service = *io_services_[next_io_service_];
++next_io_service_;
if (next_io_service_ == io_services_.size()) {
next_io_service_ = 0;
}
return io_service;
}
const std::vector<std::shared_ptr<boost::asio::io_service>> &
io_service_pool::io_services() const {
return io_services_;
}
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,98 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// io_service_pool.hpp
// ~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_IO_SERVICE_POOL_H
#define ASIO_IO_SERVICE_POOL_H
#include "nghttp2_config.h"
#include <vector>
#include <memory>
#include <future>
#include <boost/noncopyable.hpp>
#include <boost/thread.hpp>
#include <nghttp2/asio_http2.h>
namespace nghttp2 {
namespace asio_http2 {
/// A pool of io_service objects.
class io_service_pool : private boost::noncopyable {
public:
/// Construct the io_service pool.
explicit io_service_pool(std::size_t pool_size);
/// Run all io_service objects in the pool.
void run(bool asynchronous = false);
/// Stop all io_service objects in the pool.
void force_stop();
/// Destroy all work objects to signals end of work
void stop();
/// Join on all io_service objects in the pool.
void join();
/// Get an io_service to use.
boost::asio::io_service &get_io_service();
/// Get access to all io_service objects.
const std::vector<std::shared_ptr<boost::asio::io_service>> &
io_services() const;
private:
/// The pool of io_services.
std::vector<std::shared_ptr<boost::asio::io_service>> io_services_;
/// The work that keeps the io_services running.
std::vector<std::shared_ptr<boost::asio::io_service::work>> work_;
/// The next io_service to use for a connection.
std::size_t next_io_service_;
/// Futures to all the io_service objects
std::vector<std::future<std::size_t>> futures_;
};
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_IO_SERVICE_POOL_H

View File

@ -1,214 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// server.cpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "asio_server.h"
#include "asio_server_connection.h"
#include "asio_common.h"
#include "util.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
server::server(std::size_t io_service_pool_size,
const boost::posix_time::time_duration &tls_handshake_timeout,
const boost::posix_time::time_duration &read_timeout)
: io_service_pool_(io_service_pool_size),
tls_handshake_timeout_(tls_handshake_timeout),
read_timeout_(read_timeout) {}
boost::system::error_code
server::listen_and_serve(boost::system::error_code &ec,
boost::asio::ssl::context *tls_context,
const std::string &address, const std::string &port,
int backlog, serve_mux &mux, bool asynchronous) {
ec.clear();
if (bind_and_listen(ec, address, port, backlog)) {
return ec;
}
for (auto &acceptor : acceptors_) {
if (tls_context) {
start_accept(*tls_context, acceptor, mux);
} else {
start_accept(acceptor, mux);
}
}
io_service_pool_.run(asynchronous);
return ec;
}
boost::system::error_code server::bind_and_listen(boost::system::error_code &ec,
const std::string &address,
const std::string &port,
int backlog) {
// Open the acceptor with the option to reuse the address (i.e.
// SO_REUSEADDR).
tcp::resolver resolver(io_service_pool_.get_io_service());
tcp::resolver::query query(address, port);
auto it = resolver.resolve(query, ec);
if (ec) {
return ec;
}
for (; it != tcp::resolver::iterator(); ++it) {
tcp::endpoint endpoint = *it;
auto acceptor = tcp::acceptor(io_service_pool_.get_io_service());
if (acceptor.open(endpoint.protocol(), ec)) {
continue;
}
acceptor.set_option(tcp::acceptor::reuse_address(true));
if (acceptor.bind(endpoint, ec)) {
continue;
}
if (acceptor.listen(
backlog == -1 ? boost::asio::socket_base::max_connections : backlog,
ec)) {
continue;
}
acceptors_.push_back(std::move(acceptor));
}
if (acceptors_.empty()) {
return ec;
}
// ec could have some errors since we may have failed to bind some
// interfaces.
ec.clear();
return ec;
}
void server::start_accept(boost::asio::ssl::context &tls_context,
tcp::acceptor &acceptor, serve_mux &mux) {
if (!acceptor.is_open()) {
return;
}
auto new_connection = std::make_shared<connection<ssl_socket>>(
mux, tls_handshake_timeout_, read_timeout_,
io_service_pool_.get_io_service(), tls_context);
acceptor.async_accept(
new_connection->socket().lowest_layer(),
[this, &tls_context, &acceptor, &mux,
new_connection](const boost::system::error_code &e) {
if (!e) {
new_connection->socket().lowest_layer().set_option(
tcp::no_delay(true));
new_connection->start_tls_handshake_deadline();
new_connection->socket().async_handshake(
boost::asio::ssl::stream_base::server,
[new_connection](const boost::system::error_code &e) {
if (e) {
new_connection->stop();
return;
}
if (!tls_h2_negotiated(new_connection->socket())) {
new_connection->stop();
return;
}
new_connection->start();
});
}
start_accept(tls_context, acceptor, mux);
});
}
void server::start_accept(tcp::acceptor &acceptor, serve_mux &mux) {
if (!acceptor.is_open()) {
return;
}
auto new_connection = std::make_shared<connection<tcp::socket>>(
mux, tls_handshake_timeout_, read_timeout_,
io_service_pool_.get_io_service());
acceptor.async_accept(
new_connection->socket(), [this, &acceptor, &mux, new_connection](
const boost::system::error_code &e) {
if (!e) {
new_connection->socket().set_option(tcp::no_delay(true));
new_connection->start_read_deadline();
new_connection->start();
}
if (acceptor.is_open()) {
start_accept(acceptor, mux);
}
});
}
void server::stop() {
for (auto &acceptor : acceptors_) {
acceptor.close();
}
io_service_pool_.stop();
}
void server::join() { io_service_pool_.join(); }
const std::vector<std::shared_ptr<boost::asio::io_service>> &
server::io_services() const {
return io_service_pool_.io_services();
}
const std::vector<int> server::ports() const {
auto ports = std::vector<int>(acceptors_.size());
auto index = 0;
for (const auto &acceptor : acceptors_) {
ports[index++] = acceptor.local_endpoint().port();
}
return ports;
}
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,117 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// server.hpp
// ~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_SERVER_H
#define ASIO_SERVER_H
#include "nghttp2_config.h"
#include <string>
#include <vector>
#include <memory>
#include <boost/noncopyable.hpp>
#include <nghttp2/asio_http2_server.h>
#include "asio_io_service_pool.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
class serve_mux;
using boost::asio::ip::tcp;
using ssl_socket = boost::asio::ssl::stream<tcp::socket>;
class server : private boost::noncopyable {
public:
explicit server(std::size_t io_service_pool_size,
const boost::posix_time::time_duration &tls_handshake_timeout,
const boost::posix_time::time_duration &read_timeout);
boost::system::error_code
listen_and_serve(boost::system::error_code &ec,
boost::asio::ssl::context *tls_context,
const std::string &address, const std::string &port,
int backlog, serve_mux &mux, bool asynchronous = false);
void join();
void stop();
/// Get access to all io_service objects.
const std::vector<std::shared_ptr<boost::asio::io_service>> &
io_services() const;
/// Returns a vector with all the acceptors ports in use.
const std::vector<int> ports() const;
private:
/// Initiate an asynchronous accept operation.
void start_accept(tcp::acceptor &acceptor, serve_mux &mux);
/// Same as above but with tls_context
void start_accept(boost::asio::ssl::context &tls_context,
tcp::acceptor &acceptor, serve_mux &mux);
/// Resolves address and bind socket to the resolved addresses.
boost::system::error_code bind_and_listen(boost::system::error_code &ec,
const std::string &address,
const std::string &port,
int backlog);
/// The pool of io_service objects used to perform asynchronous
/// operations.
io_service_pool io_service_pool_;
/// Acceptor used to listen for incoming connections.
std::vector<tcp::acceptor> acceptors_;
std::unique_ptr<boost::asio::ssl::context> ssl_ctx_;
boost::posix_time::time_duration tls_handshake_timeout_;
boost::posix_time::time_duration read_timeout_;
};
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_SERVER_H

View File

@ -1,253 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
// We wrote this code based on the original code which has the
// following license:
//
// connection.hpp
// ~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef ASIO_SERVER_CONNECTION_H
#define ASIO_SERVER_CONNECTION_H
#include "nghttp2_config.h"
#include <memory>
#include <boost/noncopyable.hpp>
#include <boost/array.hpp>
#include <nghttp2/asio_http2_server.h>
#include "asio_server_http2_handler.h"
#include "asio_server_serve_mux.h"
#include "util.h"
#include "template.h"
#if BOOST_VERSION >= 107000
# define GET_IO_SERVICE(s) \
((boost::asio::io_context &)(s).get_executor().context())
#else
# define GET_IO_SERVICE(s) ((s).get_io_service())
#endif
namespace nghttp2 {
namespace asio_http2 {
namespace server {
/// Represents a single connection from a client.
template <typename socket_type>
class connection : public std::enable_shared_from_this<connection<socket_type>>,
private boost::noncopyable {
public:
/// Construct a connection with the given io_service.
template <typename... SocketArgs>
explicit connection(
serve_mux &mux,
const boost::posix_time::time_duration &tls_handshake_timeout,
const boost::posix_time::time_duration &read_timeout,
SocketArgs &&...args)
: socket_(std::forward<SocketArgs>(args)...),
mux_(mux),
deadline_(GET_IO_SERVICE(socket_)),
tls_handshake_timeout_(tls_handshake_timeout),
read_timeout_(read_timeout),
writing_(false),
stopped_(false) {}
/// Start the first asynchronous operation for the connection.
void start() {
boost::system::error_code ec;
handler_ = std::make_shared<http2_handler>(
GET_IO_SERVICE(socket_), socket_.lowest_layer().remote_endpoint(ec),
[this]() { do_write(); }, mux_);
if (handler_->start() != 0) {
stop();
return;
}
do_read();
}
socket_type &socket() { return socket_; }
void start_tls_handshake_deadline() {
deadline_.expires_from_now(tls_handshake_timeout_);
deadline_.async_wait(
std::bind(&connection::handle_deadline, this->shared_from_this()));
}
void start_read_deadline() {
deadline_.expires_from_now(read_timeout_);
deadline_.async_wait(
std::bind(&connection::handle_deadline, this->shared_from_this()));
}
void handle_deadline() {
if (stopped_) {
return;
}
if (deadline_.expires_at() <=
boost::asio::deadline_timer::traits_type::now()) {
stop();
deadline_.expires_at(boost::posix_time::pos_infin);
return;
}
deadline_.async_wait(
std::bind(&connection::handle_deadline, this->shared_from_this()));
}
void do_read() {
auto self = this->shared_from_this();
deadline_.expires_from_now(read_timeout_);
socket_.async_read_some(
boost::asio::buffer(buffer_),
[this, self](const boost::system::error_code &e,
std::size_t bytes_transferred) {
if (e) {
stop();
return;
}
if (handler_->on_read(buffer_, bytes_transferred) != 0) {
stop();
return;
}
do_write();
if (!writing_ && handler_->should_stop()) {
stop();
return;
}
do_read();
// If an error occurs then no new asynchronous operations are
// started. This means that all shared_ptr references to the
// connection object will disappear and the object will be
// destroyed automatically after this handler returns. The
// connection class's destructor closes the socket.
});
}
void do_write() {
auto self = this->shared_from_this();
if (writing_) {
return;
}
int rv;
std::size_t nwrite;
rv = handler_->on_write(outbuf_, nwrite);
if (rv != 0) {
stop();
return;
}
if (nwrite == 0) {
if (handler_->should_stop()) {
stop();
}
return;
}
writing_ = true;
// Reset read deadline here, because normally client is sending
// something, it does not expect timeout while doing it.
deadline_.expires_from_now(read_timeout_);
boost::asio::async_write(
socket_, boost::asio::buffer(outbuf_, nwrite),
[this, self](const boost::system::error_code &e, std::size_t) {
if (e) {
stop();
return;
}
writing_ = false;
do_write();
});
// No new asynchronous operations are started. This means that all
// shared_ptr references to the connection object will disappear and
// the object will be destroyed automatically after this handler
// returns. The connection class's destructor closes the socket.
}
void stop() {
if (stopped_) {
return;
}
stopped_ = true;
boost::system::error_code ignored_ec;
socket_.lowest_layer().close(ignored_ec);
deadline_.cancel();
}
private:
socket_type socket_;
serve_mux &mux_;
std::shared_ptr<http2_handler> handler_;
/// Buffer for incoming data.
boost::array<uint8_t, 8_k> buffer_;
boost::array<uint8_t, 64_k> outbuf_;
boost::asio::deadline_timer deadline_;
boost::posix_time::time_duration tls_handshake_timeout_;
boost::posix_time::time_duration read_timeout_;
bool writing_;
bool stopped_;
};
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_SERVER_CONNECTION_H

View File

@ -1,99 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
#include "asio_server_http2_impl.h"
#include "asio_server.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
http2::http2() : impl_(std::make_unique<http2_impl>()) {}
http2::~http2() {}
http2::http2(http2 &&other) noexcept : impl_(std::move(other.impl_)) {}
http2 &http2::operator=(http2 &&other) noexcept {
if (this == &other) {
return *this;
}
impl_ = std::move(other.impl_);
return *this;
}
boost::system::error_code http2::listen_and_serve(boost::system::error_code &ec,
const std::string &address,
const std::string &port,
bool asynchronous) {
return impl_->listen_and_serve(ec, nullptr, address, port, asynchronous);
}
boost::system::error_code http2::listen_and_serve(
boost::system::error_code &ec, boost::asio::ssl::context &tls_context,
const std::string &address, const std::string &port, bool asynchronous) {
return impl_->listen_and_serve(ec, &tls_context, address, port, asynchronous);
}
void http2::num_threads(size_t num_threads) { impl_->num_threads(num_threads); }
void http2::backlog(int backlog) { impl_->backlog(backlog); }
void http2::tls_handshake_timeout(const boost::posix_time::time_duration &t) {
impl_->tls_handshake_timeout(t);
}
void http2::read_timeout(const boost::posix_time::time_duration &t) {
impl_->read_timeout(t);
}
bool http2::handle(std::string pattern, request_cb cb) {
return impl_->handle(std::move(pattern), std::move(cb));
}
void http2::stop() { impl_->stop(); }
void http2::join() { return impl_->join(); }
const std::vector<std::shared_ptr<boost::asio::io_service>> &
http2::io_services() const {
return impl_->io_services();
}
std::vector<int> http2::ports() const { return impl_->ports(); }
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,497 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_server_http2_handler.h"
#include <iostream>
#include "asio_common.h"
#include "asio_server_serve_mux.h"
#include "asio_server_stream.h"
#include "asio_server_request_impl.h"
#include "asio_server_response_impl.h"
#include "http2.h"
#include "util.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
namespace {
int stream_error(nghttp2_session *session, int32_t stream_id,
uint32_t error_code) {
return nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, stream_id,
error_code);
}
} // namespace
namespace {
int on_begin_headers_callback(nghttp2_session *session,
const nghttp2_frame *frame, void *user_data) {
auto handler = static_cast<http2_handler *>(user_data);
if (frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
return 0;
}
handler->create_stream(frame->hd.stream_id);
return 0;
}
} // namespace
namespace {
int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
const uint8_t *name, size_t namelen,
const uint8_t *value, size_t valuelen, uint8_t flags,
void *user_data) {
auto handler = static_cast<http2_handler *>(user_data);
auto stream_id = frame->hd.stream_id;
if (frame->hd.type != NGHTTP2_HEADERS ||
frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
return 0;
}
auto strm = handler->find_stream(stream_id);
if (!strm) {
return 0;
}
auto &req = strm->request().impl();
auto &uref = req.uri();
switch (nghttp2::http2::lookup_token(name, namelen)) {
case nghttp2::http2::HD__METHOD:
req.method(std::string(value, value + valuelen));
break;
case nghttp2::http2::HD__SCHEME:
uref.scheme.assign(value, value + valuelen);
break;
case nghttp2::http2::HD__AUTHORITY:
uref.host.assign(value, value + valuelen);
break;
case nghttp2::http2::HD__PATH:
split_path(uref, value, value + valuelen);
break;
case nghttp2::http2::HD_HOST:
if (uref.host.empty()) {
uref.host.assign(value, value + valuelen);
}
// fall through
default:
if (req.header_buffer_size() + namelen + valuelen > 64_k) {
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id,
NGHTTP2_INTERNAL_ERROR);
break;
}
req.update_header_buffer_size(namelen + valuelen);
req.header().emplace(std::string(name, name + namelen),
header_value{std::string(value, value + valuelen),
(flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0});
}
return 0;
}
} // namespace
namespace {
int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
void *user_data) {
auto handler = static_cast<http2_handler *>(user_data);
auto strm = handler->find_stream(frame->hd.stream_id);
switch (frame->hd.type) {
case NGHTTP2_DATA:
if (!strm) {
break;
}
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
strm->request().impl().call_on_data(nullptr, 0);
}
break;
case NGHTTP2_HEADERS: {
if (!strm || frame->headers.cat != NGHTTP2_HCAT_REQUEST) {
break;
}
auto &req = strm->request().impl();
req.remote_endpoint(handler->remote_endpoint());
handler->call_on_request(*strm);
if (frame->hd.flags & NGHTTP2_FLAG_END_STREAM) {
strm->request().impl().call_on_data(nullptr, 0);
}
break;
}
}
return 0;
}
} // namespace
namespace {
int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t stream_id, const uint8_t *data,
size_t len, void *user_data) {
auto handler = static_cast<http2_handler *>(user_data);
auto strm = handler->find_stream(stream_id);
if (!strm) {
return 0;
}
strm->request().impl().call_on_data(data, len);
return 0;
}
} // namespace
namespace {
int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
uint32_t error_code, void *user_data) {
auto handler = static_cast<http2_handler *>(user_data);
auto strm = handler->find_stream(stream_id);
if (!strm) {
return 0;
}
strm->response().impl().call_on_close(error_code);
handler->close_stream(stream_id);
return 0;
}
} // namespace
namespace {
int on_frame_send_callback(nghttp2_session *session, const nghttp2_frame *frame,
void *user_data) {
auto handler = static_cast<http2_handler *>(user_data);
if (frame->hd.type != NGHTTP2_PUSH_PROMISE) {
return 0;
}
auto strm = handler->find_stream(frame->push_promise.promised_stream_id);
if (!strm) {
return 0;
}
auto &res = strm->response().impl();
res.push_promise_sent();
return 0;
}
} // namespace
namespace {
int on_frame_not_send_callback(nghttp2_session *session,
const nghttp2_frame *frame, int lib_error_code,
void *user_data) {
if (frame->hd.type != NGHTTP2_HEADERS) {
return 0;
}
// Issue RST_STREAM so that stream does not hang around.
nghttp2_submit_rst_stream(session, NGHTTP2_FLAG_NONE, frame->hd.stream_id,
NGHTTP2_INTERNAL_ERROR);
return 0;
}
} // namespace
http2_handler::http2_handler(boost::asio::io_service &io_service,
boost::asio::ip::tcp::endpoint ep,
connection_write writefun, serve_mux &mux)
: writefun_(writefun),
mux_(mux),
io_service_(io_service),
remote_ep_(ep),
session_(nullptr),
buf_(nullptr),
buflen_(0),
inside_callback_(false),
write_signaled_(false),
tstamp_cached_(time(nullptr)),
formatted_date_(util::http_date(tstamp_cached_)) {}
http2_handler::~http2_handler() {
for (auto &p : streams_) {
auto &strm = p.second;
strm->response().impl().call_on_close(NGHTTP2_INTERNAL_ERROR);
}
nghttp2_session_del(session_);
}
const std::string &http2_handler::http_date() {
auto t = time(nullptr);
if (t != tstamp_cached_) {
tstamp_cached_ = t;
formatted_date_ = util::http_date(t);
}
return formatted_date_;
}
int http2_handler::start() {
int rv;
nghttp2_session_callbacks *callbacks;
rv = nghttp2_session_callbacks_new(&callbacks);
if (rv != 0) {
return -1;
}
auto cb_del = defer(nghttp2_session_callbacks_del, callbacks);
nghttp2_session_callbacks_set_on_begin_headers_callback(
callbacks, on_begin_headers_callback);
nghttp2_session_callbacks_set_on_header_callback(callbacks,
on_header_callback);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
on_frame_recv_callback);
nghttp2_session_callbacks_set_on_data_chunk_recv_callback(
callbacks, on_data_chunk_recv_callback);
nghttp2_session_callbacks_set_on_stream_close_callback(
callbacks, on_stream_close_callback);
nghttp2_session_callbacks_set_on_frame_send_callback(callbacks,
on_frame_send_callback);
nghttp2_session_callbacks_set_on_frame_not_send_callback(
callbacks, on_frame_not_send_callback);
rv = nghttp2_session_server_new(&session_, callbacks, this);
if (rv != 0) {
return -1;
}
nghttp2_settings_entry ent{NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, 100};
nghttp2_submit_settings(session_, NGHTTP2_FLAG_NONE, &ent, 1);
return 0;
}
stream *http2_handler::create_stream(int32_t stream_id) {
auto p =
streams_.emplace(stream_id, std::make_unique<stream>(this, stream_id));
assert(p.second);
return (*p.first).second.get();
}
void http2_handler::close_stream(int32_t stream_id) {
streams_.erase(stream_id);
}
stream *http2_handler::find_stream(int32_t stream_id) {
auto i = streams_.find(stream_id);
if (i == std::end(streams_)) {
return nullptr;
}
return (*i).second.get();
}
void http2_handler::call_on_request(stream &strm) {
auto cb = mux_.handler(strm.request().impl());
cb(strm.request(), strm.response());
}
bool http2_handler::should_stop() const {
return !nghttp2_session_want_read(session_) &&
!nghttp2_session_want_write(session_);
}
int http2_handler::start_response(stream &strm) {
int rv;
auto &res = strm.response().impl();
auto &header = res.header();
auto nva = std::vector<nghttp2_nv>();
nva.reserve(2 + header.size());
auto status = util::utos(res.status_code());
auto date = http_date();
nva.push_back(nghttp2::http2::make_nv_ls(":status", status));
nva.push_back(nghttp2::http2::make_nv_ls("date", date));
for (auto &hd : header) {
nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value,
hd.second.sensitive));
}
nghttp2_data_provider *prd_ptr = nullptr, prd;
auto &req = strm.request().impl();
if (::nghttp2::http2::expect_response_body(req.method(), res.status_code())) {
prd.source.ptr = &strm;
prd.read_callback = [](nghttp2_session *session, int32_t stream_id,
uint8_t *buf, size_t length, uint32_t *data_flags,
nghttp2_data_source *source,
void *user_data) -> ssize_t {
auto &strm = *static_cast<stream *>(source->ptr);
return strm.response().impl().call_read(buf, length, data_flags);
};
prd_ptr = &prd;
}
rv = nghttp2_submit_response(session_, strm.get_stream_id(), nva.data(),
nva.size(), prd_ptr);
if (rv != 0) {
return -1;
}
signal_write();
return 0;
}
int http2_handler::submit_trailer(stream &strm, header_map h) {
int rv;
auto nva = std::vector<nghttp2_nv>();
nva.reserve(h.size());
for (auto &hd : h) {
nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value,
hd.second.sensitive));
}
rv = nghttp2_submit_trailer(session_, strm.get_stream_id(), nva.data(),
nva.size());
if (rv != 0) {
return -1;
}
signal_write();
return 0;
}
void http2_handler::enter_callback() {
assert(!inside_callback_);
inside_callback_ = true;
}
void http2_handler::leave_callback() {
assert(inside_callback_);
inside_callback_ = false;
}
void http2_handler::stream_error(int32_t stream_id, uint32_t error_code) {
::nghttp2::asio_http2::server::stream_error(session_, stream_id, error_code);
signal_write();
}
void http2_handler::signal_write() {
if (!inside_callback_ && !write_signaled_) {
write_signaled_ = true;
auto self = shared_from_this();
io_service_.post([self]() { self->initiate_write(); });
}
}
void http2_handler::initiate_write() {
write_signaled_ = false;
writefun_();
}
void http2_handler::resume(stream &strm) {
nghttp2_session_resume_data(session_, strm.get_stream_id());
signal_write();
}
response *http2_handler::push_promise(boost::system::error_code &ec,
stream &strm, std::string method,
std::string raw_path_query,
header_map h) {
int rv;
ec.clear();
auto &req = strm.request().impl();
auto nva = std::vector<nghttp2_nv>();
nva.reserve(4 + h.size());
nva.push_back(nghttp2::http2::make_nv_ls(":method", method));
nva.push_back(nghttp2::http2::make_nv_ls(":scheme", req.uri().scheme));
nva.push_back(nghttp2::http2::make_nv_ls(":authority", req.uri().host));
nva.push_back(nghttp2::http2::make_nv_ls(":path", raw_path_query));
for (auto &hd : h) {
nva.push_back(nghttp2::http2::make_nv(hd.first, hd.second.value,
hd.second.sensitive));
}
rv = nghttp2_submit_push_promise(session_, NGHTTP2_FLAG_NONE,
strm.get_stream_id(), nva.data(), nva.size(),
nullptr);
if (rv < 0) {
ec = make_error_code(static_cast<nghttp2_error>(rv));
return nullptr;
}
auto promised_strm = create_stream(rv);
auto &promised_req = promised_strm->request().impl();
promised_req.header(std::move(h));
promised_req.method(std::move(method));
auto &uref = promised_req.uri();
uref.scheme = req.uri().scheme;
uref.host = req.uri().host;
split_path(uref, std::begin(raw_path_query), std::end(raw_path_query));
auto &promised_res = promised_strm->response().impl();
promised_res.pushed(true);
signal_write();
return &promised_strm->response();
}
boost::asio::io_service &http2_handler::io_service() { return io_service_; }
const boost::asio::ip::tcp::endpoint &http2_handler::remote_endpoint() {
return remote_ep_;
}
callback_guard::callback_guard(http2_handler &h) : handler(h) {
handler.enter_callback();
}
callback_guard::~callback_guard() { handler.leave_callback(); }
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,174 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_SERVER_HTTP2_HANDLER_H
#define ASIO_SERVER_HTTP2_HANDLER_H
#include "nghttp2_config.h"
#include <map>
#include <functional>
#include <string>
#include <boost/array.hpp>
#include <nghttp2/asio_http2_server.h>
namespace nghttp2 {
namespace asio_http2 {
namespace server {
class http2_handler;
class stream;
class serve_mux;
struct callback_guard {
callback_guard(http2_handler &h);
~callback_guard();
http2_handler &handler;
};
using connection_write = std::function<void(void)>;
class http2_handler : public std::enable_shared_from_this<http2_handler> {
public:
http2_handler(boost::asio::io_service &io_service,
boost::asio::ip::tcp::endpoint ep, connection_write writefun,
serve_mux &mux);
~http2_handler();
int start();
stream *create_stream(int32_t stream_id);
void close_stream(int32_t stream_id);
stream *find_stream(int32_t stream_id);
void call_on_request(stream &s);
bool should_stop() const;
int start_response(stream &s);
int submit_trailer(stream &s, header_map h);
void stream_error(int32_t stream_id, uint32_t error_code);
void initiate_write();
void enter_callback();
void leave_callback();
void resume(stream &s);
response *push_promise(boost::system::error_code &ec, stream &s,
std::string method, std::string raw_path_query,
header_map h);
void signal_write();
boost::asio::io_service &io_service();
const boost::asio::ip::tcp::endpoint &remote_endpoint();
const std::string &http_date();
template <size_t N>
int on_read(const boost::array<uint8_t, N> &buffer, std::size_t len) {
callback_guard cg(*this);
int rv;
rv = nghttp2_session_mem_recv(session_, buffer.data(), len);
if (rv < 0) {
return -1;
}
return 0;
}
template <size_t N>
int on_write(boost::array<uint8_t, N> &buffer, std::size_t &len) {
callback_guard cg(*this);
len = 0;
if (buf_) {
std::copy_n(buf_, buflen_, std::begin(buffer));
len += buflen_;
buf_ = nullptr;
buflen_ = 0;
}
for (;;) {
const uint8_t *data;
auto nread = nghttp2_session_mem_send(session_, &data);
if (nread < 0) {
return -1;
}
if (nread == 0) {
break;
}
if (len + nread > buffer.size()) {
buf_ = data;
buflen_ = nread;
break;
}
std::copy_n(data, nread, std::begin(buffer) + len);
len += nread;
}
return 0;
}
private:
std::map<int32_t, std::shared_ptr<stream>> streams_;
connection_write writefun_;
serve_mux &mux_;
boost::asio::io_service &io_service_;
boost::asio::ip::tcp::endpoint remote_ep_;
nghttp2_session *session_;
const uint8_t *buf_;
std::size_t buflen_;
bool inside_callback_;
// true if we have pending on_write call. This avoids repeated call
// of io_service::post.
bool write_signaled_;
time_t tstamp_cached_;
std::string formatted_date_;
};
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_SERVER_HTTP2_HANDLER_H

View File

@ -1,87 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_server_http2_impl.h"
#include <openssl/ssl.h>
#include "asio_server.h"
#include "util.h"
#include "tls.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
http2_impl::http2_impl()
: num_threads_(1),
backlog_(-1),
tls_handshake_timeout_(boost::posix_time::seconds(60)),
read_timeout_(boost::posix_time::seconds(60)) {}
boost::system::error_code http2_impl::listen_and_serve(
boost::system::error_code &ec, boost::asio::ssl::context *tls_context,
const std::string &address, const std::string &port, bool asynchronous) {
server_.reset(
new server(num_threads_, tls_handshake_timeout_, read_timeout_));
return server_->listen_and_serve(ec, tls_context, address, port, backlog_,
mux_, asynchronous);
}
void http2_impl::num_threads(size_t num_threads) { num_threads_ = num_threads; }
void http2_impl::backlog(int backlog) { backlog_ = backlog; }
void http2_impl::tls_handshake_timeout(
const boost::posix_time::time_duration &t) {
tls_handshake_timeout_ = t;
}
void http2_impl::read_timeout(const boost::posix_time::time_duration &t) {
read_timeout_ = t;
}
bool http2_impl::handle(std::string pattern, request_cb cb) {
return mux_.handle(std::move(pattern), std::move(cb));
}
void http2_impl::stop() { return server_->stop(); }
void http2_impl::join() { return server_->join(); }
const std::vector<std::shared_ptr<boost::asio::io_service>> &
http2_impl::io_services() const {
return server_->io_services();
}
std::vector<int> http2_impl::ports() const { return server_->ports(); }
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,74 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_SERVER_HTTP2_IMPL_H
#define ASIO_SERVER_HTTP2_IMPL_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
#include "asio_server_serve_mux.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
class server;
class http2_impl {
public:
http2_impl();
boost::system::error_code listen_and_serve(
boost::system::error_code &ec, boost::asio::ssl::context *tls_context,
const std::string &address, const std::string &port, bool asynchronous);
void num_threads(size_t num_threads);
void backlog(int backlog);
void tls_handshake_timeout(const boost::posix_time::time_duration &t);
void read_timeout(const boost::posix_time::time_duration &t);
bool handle(std::string pattern, request_cb cb);
void stop();
void join();
const std::vector<std::shared_ptr<boost::asio::io_service>> &
io_services() const;
std::vector<int> ports() const;
private:
std::unique_ptr<server> server_;
std::size_t num_threads_;
int backlog_;
serve_mux mux_;
boost::posix_time::time_duration tls_handshake_timeout_;
boost::posix_time::time_duration read_timeout_;
};
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_SERVER_HTTP2_IMPL_H

View File

@ -1,59 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
#include "asio_server_request_impl.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
request::request() : impl_(std::make_unique<request_impl>()) {}
request::~request() {}
const header_map &request::header() const { return impl_->header(); }
const std::string &request::method() const { return impl_->method(); }
const uri_ref &request::uri() const { return impl_->uri(); }
void request::on_data(data_cb cb) const {
return impl_->on_data(std::move(cb));
}
request_impl &request::impl() const { return *impl_; }
const boost::asio::ip::tcp::endpoint &request::remote_endpoint() const {
return impl_->remote_endpoint();
}
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,90 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_server_request_handler.h"
#include "util.h"
#include "http2.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
namespace {
std::string create_html(int status_code) {
BlockAllocator balloc(1024, 1024);
std::string res;
res.reserve(512);
auto status_string = ::nghttp2::http2::stringify_status(balloc, status_code);
auto reason_phrase = ::nghttp2::http2::get_reason_phrase(status_code);
res += R"(<!DOCTYPE html><html lang="en"><title>)";
res += status_string;
res += ' ';
res += reason_phrase;
res += "</title><body><h1>";
res += status_string;
res += ' ';
res += reason_phrase;
res += "</h1></body></html>";
return res;
}
} // namespace
request_cb redirect_handler(int status_code, std::string uri) {
return [status_code, uri](const request &req, const response &res) {
header_map h;
h.emplace("location", header_value{std::move(uri)});
std::string html;
if (req.method() == "GET") {
html = create_html(status_code);
}
h.emplace("content-length", header_value{util::utos(html.size())});
res.write_head(status_code, std::move(h));
res.end(std::move(html));
};
}
request_cb status_handler(int status_code) {
return [status_code](const request &req, const response &res) {
if (!::nghttp2::http2::expect_response_body(status_code)) {
res.write_head(status_code);
res.end();
return;
}
// we supply content-length for HEAD request, but body will not be
// sent.
auto html = create_html(status_code);
header_map h;
h.emplace("content-length", header_value{util::utos(html.size())});
h.emplace("content-type", header_value{"text/html; charset=utf-8"});
res.write_head(status_code, std::move(h));
res.end(std::move(html));
};
}
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,32 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_SERVER_REQUEST_HANDLER_H
#define ASIO_SERVER_REQUEST_HANDLER_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
#endif // ASIO_SERVER_REQUEST_HANDLER_H

View File

@ -1,73 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_server_request_impl.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
request_impl::request_impl() : strm_(nullptr), header_buffer_size_(0) {}
const header_map &request_impl::header() const { return header_; }
const std::string &request_impl::method() const { return method_; }
const uri_ref &request_impl::uri() const { return uri_; }
uri_ref &request_impl::uri() { return uri_; }
void request_impl::header(header_map h) { header_ = std::move(h); }
header_map &request_impl::header() { return header_; }
void request_impl::method(std::string arg) { method_ = std::move(arg); }
void request_impl::on_data(data_cb cb) { on_data_cb_ = std::move(cb); }
void request_impl::stream(class stream *s) { strm_ = s; }
void request_impl::call_on_data(const uint8_t *data, std::size_t len) {
if (on_data_cb_) {
on_data_cb_(data, len);
}
}
const boost::asio::ip::tcp::endpoint &request_impl::remote_endpoint() const {
return remote_ep_;
}
void request_impl::remote_endpoint(boost::asio::ip::tcp::endpoint ep) {
remote_ep_ = std::move(ep);
}
size_t request_impl::header_buffer_size() const { return header_buffer_size_; }
void request_impl::update_header_buffer_size(size_t len) {
header_buffer_size_ += len;
}
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,78 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_SERVER_REQUEST_IMPL_H
#define ASIO_SERVER_REQUEST_IMPL_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
#include <boost/asio/ip/tcp.hpp>
namespace nghttp2 {
namespace asio_http2 {
namespace server {
class stream;
class request_impl {
public:
request_impl();
void header(header_map h);
const header_map &header() const;
header_map &header();
void method(std::string method);
const std::string &method() const;
const uri_ref &uri() const;
uri_ref &uri();
void on_data(data_cb cb);
void stream(class stream *s);
void call_on_data(const uint8_t *data, std::size_t len);
const boost::asio::ip::tcp::endpoint &remote_endpoint() const;
void remote_endpoint(boost::asio::ip::tcp::endpoint ep);
size_t header_buffer_size() const;
void update_header_buffer_size(size_t len);
private:
class stream *strm_;
header_map header_;
std::string method_;
uri_ref uri_;
data_cb on_data_cb_;
boost::asio::ip::tcp::endpoint remote_ep_;
size_t header_buffer_size_;
};
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_SERVER_REQUEST_IMPL_H

View File

@ -1,75 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
#include "asio_server_response_impl.h"
#include "template.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
response::response() : impl_(std::make_unique<response_impl>()) {}
response::~response() {}
void response::write_head(unsigned int status_code, header_map h) const {
impl_->write_head(status_code, std::move(h));
}
void response::end(std::string data) const { impl_->end(std::move(data)); }
void response::end(generator_cb cb) const { impl_->end(std::move(cb)); }
void response::write_trailer(header_map h) const {
impl_->write_trailer(std::move(h));
}
void response::on_close(close_cb cb) const { impl_->on_close(std::move(cb)); }
void response::cancel(uint32_t error_code) const { impl_->cancel(error_code); }
const response *response::push(boost::system::error_code &ec,
std::string method, std::string path,
header_map h) const {
return impl_->push(ec, std::move(method), std::move(path), std::move(h));
}
void response::resume() const { impl_->resume(); }
unsigned int response::status_code() const { return impl_->status_code(); }
boost::asio::io_service &response::io_service() const {
return impl_->io_service();
}
response_impl &response::impl() const { return *impl_; }
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,166 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_server_response_impl.h"
#include "asio_server_stream.h"
#include "asio_server_request_impl.h"
#include "asio_server_http2_handler.h"
#include "asio_common.h"
#include "http2.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
response_impl::response_impl()
: strm_(nullptr),
generator_cb_(deferred_generator()),
status_code_(200),
state_(response_state::INITIAL),
pushed_(false),
push_promise_sent_(false) {}
unsigned int response_impl::status_code() const { return status_code_; }
void response_impl::write_head(unsigned int status_code, header_map h) {
if (state_ != response_state::INITIAL) {
return;
}
status_code_ = status_code;
header_ = std::move(h);
state_ = response_state::HEADER_DONE;
if (pushed_ && !push_promise_sent_) {
return;
}
start_response();
}
void response_impl::end(std::string data) {
end(string_generator(std::move(data)));
}
void response_impl::end(generator_cb cb) {
if (state_ == response_state::BODY_STARTED) {
return;
}
generator_cb_ = std::move(cb);
if (state_ == response_state::INITIAL) {
write_head(status_code_);
} else {
// generator_cb is changed, start writing in case it is deferred.
auto handler = strm_->handler();
handler->resume(*strm_);
}
state_ = response_state::BODY_STARTED;
}
void response_impl::write_trailer(header_map h) {
auto handler = strm_->handler();
handler->submit_trailer(*strm_, std::move(h));
}
void response_impl::start_response() {
auto handler = strm_->handler();
auto &req = strm_->request().impl();
if (!::nghttp2::http2::expect_response_body(req.method(), status_code_)) {
state_ = response_state::BODY_STARTED;
}
if (handler->start_response(*strm_) != 0) {
handler->stream_error(strm_->get_stream_id(), NGHTTP2_INTERNAL_ERROR);
return;
}
}
void response_impl::on_close(close_cb cb) { close_cb_ = std::move(cb); }
void response_impl::call_on_close(uint32_t error_code) {
if (close_cb_) {
close_cb_(error_code);
}
}
void response_impl::cancel(uint32_t error_code) {
auto handler = strm_->handler();
handler->stream_error(strm_->get_stream_id(), error_code);
}
response *response_impl::push(boost::system::error_code &ec, std::string method,
std::string raw_path_query, header_map h) const {
auto handler = strm_->handler();
return handler->push_promise(ec, *strm_, std::move(method),
std::move(raw_path_query), std::move(h));
}
void response_impl::resume() {
auto handler = strm_->handler();
handler->resume(*strm_);
}
boost::asio::io_service &response_impl::io_service() {
return strm_->handler()->io_service();
}
void response_impl::pushed(bool f) { pushed_ = f; }
void response_impl::push_promise_sent() {
if (push_promise_sent_) {
return;
}
push_promise_sent_ = true;
if (state_ == response_state::INITIAL) {
return;
}
start_response();
}
const header_map &response_impl::header() const { return header_; }
void response_impl::stream(class stream *s) { strm_ = s; }
generator_cb::result_type
response_impl::call_read(uint8_t *data, std::size_t len, uint32_t *data_flags) {
if (generator_cb_) {
return generator_cb_(data, len, data_flags);
}
*data_flags |= NGHTTP2_DATA_FLAG_EOF;
return 0;
}
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,92 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_SERVER_RESPONSE_IMPL_H
#define ASIO_SERVER_RESPONSE_IMPL_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
namespace nghttp2 {
namespace asio_http2 {
namespace server {
class stream;
enum class response_state {
INITIAL,
// response_impl::write_head() was called
HEADER_DONE,
// response_impl::end() was called
BODY_STARTED,
};
class response_impl {
public:
response_impl();
void write_head(unsigned int status_code, header_map h = header_map{});
void end(std::string data = "");
void end(generator_cb cb);
void write_trailer(header_map h);
void on_close(close_cb cb);
void resume();
void cancel(uint32_t error_code);
response *push(boost::system::error_code &ec, std::string method,
std::string raw_path_query, header_map) const;
boost::asio::io_service &io_service();
void start_response();
unsigned int status_code() const;
const header_map &header() const;
void pushed(bool f);
void push_promise_sent();
void stream(class stream *s);
generator_cb::result_type call_read(uint8_t *data, std::size_t len,
uint32_t *data_flags);
void call_on_close(uint32_t error_code);
private:
class stream *strm_;
header_map header_;
generator_cb generator_cb_;
close_cb close_cb_;
unsigned int status_code_;
response_state state_;
// true if this is pushed stream's response
bool pushed_;
// true if PUSH_PROMISE is sent if this is response of a pushed
// stream
bool push_promise_sent_;
};
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_SERVER_RESPONSE_IMPL_H

View File

@ -1,138 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_server_serve_mux.h"
#include "asio_server_request_impl.h"
#include "asio_server_request_handler.h"
#include "util.h"
#include "http2.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
bool serve_mux::handle(std::string pattern, request_cb cb) {
if (pattern.empty() || !cb) {
return false;
}
auto it = mux_.find(pattern);
if (it != std::end(mux_) && (*it).second.user_defined) {
return false;
}
// if pattern ends with '/' (e.g., /foo/), add implicit permanent
// redirect for '/foo'.
if (pattern.size() >= 2 && pattern.back() == '/') {
auto redirect_pattern = pattern.substr(0, pattern.size() - 1);
auto it = mux_.find(redirect_pattern);
if (it == std::end(mux_) || !(*it).second.user_defined) {
std::string path;
if (pattern[0] == '/') {
path = pattern;
} else {
// skip host part
path = pattern.substr(pattern.find('/'));
}
if (it == std::end(mux_)) {
mux_.emplace(std::move(redirect_pattern),
handler_entry{false,
redirect_handler(301, std::move(path)),
pattern});
} else {
(*it).second = handler_entry{
false, redirect_handler(301, std::move(path)), pattern};
}
}
}
mux_.emplace(pattern, handler_entry{true, std::move(cb), pattern});
return true;
}
request_cb serve_mux::handler(request_impl &req) const {
auto &path = req.uri().path;
if (req.method() != "CONNECT") {
auto clean_path = ::nghttp2::http2::path_join(StringRef{}, StringRef{},
StringRef{path}, StringRef{});
if (clean_path != path) {
auto new_uri = util::percent_encode_path(clean_path);
auto &uref = req.uri();
if (!uref.raw_query.empty()) {
new_uri += '?';
new_uri += uref.raw_query;
}
return redirect_handler(301, std::move(new_uri));
}
}
auto &host = req.uri().host;
auto cb = match(host + path);
if (cb) {
return cb;
}
cb = match(path);
if (cb) {
return cb;
}
return status_handler(404);
}
namespace {
bool path_match(const std::string &pattern, const std::string &path) {
if (pattern.back() != '/') {
return pattern == path;
}
return util::starts_with(path, pattern);
}
} // namespace
request_cb serve_mux::match(const std::string &path) const {
const handler_entry *ent = nullptr;
size_t best = 0;
for (auto &kv : mux_) {
auto &pattern = kv.first;
if (!path_match(pattern, path)) {
continue;
}
if (!ent || best < pattern.size()) {
best = pattern.size();
ent = &kv.second;
}
}
if (ent) {
return ent->cb;
}
return request_cb();
}
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,64 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_SERVER_SERVE_MUX_H
#define ASIO_SERVER_SERVE_MUX_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
namespace nghttp2 {
namespace asio_http2 {
namespace server {
class request_impl;
// port from go's ServeMux
struct handler_entry {
bool user_defined;
request_cb cb;
std::string pattern;
};
class serve_mux {
public:
bool handle(std::string pattern, request_cb cb);
request_cb handler(request_impl &req) const;
request_cb match(const std::string &path) const;
private:
std::map<std::string, handler_entry> mux_;
};
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_SERVER_SERVE_MUX_H

View File

@ -1,55 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_server_stream.h"
#include "asio_server_http2_handler.h"
#include "asio_server_request_impl.h"
#include "asio_server_response_impl.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
stream::stream(http2_handler *h, int32_t stream_id)
: handler_(h), stream_id_(stream_id) {
request_.impl().stream(this);
response_.impl().stream(this);
}
int32_t stream::get_stream_id() const { return stream_id_; }
class request &stream::request() {
return request_;
}
class response &stream::response() {
return response_;
}
http2_handler *stream::handler() const { return handler_; }
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,59 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_SERVER_STREAM_H
#define ASIO_SERVER_STREAM_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
namespace nghttp2 {
namespace asio_http2 {
namespace server {
class http2_handler;
class stream {
public:
stream(http2_handler *h, int32_t stream_id);
int32_t get_stream_id() const;
class request &request();
class response &response();
http2_handler *handler() const;
private:
http2_handler *handler_;
class request request_;
class response response_;
int32_t stream_id_;
};
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_SERVER_STREAM_H

View File

@ -1,111 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "asio_server_tls_context.h"
#include <openssl/ssl.h>
#include <boost/asio/ssl.hpp>
#include "tls.h"
#include "util.h"
namespace nghttp2 {
namespace asio_http2 {
namespace server {
#ifndef OPENSSL_NO_NEXTPROTONEG
namespace {
std::vector<unsigned char> &get_alpn_token() {
static auto alpn_token = util::get_default_alpn();
return alpn_token;
}
} // namespace
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
namespace {
int alpn_select_proto_cb(SSL *ssl, const unsigned char **out,
unsigned char *outlen, const unsigned char *in,
unsigned int inlen, void *arg) {
if (!util::select_h2(out, outlen, in, inlen)) {
return SSL_TLSEXT_ERR_NOACK;
}
return SSL_TLSEXT_ERR_OK;
}
} // namespace
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
boost::system::error_code
configure_tls_context_easy(boost::system::error_code &ec,
boost::asio::ssl::context &tls_context) {
ec.clear();
auto ctx = tls_context.native_handle();
auto ssl_opts = (SSL_OP_ALL & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) |
SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION |
SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION |
SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_TICKET |
SSL_OP_CIPHER_SERVER_PREFERENCE;
SSL_CTX_set_options(ctx, ssl_opts);
SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
SSL_CTX_set_cipher_list(ctx, tls::DEFAULT_CIPHER_LIST);
#ifndef OPENSSL_NO_EC
auto ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
if (ecdh) {
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
EC_KEY_free(ecdh);
}
#endif /* OPENSSL_NO_EC */
#ifndef OPENSSL_NO_NEXTPROTONEG
SSL_CTX_set_next_protos_advertised_cb(
ctx,
[](SSL *s, const unsigned char **data, unsigned int *len, void *arg) {
auto &token = get_alpn_token();
*data = token.data();
*len = token.size();
return SSL_TLSEXT_ERR_OK;
},
nullptr);
#endif // !OPENSSL_NO_NEXTPROTONEG
#if OPENSSL_VERSION_NUMBER >= 0x10002000L
// ALPN selection callback
SSL_CTX_set_alpn_select_cb(ctx, alpn_select_proto_cb, nullptr);
#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
return ec;
}
} // namespace server
} // namespace asio_http2
} // namespace nghttp2

View File

@ -1,32 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_SERVER_TLS_CONTEXT_H
#define ASIO_SERVER_TLS_CONTEXT_H
#include "nghttp2_config.h"
#include <nghttp2/asio_http2_server.h>
#endif // ASIO_SERVER_TLS_CONTEXT_H

View File

@ -1,7 +0,0 @@
if(ENABLE_ASIO_LIB)
install(FILES
nghttp2/asio_http2.h
nghttp2/asio_http2_client.h
nghttp2/asio_http2_server.h
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/nghttp2")
endif()

View File

@ -1,29 +0,0 @@
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2014 Tatsuhiro Tsujikawa
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
EXTRA_DIST = CMakeLists.txt
if ENABLE_ASIO_LIB
nobase_include_HEADERS = nghttp2/asio_http2.h nghttp2/asio_http2_client.h \
nghttp2/asio_http2_server.h
endif # ENABLE_ASIO_LIB

View File

@ -1,151 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2014 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_HTTP2_H
#define ASIO_HTTP2_H
#include <cstdint>
#include <memory>
#include <string>
#include <vector>
#include <functional>
#include <map>
#include <boost/system/error_code.hpp>
#include <boost/asio.hpp>
#include <boost/asio/ssl.hpp>
#include <nghttp2/nghttp2.h>
namespace nghttp2 {
namespace asio_http2 {
struct header_value {
// header field value
std::string value;
// true if the header field value is sensitive information, such as
// authorization information or short length secret cookies. If
// true, those header fields are not indexed by HPACK (but still
// huffman-encoded), which results in lesser compression.
bool sensitive;
};
// header fields. The header field name must be lower-cased.
using header_map = std::multimap<std::string, header_value>;
const boost::system::error_category &nghttp2_category() noexcept;
struct uri_ref {
std::string scheme;
std::string host;
// form after percent-encoding decoded
std::string path;
// original path, percent-encoded
std::string raw_path;
// original query, percent-encoded
std::string raw_query;
std::string fragment;
};
// Callback function when data is arrived. EOF is indicated by
// passing 0 to the second parameter.
typedef std::function<void(const uint8_t *, std::size_t)> data_cb;
typedef std::function<void(void)> void_cb;
typedef std::function<void(const boost::system::error_code &ec)> error_cb;
// Callback function when request and response are finished. The
// parameter indicates the cause of closure.
typedef std::function<void(uint32_t)> close_cb;
// Callback function to generate response body. This function has the
// same semantics with nghttp2_data_source_read_callback. Just source
// and user_data parameters are removed.
//
// Basically, write at most |len| bytes to |data| and returns the
// number of bytes written. If there is no data left to send, set
// NGHTTP2_DATA_FLAG_EOF to *data_flags (e.g., *data_flags |=
// NGHTTP2_DATA_FLAG_EOF). If there is still data to send but they
// are not available right now, return NGHTTP2_ERR_DEFERRED. In case
// of the error and request/response must be closed, return
// NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE.
typedef std::function<ssize_t(uint8_t *buf, std::size_t len,
uint32_t *data_flags)>
generator_cb;
// Convenient function to create function to read file denoted by
// |path|. This can be passed to response::end().
generator_cb file_generator(const std::string &path);
// Like file_generator(const std::string&), but it takes opened file
// descriptor. The passed descriptor will be closed when returned
// function object is destroyed.
generator_cb file_generator_from_fd(int fd);
// Validates path so that it does not contain directory traversal
// vector. Returns true if path is safe. The |path| must start with
// "/" otherwise returns false. This function should be called after
// percent-decode was performed.
bool check_path(const std::string &path);
// Performs percent-decode against string |s|.
std::string percent_decode(const std::string &s);
// Returns HTTP date representation of current posix time |t|.
std::string http_date(int64_t t);
// Parses |uri| and extract scheme, host and service. The service is
// port component of URI (e.g., "8443") if available, otherwise it is
// scheme (e.g., "https").
boost::system::error_code host_service_from_uri(boost::system::error_code &ec,
std::string &scheme,
std::string &host,
std::string &service,
const std::string &uri);
enum nghttp2_asio_error {
NGHTTP2_ASIO_ERR_NO_ERROR = 0,
NGHTTP2_ASIO_ERR_TLS_NO_APP_PROTO_NEGOTIATED = 1,
};
} // namespace asio_http2
} // namespace nghttp2
namespace boost {
namespace system {
template <> struct is_error_code_enum<nghttp2_error> {
BOOST_STATIC_CONSTANT(bool, value = true);
};
template <> struct is_error_code_enum<nghttp2::asio_http2::nghttp2_asio_error> {
BOOST_STATIC_CONSTANT(bool, value = true);
};
} // namespace system
} // namespace boost
#endif // ASIO_HTTP2_H

View File

@ -1,252 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_HTTP2_CLIENT_H
#define ASIO_HTTP2_CLIENT_H
#include <nghttp2/asio_http2.h>
namespace nghttp2 {
namespace asio_http2 {
namespace client {
class response_impl;
class response {
public:
// Application must not call this directly.
response();
~response();
// Sets callback which is invoked when chunk of response body is
// received.
void on_data(data_cb cb) const;
// Returns status code.
int status_code() const;
// Returns content-length. -1 if it is unknown.
int64_t content_length() const;
// Returns the response header fields. The pseudo header fields,
// which start with colon (:), are excluded from this list.
const header_map &header() const;
// Application must not call this directly.
response_impl &impl() const;
private:
std::unique_ptr<response_impl> impl_;
};
class request;
using response_cb = std::function<void(const response &)>;
using request_cb = std::function<void(const request &)>;
using connect_cb =
std::function<void(boost::asio::ip::tcp::resolver::iterator)>;
class request_impl;
class request {
public:
// Application must not call this directly.
request();
~request();
// Sets callback which is invoked when response header is received.
void on_response(response_cb cb) const;
// Sets callback which is invoked when push request header is
// received.
void on_push(request_cb cb) const;
// Sets callback which is invoked when this request and response are
// finished. After the invocation of this callback, the application
// must not access request and response object.
void on_close(close_cb cb) const;
// Write trailer part. This must be called after setting both
// NGHTTP2_DATA_FLAG_EOF and NGHTTP2_DATA_FLAG_NO_END_STREAM set in
// *data_flag parameter in generator_cb passed to session::submit()
// function.
void write_trailer(header_map h) const;
// Cancels this request and response with given error code.
void cancel(uint32_t error_code = NGHTTP2_INTERNAL_ERROR) const;
// Resumes deferred uploading.
void resume() const;
// Returns method (e.g., GET).
const std::string &method() const;
// Returns request URI, split into components.
const uri_ref &uri() const;
// Returns request header fields. The pseudo header fields, which
// start with colon (:), are excluded from this list.
const header_map &header() const;
// Application must not call this directly.
request_impl &impl() const;
private:
std::unique_ptr<request_impl> impl_;
};
// Wrapper around an nghttp2_priority_spec.
class priority_spec {
public:
// The default ctor is used only by sentinel values.
priority_spec() = default;
// Create a priority spec with the given priority settings.
explicit priority_spec(const int32_t stream_id, const int32_t weight,
const bool exclusive = false);
// Return a pointer to a valid nghttp2 priority spec, or null.
const nghttp2_priority_spec *get() const;
// Indicates whether or not this spec is valid (i.e. was constructed with
// values).
bool valid() const;
private:
nghttp2_priority_spec spec_;
bool valid_ = false;
};
class session_impl;
class session {
public:
// Starts HTTP/2 session by connecting to |host| and |service|
// (e.g., "80") using clear text TCP connection with connect timeout
// 60 seconds.
session(boost::asio::io_service &io_service, const std::string &host,
const std::string &service);
// Same as previous but with pegged local endpoint
session(boost::asio::io_service &io_service,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host, const std::string &service);
// Starts HTTP/2 session by connecting to |host| and |service|
// (e.g., "80") using clear text TCP connection with given connect
// timeout.
session(boost::asio::io_service &io_service, const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout);
// Same as previous but with pegged local endpoint
session(boost::asio::io_service &io_service,
const boost::asio::ip::tcp::endpoint &local_endpoint,
const std::string &host, const std::string &service,
const boost::posix_time::time_duration &connect_timeout);
// Starts HTTP/2 session by connecting to |host| and |service|
// (e.g., "443") using encrypted SSL/TLS connection with connect
// timeout 60 seconds.
session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_context, const std::string &host,
const std::string &service);
// Starts HTTP/2 session by connecting to |host| and |service|
// (e.g., "443") using encrypted SSL/TLS connection with given
// connect timeout.
session(boost::asio::io_service &io_service,
boost::asio::ssl::context &tls_context, const std::string &host,
const std::string &service,
const boost::posix_time::time_duration &connect_timeout);
~session();
session(session &&other) noexcept;
session &operator=(session &&other) noexcept;
// Sets callback which is invoked after connection is established.
void on_connect(connect_cb cb) const;
// Sets callback which is invoked there is connection level error
// and session is terminated.
void on_error(error_cb cb) const;
// Sets read timeout, which defaults to 60 seconds.
void read_timeout(const boost::posix_time::time_duration &t);
// Shutdowns connection.
void shutdown() const;
// Returns underlying io_service object.
boost::asio::io_service &io_service() const;
// Submits request to server using |method| (e.g., "GET"), |uri|
// (e.g., "http://localhost/") and optionally additional header
// fields. This function returns pointer to request object if it
// succeeds, or nullptr and |ec| contains error message.
const request *submit(boost::system::error_code &ec,
const std::string &method, const std::string &uri,
header_map h = header_map{},
priority_spec prio = priority_spec()) const;
// Submits request to server using |method| (e.g., "GET"), |uri|
// (e.g., "http://localhost/") and optionally additional header
// fields. The |data| is request body. This function returns
// pointer to request object if it succeeds, or nullptr and |ec|
// contains error message.
const request *submit(boost::system::error_code &ec,
const std::string &method, const std::string &uri,
std::string data, header_map h = header_map{},
priority_spec prio = priority_spec()) const;
// Submits request to server using |method| (e.g., "GET"), |uri|
// (e.g., "http://localhost/") and optionally additional header
// fields. The |cb| is used to generate request body. This
// function returns pointer to request object if it succeeds, or
// nullptr and |ec| contains error message.
const request *submit(boost::system::error_code &ec,
const std::string &method, const std::string &uri,
generator_cb cb, header_map h = header_map{},
priority_spec prio = priority_spec()) const;
private:
std::shared_ptr<session_impl> impl_;
};
// configure |tls_ctx| for client use. Currently, we just set NPN
// callback for HTTP/2.
boost::system::error_code
configure_tls_context(boost::system::error_code &ec,
boost::asio::ssl::context &tls_ctx);
} // namespace client
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_HTTP2_CLIENT_H

View File

@ -1,245 +0,0 @@
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2015 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef ASIO_HTTP2_SERVER_H
#define ASIO_HTTP2_SERVER_H
#include <nghttp2/asio_http2.h>
namespace nghttp2 {
namespace asio_http2 {
namespace server {
class request_impl;
class response_impl;
class request {
public:
// Application must not call this directly.
request();
~request();
// Returns request header fields. The pseudo header fields, which
// start with colon (:), are excluded from this list.
const header_map &header() const;
// Returns method (e.g., GET).
const std::string &method() const;
// Returns request URI, split into components.
const uri_ref &uri() const;
// Sets callback which is invoked when chunk of request body is
// received.
void on_data(data_cb cb) const;
// Application must not call this directly.
request_impl &impl() const;
// Returns the remote endpoint of the request
const boost::asio::ip::tcp::endpoint &remote_endpoint() const;
private:
std::unique_ptr<request_impl> impl_;
};
class response {
public:
// Application must not call this directly.
response();
~response();
// Write response header using |status_code| (e.g., 200) and
// additional header fields in |h|.
void write_head(unsigned int status_code, header_map h = header_map{}) const;
// Sends |data| as request body. No further call of end() is
// allowed.
void end(std::string data = "") const;
// Sets callback as a generator of the response body. No further
// call of end() is allowed.
void end(generator_cb cb) const;
// Write trailer part. This must be called after setting both
// NGHTTP2_DATA_FLAG_EOF and NGHTTP2_DATA_FLAG_NO_END_STREAM set in
// *data_flag parameter in generator_cb passed to end() function.
void write_trailer(header_map h) const;
// Sets callback which is invoked when this request and response are
// finished. After the invocation of this callback, the application
// must not access request and response object.
void on_close(close_cb cb) const;
// Cancels this request and response with given error code.
void cancel(uint32_t error_code = NGHTTP2_INTERNAL_ERROR) const;
// Resumes deferred response.
void resume() const;
// Pushes resource denoted by |raw_path_query| using |method|. The
// additional header fields can be given in |h|. This function
// returns pointer to response object for promised stream, otherwise
// nullptr and error code is filled in |ec|. Be aware that the
// header field name given in |h| must be lower-cased.
const response *push(boost::system::error_code &ec, std::string method,
std::string raw_path_query,
header_map h = header_map{}) const;
// Returns status code.
unsigned int status_code() const;
// Returns boost::asio::io_service this response is running on.
boost::asio::io_service &io_service() const;
// Application must not call this directly.
response_impl &impl() const;
private:
std::unique_ptr<response_impl> impl_;
};
// This is so called request callback. Called every time request is
// received. The life time of |request| and |response| objects end
// when callback set by response::on_close() is called. After that,
// the application must not access to those objects.
typedef std::function<void(const request &, const response &)> request_cb;
class http2_impl;
class http2 {
public:
http2();
~http2();
http2(http2 &&other) noexcept;
http2 &operator=(http2 &&other) noexcept;
// Starts listening connection on given address and port and serves
// incoming requests in cleartext TCP connection. If |asynchronous|
// is false, this function blocks forever unless there is an error.
// If it is true, after server has started, this function returns
// immediately, and the caller should call stop() and join() to
// shutdown server gracefully.
boost::system::error_code listen_and_serve(boost::system::error_code &ec,
const std::string &address,
const std::string &port,
bool asynchronous = false);
// Starts listening connection on given address and port and serves
// incoming requests in SSL/TLS encrypted connection. For
// |asynchronous| parameter, see cleartext version
// |listen_and_serve|.
boost::system::error_code
listen_and_serve(boost::system::error_code &ec,
boost::asio::ssl::context &tls_context,
const std::string &address, const std::string &port,
bool asynchronous = false);
// Registers request handler |cb| with path pattern |pattern|. This
// function will fail and returns false if same pattern has been
// already registered or |pattern| is empty string. Otherwise
// returns true. The pattern match rule is the same as
// net/http/ServeMux in golang. Quoted from golang manual
// (http://golang.org/pkg/net/http/#ServeMux):
//
// Patterns name fixed, rooted paths, like "/favicon.ico", or
// rooted subtrees, like "/images/" (note the trailing
// slash). Longer patterns take precedence over shorter ones, so
// that if there are handlers registered for both "/images/" and
// "/images/thumbnails/", the latter handler will be called for
// paths beginning "/images/thumbnails/" and the former will
// receive requests for any other paths in the "/images/" subtree.
//
// Note that since a pattern ending in a slash names a rooted
// subtree, the pattern "/" matches all paths not matched by other
// registered patterns, not just the URL with Path == "/".
//
// Patterns may optionally begin with a host name, restricting
// matches to URLs on that host only. Host-specific patterns take
// precedence over general patterns, so that a handler might
// register for the two patterns "/codesearch" and
// "codesearch.google.com/" without also taking over requests for
// "http://www.google.com/".
//
// Just like ServeMux in golang, URL request path is sanitized and
// if they contains . or .. elements, they are redirected to an
// equivalent .- and ..-free URL.
bool handle(std::string pattern, request_cb cb);
// Sets number of native threads to handle incoming HTTP request.
// It defaults to 1.
void num_threads(size_t num_threads);
// Sets the maximum length to which the queue of pending
// connections.
void backlog(int backlog);
// Sets TLS handshake timeout, which defaults to 60 seconds.
void tls_handshake_timeout(const boost::posix_time::time_duration &t);
// Sets read timeout, which defaults to 60 seconds.
void read_timeout(const boost::posix_time::time_duration &t);
// Gracefully stop http2 server
void stop();
// Join on http2 server and wait for it to fully stop
void join();
// Get access to the io_service objects.
const std::vector<std::shared_ptr<boost::asio::io_service>> &
io_services() const;
// Returns a vector with the ports in use
std::vector<int> ports() const;
private:
std::unique_ptr<http2_impl> impl_;
};
// Configures |tls_context| for server use. This function sets couple
// of OpenSSL options (disables SSLv2 and SSLv3 and compression) and
// enables ECDHE ciphers. NPN callback is also configured.
boost::system::error_code
configure_tls_context_easy(boost::system::error_code &ec,
boost::asio::ssl::context &tls_context);
// Returns request handler to do redirect to |uri| using
// |status_code|. The |uri| appears in "location" header field as is.
request_cb redirect_handler(int status_code, std::string uri);
// Returns request handler to reply with given |status_code| and HTML
// including message about status code.
request_cb status_handler(int status_code);
} // namespace server
} // namespace asio_http2
} // namespace nghttp2
#endif // ASIO_HTTP2_SERVER_H

View File

@ -1,33 +0,0 @@
# nghttp2 - HTTP/2 C Library
# Copyright (c) 2014 Tatsuhiro Tsujikawa
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libnghttp2_asio
Description: HTTP/2 C++ library
URL: https://github.com/tatsuhiro-t/nghttp2
Version: @VERSION@
Libs: -L${libdir} -lnghttp2_asio
Cflags: -I${includedir}

View File

@ -43,7 +43,6 @@
#endif // HAVE_NETINET_IN_H
#ifdef _WIN32
# include <ws2tcpip.h>
# include <boost/date_time/posix_time/posix_time.hpp>
#else // !_WIN32
# include <netinet/tcp.h>
#endif // !_WIN32
@ -58,6 +57,7 @@
#include <cstring>
#include <iostream>
#include <fstream>
#include <iomanip>
#include <openssl/evp.h>
@ -437,34 +437,22 @@ char *iso8601_basic_date(char *res, int64_t ms) {
return p;
}
#ifdef _WIN32
namespace bt = boost::posix_time;
// one-time definition of the locale that is used to parse UTC strings
// (note that the time_input_facet is ref-counted and deleted automatically)
static const std::locale
ptime_locale(std::locale::classic(),
new bt::time_input_facet("%a, %d %b %Y %H:%M:%S GMT"));
#endif //_WIN32
time_t parse_http_date(const StringRef &s) {
#ifdef _WIN32
// there is no strptime - use boost
std::stringstream sstr(s.str());
sstr.imbue(ptime_locale);
bt::ptime ltime;
sstr >> ltime;
if (!sstr)
return 0;
return boost::posix_time::to_time_t(ltime);
#else // !_WIN32
tm tm{};
#ifdef _WIN32
// there is no strptime - use std::get_time
std::stringstream sstr(s.str());
sstr >> std::get_time(&tm, "%a, %d %b %Y %H:%M:%S GMT");
if (sstr.fail()) {
return 0;
}
#else // !_WIN32
char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
if (r == 0) {
return 0;
}
return nghttp2_timegm_without_yday(&tm);
#endif // !_WIN32
return nghttp2_timegm_without_yday(&tm);
}
time_t parse_openssl_asn1_time_print(const StringRef &s) {