mirror of
https://gitee.com/openharmony/third_party_nghttp2
synced 2024-11-26 17:40:25 +00:00
Remove deprecated libnghttp2_asio
This commit is contained in:
parent
00a33281be
commit
e6d608b522
@ -243,10 +243,6 @@ endif()
|
|||||||
# jemalloc
|
# jemalloc
|
||||||
set(HAVE_JEMALLOC ${JEMALLOC_FOUND})
|
set(HAVE_JEMALLOC ${JEMALLOC_FOUND})
|
||||||
|
|
||||||
if(ENABLE_ASIO_LIB)
|
|
||||||
find_package(Boost 1.54.0 REQUIRED system thread)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# libbpf (for bpf)
|
# libbpf (for bpf)
|
||||||
set(HAVE_LIBBPF ${LIBBPF_FOUND})
|
set(HAVE_LIBBPF ${LIBBPF_FOUND})
|
||||||
if(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.")
|
message(FATAL_ERROR "HPACK tools were requested (ENABLE_HPACK_TOOLS=1) but dependencies are not met.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# C++ library libnghttp2_asio
|
# examples
|
||||||
if(ENABLE_EXAMPLES AND NOT (OPENSSL_FOUND AND LIBEVENT_OPENSSL_FOUND))
|
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.")
|
message(FATAL_ERROR "examples were requested (ENABLE_EXAMPLES=1) but dependencies are not met.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# third-party http-parser only be built when needed
|
# 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)
|
set(ENABLE_THIRD_PARTY 1)
|
||||||
# mruby (for src/nghttpx)
|
# mruby (for src/nghttpx)
|
||||||
set(HAVE_MRUBY ${WITH_MRUBY})
|
set(HAVE_MRUBY ${WITH_MRUBY})
|
||||||
@ -467,7 +463,6 @@ set(sbindir "${CMAKE_INSTALL_FULL_SBINDIR}")
|
|||||||
foreach(name
|
foreach(name
|
||||||
lib/libnghttp2.pc
|
lib/libnghttp2.pc
|
||||||
lib/includes/nghttp2/nghttp2ver.h
|
lib/includes/nghttp2/nghttp2ver.h
|
||||||
src/libnghttp2_asio.pc
|
|
||||||
python/setup.py
|
python/setup.py
|
||||||
integration-tests/config.go
|
integration-tests/config.go
|
||||||
integration-tests/setenv
|
integration-tests/setenv
|
||||||
@ -479,14 +474,10 @@ foreach(name
|
|||||||
doc/tutorial-hpack.rst
|
doc/tutorial-hpack.rst
|
||||||
doc/nghttpx-howto.rst
|
doc/nghttpx-howto.rst
|
||||||
doc/h2load-howto.rst
|
doc/h2load-howto.rst
|
||||||
doc/libnghttp2_asio.rst
|
|
||||||
doc/python-apiref.rst
|
doc/python-apiref.rst
|
||||||
doc/building-android-binary.rst
|
doc/building-android-binary.rst
|
||||||
doc/nghttp2.h.rst
|
doc/nghttp2.h.rst
|
||||||
doc/nghttp2ver.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
|
doc/contribute.rst
|
||||||
)
|
)
|
||||||
configure_file("${name}.in" "${name}" @ONLY)
|
configure_file("${name}.in" "${name}" @ONLY)
|
||||||
@ -560,8 +551,6 @@ message(STATUS "summary of build options:
|
|||||||
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
|
Jemalloc: ${HAVE_JEMALLOC} (LIBS='${JEMALLOC_LIBRARIES}')
|
||||||
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
|
Zlib: ${HAVE_ZLIB} (LIBS='${ZLIB_LIBRARIES}')
|
||||||
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
|
Systemd: ${HAVE_SYSTEMD} (LIBS='${SYSTEMD_LIBRARIES}')
|
||||||
Boost::System: ${Boost_SYSTEM_LIBRARY}
|
|
||||||
Boost::Thread: ${Boost_THREAD_LIBRARY}
|
|
||||||
Third-party:
|
Third-party:
|
||||||
http-parser: ${ENABLE_THIRD_PARTY}
|
http-parser: ${ENABLE_THIRD_PARTY}
|
||||||
MRuby: ${HAVE_MRUBY}
|
MRuby: ${HAVE_MRUBY}
|
||||||
@ -569,7 +558,6 @@ message(STATUS "summary of build options:
|
|||||||
Features:
|
Features:
|
||||||
Applications: ${ENABLE_APP}
|
Applications: ${ENABLE_APP}
|
||||||
HPACK tools: ${ENABLE_HPACK_TOOLS}
|
HPACK tools: ${ENABLE_HPACK_TOOLS}
|
||||||
Libnghttp2_asio:${ENABLE_ASIO_LIB}
|
|
||||||
Examples: ${ENABLE_EXAMPLES}
|
Examples: ${ENABLE_EXAMPLES}
|
||||||
Python bindings:${ENABLE_PYTHON_BINDINGS}
|
Python bindings:${ENABLE_PYTHON_BINDINGS}
|
||||||
Threading: ${ENABLE_THREADS}
|
Threading: ${ENABLE_THREADS}
|
||||||
|
@ -7,7 +7,6 @@ option(ENABLE_APP "Build applications (nghttp, nghttpd, nghttpx and h2load
|
|||||||
${ENABLE_APP_DEFAULT})
|
${ENABLE_APP_DEFAULT})
|
||||||
option(ENABLE_HPACK_TOOLS "Build HPACK tools"
|
option(ENABLE_HPACK_TOOLS "Build HPACK tools"
|
||||||
${ENABLE_HPACK_TOOLS_DEFAULT})
|
${ENABLE_HPACK_TOOLS_DEFAULT})
|
||||||
option(ENABLE_ASIO_LIB "Build C++ libnghttp2_asio library")
|
|
||||||
option(ENABLE_EXAMPLES "Build examples"
|
option(ENABLE_EXAMPLES "Build examples"
|
||||||
${ENABLE_EXAMPLES_DEFAULT})
|
${ENABLE_EXAMPLES_DEFAULT})
|
||||||
option(ENABLE_PYTHON_BINDINGS "Build Python bindings"
|
option(ENABLE_PYTHON_BINDINGS "Build Python bindings"
|
||||||
|
107
README.rst
107
README.rst
@ -103,13 +103,6 @@ To mitigate heap fragmentation in long running server programs
|
|||||||
Alpine Linux currently does not support malloc replacement
|
Alpine Linux currently does not support malloc replacement
|
||||||
due to musl limitations. See details in issue `#762 <https://github.com/nghttp2/nghttp2/issues/762>`_.
|
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:
|
The Python bindings (deprecated) require the following packages:
|
||||||
|
|
||||||
* cython >= 0.19
|
* 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
|
corresponding header set was processed. The format is the same as
|
||||||
``deflatehd``.
|
``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
|
Python bindings
|
||||||
---------------
|
---------------
|
||||||
|
|
||||||
|
49
configure.ac
49
configure.ac
@ -82,11 +82,6 @@ AC_ARG_ENABLE([hpack-tools],
|
|||||||
[Build HPACK tools [default=check]])],
|
[Build HPACK tools [default=check]])],
|
||||||
[request_hpack_tools=$enableval], [request_hpack_tools=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],
|
AC_ARG_ENABLE([examples],
|
||||||
[AS_HELP_STRING([--enable-examples],
|
[AS_HELP_STRING([--enable-examples],
|
||||||
[Build examples [default=check]])],
|
[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])
|
AC_MSG_ERROR([jemalloc was requested (--with-jemalloc) but not found])
|
||||||
fi
|
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,
|
# The nghttp, nghttpd and nghttpx under src depend on zlib, OpenSSL,
|
||||||
# libev, and libc-ares.
|
# libev, and libc-ares.
|
||||||
enable_app=no
|
enable_app=no
|
||||||
@ -834,16 +810,6 @@ fi
|
|||||||
|
|
||||||
AM_CONDITIONAL([ENABLE_HPACK_TOOLS], [ test "x${enable_hpack_tools}" = "xyes" ])
|
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
|
# The example programs depend on OpenSSL and libevent_openssl
|
||||||
enable_examples=no
|
enable_examples=no
|
||||||
if test "x${request_examples}" != "xno" &&
|
if test "x${request_examples}" != "xno" &&
|
||||||
@ -866,8 +832,7 @@ have_mruby=no
|
|||||||
have_neverbleed=no
|
have_neverbleed=no
|
||||||
if test "x${enable_examples}" = "xyes" ||
|
if test "x${enable_examples}" = "xyes" ||
|
||||||
test "x${enable_app}" = "xyes" ||
|
test "x${enable_app}" = "xyes" ||
|
||||||
test "x${enable_hpack_tools}" = "xyes" ||
|
test "x${enable_hpack_tools}" = "xyes"; then
|
||||||
test "x${enable_asio_lib}" = "xyes"; then
|
|
||||||
enable_third_party=yes
|
enable_third_party=yes
|
||||||
|
|
||||||
# mruby (for src/nghttpx)
|
# mruby (for src/nghttpx)
|
||||||
@ -1159,8 +1124,6 @@ AC_CONFIG_FILES([
|
|||||||
tests/testdata/Makefile
|
tests/testdata/Makefile
|
||||||
third-party/Makefile
|
third-party/Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/includes/Makefile
|
|
||||||
src/libnghttp2_asio.pc
|
|
||||||
bpf/Makefile
|
bpf/Makefile
|
||||||
examples/Makefile
|
examples/Makefile
|
||||||
python/Makefile
|
python/Makefile
|
||||||
@ -1177,14 +1140,10 @@ AC_CONFIG_FILES([
|
|||||||
doc/tutorial-hpack.rst
|
doc/tutorial-hpack.rst
|
||||||
doc/nghttpx-howto.rst
|
doc/nghttpx-howto.rst
|
||||||
doc/h2load-howto.rst
|
doc/h2load-howto.rst
|
||||||
doc/libnghttp2_asio.rst
|
|
||||||
doc/python-apiref.rst
|
doc/python-apiref.rst
|
||||||
doc/building-android-binary.rst
|
doc/building-android-binary.rst
|
||||||
doc/nghttp2.h.rst
|
doc/nghttp2.h.rst
|
||||||
doc/nghttp2ver.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
|
doc/contribute.rst
|
||||||
contrib/Makefile
|
contrib/Makefile
|
||||||
script/Makefile
|
script/Makefile
|
||||||
@ -1248,11 +1207,6 @@ AC_MSG_NOTICE([summary of build options:
|
|||||||
Jemalloc: ${have_jemalloc} (CFLAGS='${JEMALLOC_CFLAGS}' LIBS='${JEMALLOC_LIBS}')
|
Jemalloc: ${have_jemalloc} (CFLAGS='${JEMALLOC_CFLAGS}' LIBS='${JEMALLOC_LIBS}')
|
||||||
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
|
Zlib: ${have_zlib} (CFLAGS='${ZLIB_CFLAGS}' LIBS='${ZLIB_LIBS}')
|
||||||
Systemd: ${have_libsystemd} (CFLAGS='${SYSTEMD_CFLAGS}' LIBS='${SYSTEMD_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:
|
Third-party:
|
||||||
http-parser: ${enable_third_party}
|
http-parser: ${enable_third_party}
|
||||||
MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}')
|
MRuby: ${have_mruby} (CFLAGS='${LIBMRUBY_CFLAGS}' LIBS='${LIBMRUBY_LIBS}')
|
||||||
@ -1260,7 +1214,6 @@ AC_MSG_NOTICE([summary of build options:
|
|||||||
Features:
|
Features:
|
||||||
Applications: ${enable_app}
|
Applications: ${enable_app}
|
||||||
HPACK tools: ${enable_hpack_tools}
|
HPACK tools: ${enable_hpack_tools}
|
||||||
Libnghttp2_asio:${enable_asio_lib}
|
|
||||||
Examples: ${enable_examples}
|
Examples: ${enable_examples}
|
||||||
Python bindings:${enable_python_bindings}
|
Python bindings:${enable_python_bindings}
|
||||||
Threading: ${enable_threads}
|
Threading: ${enable_threads}
|
||||||
|
4
doc/.gitignore
vendored
4
doc/.gitignore
vendored
@ -1,15 +1,11 @@
|
|||||||
# generated files
|
# generated files
|
||||||
apiref.rst
|
apiref.rst
|
||||||
asio_http2.h.rst
|
|
||||||
asio_http2_client.h.rst
|
|
||||||
asio_http2_server.h.rst
|
|
||||||
building-android-binary.rst
|
building-android-binary.rst
|
||||||
conf.py
|
conf.py
|
||||||
contribute.rst
|
contribute.rst
|
||||||
enums.rst
|
enums.rst
|
||||||
h2load-howto.rst
|
h2load-howto.rst
|
||||||
index.rst
|
index.rst
|
||||||
libnghttp2_asio.rst
|
|
||||||
macros.rst
|
macros.rst
|
||||||
manual/
|
manual/
|
||||||
nghttp2.h.rst
|
nghttp2.h.rst
|
||||||
|
@ -180,7 +180,6 @@ set(EXTRA_DIST
|
|||||||
sources/tutorial-hpack.rst
|
sources/tutorial-hpack.rst
|
||||||
sources/nghttpx-howto.rst
|
sources/nghttpx-howto.rst
|
||||||
sources/h2load-howto.rst
|
sources/h2load-howto.rst
|
||||||
sources/libnghttp2_asio.rst
|
|
||||||
sources/python-apiref.rst
|
sources/python-apiref.rst
|
||||||
sources/building-android-binary.rst
|
sources/building-android-binary.rst
|
||||||
sources/contribute.rst
|
sources/contribute.rst
|
||||||
|
@ -206,7 +206,6 @@ EXTRA_DIST = \
|
|||||||
sources/tutorial-hpack.rst \
|
sources/tutorial-hpack.rst \
|
||||||
sources/nghttpx-howto.rst \
|
sources/nghttpx-howto.rst \
|
||||||
sources/h2load-howto.rst \
|
sources/h2load-howto.rst \
|
||||||
sources/libnghttp2_asio.rst \
|
|
||||||
sources/python-apiref.rst \
|
sources/python-apiref.rst \
|
||||||
sources/building-android-binary.rst \
|
sources/building-android-binary.rst \
|
||||||
sources/contribute.rst \
|
sources/contribute.rst \
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
asio_http2.h
|
|
||||||
============
|
|
||||||
|
|
||||||
.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2.h
|
|
||||||
:language: cpp
|
|
@ -1,5 +0,0 @@
|
|||||||
asio_http2_client.h
|
|
||||||
===================
|
|
||||||
|
|
||||||
.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2_client.h
|
|
||||||
:language: cpp
|
|
@ -1,5 +0,0 @@
|
|||||||
asio_http2_server.h
|
|
||||||
===================
|
|
||||||
|
|
||||||
.. literalinclude:: @top_srcdir@/src/includes/nghttp2/asio_http2_server.h
|
|
||||||
:language: cpp
|
|
@ -1 +0,0 @@
|
|||||||
.. include:: @top_srcdir@/doc/sources/libnghttp2_asio.rst
|
|
@ -31,13 +31,9 @@ Contents:
|
|||||||
h2load-howto
|
h2load-howto
|
||||||
programmers-guide
|
programmers-guide
|
||||||
apiref
|
apiref
|
||||||
libnghttp2_asio
|
|
||||||
python-apiref
|
python-apiref
|
||||||
nghttp2.h
|
nghttp2.h
|
||||||
nghttp2ver.h
|
nghttp2ver.h
|
||||||
asio_http2_server.h
|
|
||||||
asio_http2_client.h
|
|
||||||
asio_http2.h
|
|
||||||
Source <https://github.com/nghttp2/nghttp2>
|
Source <https://github.com/nghttp2/nghttp2>
|
||||||
Issues <https://github.com/nghttp2/nghttp2/issues>
|
Issues <https://github.com/nghttp2/nghttp2/issues>
|
||||||
nghttp2.org <https://nghttp2.org/>
|
nghttp2.org <https://nghttp2.org/>
|
||||||
|
@ -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
4
examples/.gitignore
vendored
@ -3,7 +3,3 @@ libevent-client
|
|||||||
libevent-server
|
libevent-server
|
||||||
deflate
|
deflate
|
||||||
tiny-nghttpd
|
tiny-nghttpd
|
||||||
asio-sv
|
|
||||||
asio-sv2
|
|
||||||
asio-cl
|
|
||||||
asio-cl2
|
|
||||||
|
@ -34,24 +34,4 @@ if(ENABLE_EXAMPLES)
|
|||||||
add_executable(deflate deflate.c $<TARGET_OBJECTS:llhttp>
|
add_executable(deflate deflate.c $<TARGET_OBJECTS:llhttp>
|
||||||
$<TARGET_OBJECTS:url-parser>
|
$<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()
|
endif()
|
||||||
|
@ -52,40 +52,4 @@ libevent_server_SOURCES = libevent-server.c
|
|||||||
|
|
||||||
deflate_SOURCES = deflate.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
|
endif # ENABLE_EXAMPLES
|
||||||
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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;
|
|
||||||
}
|
|
@ -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
|
|
||||||
])
|
|
@ -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
|
|
||||||
|
|
||||||
])
|
|
@ -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
|
|
||||||
])
|
|
@ -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
|
|
||||||
])
|
|
@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
autoreconf -i
|
autoreconf -i
|
||||||
git submodule update --init
|
git submodule update --init
|
||||||
./configure --with-mruby --with-neverbleed --enable-asio-lib
|
./configure --with-mruby --with-neverbleed
|
||||||
make -j8 distcheck DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --enable-asio-lib --enable-werror"
|
make -j8 distcheck DISTCHECK_CONFIGURE_FLAGS="--with-mruby --with-neverbleed --enable-werror"
|
||||||
|
3
src/.gitignore
vendored
3
src/.gitignore
vendored
@ -1,6 +1,3 @@
|
|||||||
# generated files
|
|
||||||
libnghttp2_asio.pc
|
|
||||||
|
|
||||||
# programs
|
# programs
|
||||||
deflatehd
|
deflatehd
|
||||||
h2load
|
h2load
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
add_subdirectory(includes)
|
|
||||||
|
|
||||||
file(GLOB c_sources *.c)
|
file(GLOB c_sources *.c)
|
||||||
set_source_files_properties(${c_sources} PROPERTIES
|
set_source_files_properties(${c_sources} PROPERTIES
|
||||||
COMPILE_FLAGS "${WARNCFLAGS}")
|
COMPILE_FLAGS "${WARNCFLAGS}")
|
||||||
@ -243,65 +241,3 @@ if(ENABLE_HPACK_TOOLS)
|
|||||||
install(TARGETS inflatehd deflatehd
|
install(TARGETS inflatehd deflatehd
|
||||||
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}")
|
||||||
endif()
|
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()
|
|
||||||
|
@ -20,8 +20,6 @@
|
|||||||
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
SUBDIRS = includes
|
|
||||||
|
|
||||||
EXTRA_DIST = \
|
EXTRA_DIST = \
|
||||||
CMakeLists.txt \
|
CMakeLists.txt \
|
||||||
test.example.com.pem \
|
test.example.com.pem \
|
||||||
@ -95,10 +93,10 @@ endif # HAVE_LIBXML2
|
|||||||
|
|
||||||
nghttp_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttp.cc nghttp.h \
|
nghttp_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttp.cc nghttp.h \
|
||||||
${HTML_PARSER_OBJECTS} ${HTML_PARSER_HFILES} \
|
${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 \
|
nghttpd_SOURCES = ${HELPER_OBJECTS} ${HELPER_HFILES} nghttpd.cc \
|
||||||
tls.cc tls.h \
|
tls.cc tls.h ssl_compat.h \
|
||||||
HttpServer.cc HttpServer.h
|
HttpServer.cc HttpServer.h
|
||||||
|
|
||||||
bin_PROGRAMS += h2load
|
bin_PROGRAMS += h2load
|
||||||
@ -106,7 +104,7 @@ bin_PROGRAMS += h2load
|
|||||||
h2load_SOURCES = util.cc util.h \
|
h2load_SOURCES = util.cc util.h \
|
||||||
http2.cc http2.h h2load.cc h2load.h \
|
http2.cc http2.h h2load.cc h2load.h \
|
||||||
timegm.c timegm.h \
|
timegm.c timegm.h \
|
||||||
tls.cc tls.h \
|
tls.cc tls.h ssl_compat.h \
|
||||||
h2load_session.h \
|
h2load_session.h \
|
||||||
h2load_http2_session.cc h2load_http2_session.h \
|
h2load_http2_session.cc h2load_http2_session.h \
|
||||||
h2load_http1_session.cc h2load_http1_session.h
|
h2load_http1_session.cc h2load_http1_session.h
|
||||||
@ -121,7 +119,7 @@ endif # ENABLE_HTTP3
|
|||||||
NGHTTPX_SRCS = \
|
NGHTTPX_SRCS = \
|
||||||
util.cc util.h http2.cc http2.h timegm.c timegm.h base64.h \
|
util.cc util.h http2.cc http2.h timegm.c timegm.h base64.h \
|
||||||
app_helper.cc app_helper.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_config.cc shrpx_config.h \
|
||||||
shrpx_error.h \
|
shrpx_error.h \
|
||||||
shrpx_accept_handler.cc shrpx_accept_handler.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)
|
deflatehd_SOURCES = deflatehd.cc $(HPACK_TOOLS_COMMON_SRCS)
|
||||||
|
|
||||||
endif # ENABLE_HPACK_TOOLS
|
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
|
|
||||||
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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()
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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}
|
|
32
src/util.cc
32
src/util.cc
@ -43,7 +43,6 @@
|
|||||||
#endif // HAVE_NETINET_IN_H
|
#endif // HAVE_NETINET_IN_H
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
# include <ws2tcpip.h>
|
# include <ws2tcpip.h>
|
||||||
# include <boost/date_time/posix_time/posix_time.hpp>
|
|
||||||
#else // !_WIN32
|
#else // !_WIN32
|
||||||
# include <netinet/tcp.h>
|
# include <netinet/tcp.h>
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
@ -58,6 +57,7 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
@ -437,34 +437,22 @@ char *iso8601_basic_date(char *res, int64_t ms) {
|
|||||||
return p;
|
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) {
|
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{};
|
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);
|
char *r = strptime(s.c_str(), "%a, %d %b %Y %H:%M:%S GMT", &tm);
|
||||||
if (r == 0) {
|
if (r == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return nghttp2_timegm_without_yday(&tm);
|
|
||||||
#endif // !_WIN32
|
#endif // !_WIN32
|
||||||
|
return nghttp2_timegm_without_yday(&tm);
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t parse_openssl_asn1_time_print(const StringRef &s) {
|
time_t parse_openssl_asn1_time_print(const StringRef &s) {
|
||||||
|
Loading…
Reference in New Issue
Block a user