diff options
-rw-r--r-- | Makefile | 6 | ||||
-rw-r--r-- | debian/control | 2 | ||||
-rw-r--r-- | http.cpp | 119 | ||||
-rw-r--r-- | https.cpp | 145 | ||||
-rw-r--r-- | https.h | 13 | ||||
-rw-r--r-- | plugin.cpp | 15 | ||||
-rw-r--r-- | plugins/static-files/Makefile | 4 | ||||
-rw-r--r-- | server.cpp | 12 |
8 files changed, 292 insertions, 24 deletions
@@ -26,7 +26,7 @@ CXXFLAGS+= -pthread ifeq ($(CXX),clang++-10) CXXFLAGS+=-std=c++20 #-stdlib=libc++ else -CXXFLAGS+=-std=c++2a +CXXFLAGS+=-std=c++17 endif CXXTESTFLAGS=-Igoogletest/include -Igooglemock/include/ -Igoogletest -Igooglemock @@ -53,8 +53,8 @@ LIBS+= \ #-lstdc++fs else LIBS+= \ --lstdc++ -#-lstdc++fs +-lstdc++ \ +-lstdc++fs endif PROGSRC=\ diff --git a/debian/control b/debian/control index 3d5d617..4c0d558 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: webserver Section: web Priority: extra Maintainer: Roland Reichwein <mail@reichwein.it> -Build-Depends: debhelper (>= 9), libssl-dev, libssl-dev, libboost-all-dev | libboost1.71-all-dev, clang +Build-Depends: debhelper (>= 9), libssl-dev, libboost-all-dev | libboost1.71-all-dev, clang Standards-Version: 4.1.3 Homepage: http://www.reichwein.it/webserver/ @@ -1,13 +1,23 @@ #include "http.h" +#include <boost/beast/version.hpp> + +// Support both boost in Debian unstable (BOOST_LATEST) and in stable (boost 1.67) +#if BOOST_VERSION >= 107100 +#define BOOST_LATEST +#endif + #include "server.h" #include "response.h" #include <boost/beast/version.hpp> #include <boost/beast/core.hpp> #include <boost/beast/http.hpp> -#include <boost/beast/version.hpp> #include <boost/asio/dispatch.hpp> +#ifndef BOOST_LATEST +#include <boost/asio/bind_executor.hpp> +#include <boost/asio/ip/tcp.hpp> +#endif #include <boost/asio/strand.hpp> #include <boost/config.hpp> #include <algorithm> @@ -38,7 +48,12 @@ fail(beast::error_code ec, char const* what) // Handles an HTTP server connection class session : public std::enable_shared_from_this<session> { +#ifdef BOOST_LATEST beast::tcp_stream stream_; +#else + tcp::socket socket_; + boost::asio::strand<boost::asio::io_context::executor_type> strand_; +#endif beast::flat_buffer buffer_; Server& m_server; request_type req_; @@ -51,6 +66,7 @@ class session : public std::enable_shared_from_this<session> res_ = sp; // Write the response +#ifdef BOOST_LATEST http::async_write( stream_, *sp, @@ -58,14 +74,36 @@ class session : public std::enable_shared_from_this<session> &session::on_write, shared_from_this(), sp->need_eof())); +#else + http::async_write( + socket_, + *sp, + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_write, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + sp->need_eof()))); +#endif } public: // Take ownership of the stream session( +#ifdef BOOST_LATEST tcp::socket&& socket, +#else + tcp::socket socket, +#endif Server& server) +#ifdef BOOST_LATEST : stream_(std::move(socket)) +#else + : socket_(std::move(socket)) + , strand_(socket_.get_executor()) +#endif , m_server(server) { } @@ -75,13 +113,15 @@ public: run() { // We need to be executing within a strand to perform async operations - // on the I/O objects in this session. Although not strictly necessary - // for single-threaded contexts, this example code is written to be - // thread-safe by default. + // on the I/O objects in this session. +#ifdef BOOST_LATEST net::dispatch(stream_.get_executor(), beast::bind_front_handler( &session::do_read, shared_from_this())); +#else + do_read(); +#endif } void @@ -91,6 +131,7 @@ public: // otherwise the operation behavior is undefined. req_ = {}; +#ifdef BOOST_LATEST // Set the timeout. stream_.expires_after(std::chrono::seconds(30)); @@ -99,12 +140,29 @@ public: beast::bind_front_handler( &session::on_read, shared_from_this())); +#else + + http::async_read(socket_, buffer_, req_, + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); +#endif } void on_read( +#ifdef BOOST_LATEST beast::error_code ec, - std::size_t bytes_transferred) + std::size_t bytes_transferred +#else + boost::system::error_code ec, + std::size_t bytes_transferred +#endif + ) { boost::ignore_unused(bytes_transferred); @@ -121,9 +179,16 @@ public: void on_write( +#ifdef BOOST_LATEST bool close, beast::error_code ec, - std::size_t bytes_transferred) + std::size_t bytes_transferred +#else + boost::system::error_code ec, + std::size_t bytes_transferred, + bool close +#endif + ) { boost::ignore_unused(bytes_transferred); @@ -149,8 +214,11 @@ public: { // Send a TCP shutdown beast::error_code ec; +#ifdef BOOST_LATEST stream_.socket().shutdown(tcp::socket::shutdown_send, ec); - +#else + socket_.shutdown(tcp::socket::shutdown_send, ec); +#endif // At this point the connection is closed gracefully } }; @@ -160,8 +228,13 @@ public: // Accepts incoming connections and launches the sessions class listener : public std::enable_shared_from_this<listener> { +#ifdef BOOST_LATEST net::io_context& ioc_; +#endif tcp::acceptor acceptor_; +#ifndef BOOST_LATEST + tcp::socket socket_; +#endif Server& m_server; public: @@ -169,11 +242,20 @@ public: net::io_context& ioc, tcp::endpoint endpoint, Server& server) +#ifdef BOOST_LATEST : ioc_(ioc) , acceptor_(net::make_strand(ioc)) +#else + : acceptor_(ioc) + , socket_(ioc) +#endif , m_server(server) { +#ifdef BOOST_VERSION beast::error_code ec; +#else + boost::system::error_code ec; +#endif // Open the acceptor acceptor_.open(endpoint.protocol(), ec); @@ -213,7 +295,11 @@ public: void run() { - do_accept(); +#ifndef BOOST_LATEST + if (!acceptor_.is_open()) + return; +#endif + do_accept(); } private: @@ -221,15 +307,28 @@ private: do_accept() { // The new connection gets its own strand +#ifdef BOOST_LATEST acceptor_.async_accept( net::make_strand(ioc_), beast::bind_front_handler( &listener::on_accept, shared_from_this())); +#else + acceptor_.async_accept( + socket_, + std::bind( + &listener::on_accept, + shared_from_this(), + std::placeholders::_1)); +#endif } void +#ifdef BOOST_LATEST on_accept(beast::error_code ec, tcp::socket socket) +#else + on_accept(boost::system::error_code ec) +#endif { if(ec) { @@ -239,7 +338,11 @@ private: { // Create the session and run it std::make_shared<session>( +#ifdef BOOST_LATEST std::move(socket), +#else + std::move(socket_), +#endif m_server)->run(); } @@ -10,10 +10,15 @@ #include <boost/asio/buffer.hpp> #include <boost/beast/core.hpp> #include <boost/beast/http.hpp> -#include <boost/beast/version.hpp> -#include <boost/beast/ssl.hpp> #include <boost/asio/dispatch.hpp> #include <boost/asio/ssl/context.hpp> +#ifdef BOOST_LATEST +#include <boost/beast/ssl.hpp> +#else +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ssl/stream.hpp> +#include <boost/asio/bind_executor.hpp> +#endif #include <boost/asio/strand.hpp> #include <boost/config.hpp> @@ -39,8 +44,15 @@ namespace { // Report a failure void -fail(beast::error_code ec, char const* what) +fail( +#ifdef BOOST_LATEST + beast::error_code ec, +#else + boost::system::error_code ec, +#endif + char const* what) { +#ifdef BOOST_LATEST // ssl::error::stream_truncated, also known as an SSL "short read", // indicates the peer closed the connection without performing the // required closing handshake (for example, Google does this to @@ -60,6 +72,7 @@ fail(beast::error_code ec, char const* what) if(ec == net::ssl::error::stream_truncated) return; +#endif std::cerr << what << ": " << ec.message() << "\n"; } @@ -67,7 +80,13 @@ fail(beast::error_code ec, char const* what) // Handles an HTTP server connection class session : public std::enable_shared_from_this<session> { +#ifdef BOOST_LATEST beast::ssl_stream<beast::tcp_stream> stream_; +#else + tcp::socket socket_; + ssl::stream<tcp::socket&> stream_; + boost::asio::strand<boost::asio::io_context::executor_type> strand_; +#endif beast::flat_buffer buffer_; Server& m_server; http::request<http::string_body> req_; @@ -80,6 +99,7 @@ class session : public std::enable_shared_from_this<session> res_ = sp; // Write the response +#ifdef BOOST_LATEST http::async_write( stream_, *sp, @@ -87,15 +107,38 @@ class session : public std::enable_shared_from_this<session> &session::on_write, shared_from_this(), sp->need_eof())); +#else + http::async_write( + stream_, + *sp, + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_write, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2, + sp->need_eof()))); +#endif } public: // Take ownership of the socket explicit session( +#ifdef BOOST_LATEST tcp::socket&& socket, +#else + tcp::socket socket, +#endif ssl::context& ctx, Server& server) +#ifdef BOOST_LATEST : stream_(std::move(socket), ctx) +#else + : socket_(std::move(socket)) + , stream_(socket_, ctx) + , strand_(socket_.get_executor()) +#endif , m_server(server) { } @@ -104,6 +147,7 @@ public: void run() { +#ifdef BOOST_LATEST // We need to be executing within a strand to perform async operations // on the I/O objects in this session. net::dispatch( @@ -111,8 +155,19 @@ public: beast::bind_front_handler( &session::on_run, shared_from_this())); +#else + stream_.async_handshake( + ssl::stream_base::server, + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_handshake, + shared_from_this(), + std::placeholders::_1))); +#endif } +#ifdef BOOST_LATEST void on_run() { @@ -127,9 +182,16 @@ public: &session::on_handshake, shared_from_this())); } +#endif void - on_handshake(beast::error_code ec) + on_handshake( +#ifdef BOOST_LATEST + beast::error_code ec +#else + boost::system::error_code ec +#endif + ) { if(ec) return fail(ec, "handshake"); @@ -144,6 +206,7 @@ public: // otherwise the operation behavior is undefined. req_ = {}; +#ifdef BOOST_LATEST // Set the timeout. beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30)); @@ -152,11 +215,25 @@ public: beast::bind_front_handler( &session::on_read, shared_from_this())); +#else + http::async_read(stream_, buffer_, req_, + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_read, + shared_from_this(), + std::placeholders::_1, + std::placeholders::_2))); +#endif } void on_read( +#ifdef BOOST_LATEST beast::error_code ec, +#else + boost::system::error_code ec, +#endif std::size_t bytes_transferred) { boost::ignore_unused(bytes_transferred); @@ -174,9 +251,16 @@ public: void on_write( +#ifdef BOOST_LATEST bool close, beast::error_code ec, - std::size_t bytes_transferred) + std::size_t bytes_transferred +#else + boost::system::error_code ec, + std::size_t bytes_transferred, + bool close +#endif + ) { boost::ignore_unused(bytes_transferred); @@ -200,6 +284,7 @@ public: void do_close() { +#ifdef BOOST_LATEST // Set the timeout. beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30)); @@ -208,6 +293,15 @@ public: beast::bind_front_handler( &session::on_shutdown, shared_from_this())); +#else + stream_.async_shutdown( + boost::asio::bind_executor( + strand_, + std::bind( + &session::on_shutdown, + shared_from_this(), + std::placeholders::_1))); +#endif } void @@ -225,9 +319,14 @@ public: // Accepts incoming connections and launches the sessions class listener : public std::enable_shared_from_this<listener> { +#ifdef BOOST_LATEST net::io_context& ioc_; +#endif ssl::context& ctx_; tcp::acceptor acceptor_; +#ifndef BOOST_LATEST + tcp::socket socket_; +#endif ::Server& m_server; public: @@ -235,13 +334,22 @@ public: net::io_context& ioc, ssl::context& ctx, tcp::endpoint endpoint, - Server& server) - : ioc_(ioc) - , ctx_(ctx) + Server& server) : +#ifdef BOOST_LATEST + ioc_(ioc), +#endif + ctx_(ctx) , acceptor_(ioc) +#ifndef BOOST_LATEST + , socket_(ioc) +#endif , m_server(server) { +#ifdef BOOST_LATEST beast::error_code ec; +#else + boost::system::error_code ec; +#endif // Open the acceptor acceptor_.open(endpoint.protocol(), ec); @@ -281,6 +389,10 @@ public: void run() { +#ifndef BOOST_LATEST + if(! acceptor_.is_open()) + return; +#endif do_accept(); } @@ -289,15 +401,28 @@ private: do_accept() { // The new connection gets its own strand +#ifdef BOOST_LATEST acceptor_.async_accept( net::make_strand(ioc_), beast::bind_front_handler( &listener::on_accept, shared_from_this())); +#else + acceptor_.async_accept( + socket_, + std::bind( + &listener::on_accept, + shared_from_this(), + std::placeholders::_1)); +#endif } void +#ifdef BOOST_LATEST on_accept(beast::error_code ec, tcp::socket socket) +#else + on_accept(boost::system::error_code ec) +#endif { if(ec) { @@ -307,7 +432,11 @@ private: { // Create the session and run it std::make_shared<session>( +#ifdef BOOST_LATEST std::move(socket), +#else + std::move(socket_), +#endif ctx_, m_server)->run(); } @@ -1,12 +1,21 @@ #pragma once +#include <boost/beast/version.hpp> + +// Support both boost in Debian unstable (BOOST_LATEST) and in stable (boost 1.67) +#if BOOST_VERSION >= 107100 +#define BOOST_LATEST +#endif + #include <memory> #include <string> #include <unordered_map> #include <boost/asio/dispatch.hpp> #include <boost/asio/strand.hpp> +#ifdef BOOST_LATEST #include <boost/beast/ssl.hpp> +#endif #include <boost/asio/ssl.hpp> #include "config.h" @@ -16,7 +25,11 @@ namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> namespace HTTPS { +#ifdef BOOST_LATEST static const ssl::context_base::method tls_method {ssl::context::tlsv13}; +#else +static const ssl::context_base::method tls_method {ssl::context::tlsv12}; +#endif class Server: public ::Server { @@ -1,5 +1,12 @@ #include "plugin.h" +#include <boost/beast/version.hpp> + +// Support both boost in Debian unstable (BOOST_LATEST) and in stable (boost 1.67) +#if BOOST_VERSION >= 107100 +#define BOOST_LATEST +#endif + #include <boost/dll/import.hpp> #include <boost/filesystem.hpp> @@ -22,7 +29,11 @@ void PluginLoader::load_plugins() for (auto& path: fs::recursive_directory_iterator(dir)) { if (path.is_regular_file() && path.path().extension() == ".so"s) { +#ifdef BOOST_LATEST dll::fs::path lib_path{path.path()}; +#else + boost::filesystem::path lib_path{path.path().generic_string()}; +#endif try { boost::shared_ptr<webserver_plugin_interface> plugin = dll::import<webserver_plugin_interface>(lib_path, "webserver_plugin", dll::load_mode::append_decorations); @@ -31,7 +42,7 @@ void PluginLoader::load_plugins() throw std::runtime_error("Bad interface version for "s + path.path().generic_string() + ": "s + std::to_string(plugin->version()) + " vs. "s + std::to_string(webserver_plugin_interface::interface_version)); std::string name{plugin->name()}; - if (m_plugins.contains(name)) + if (m_plugins.find(name) != m_plugins.end()) throw std::runtime_error("Plugin already exists: "s + name); std::cout << "Found plugin: " << name << " (" << path.path().string() << "), "; @@ -76,7 +87,7 @@ bool PluginLoader::validate_config() std::string plugin {it->second}; // check if plugin exists - if (!m_plugins.contains(plugin)) { + if (m_plugins.find(plugin) == m_plugins.end()) { std::cout << "Configured plugin " << plugin << " not found" << std::endl; return false; } diff --git a/plugins/static-files/Makefile b/plugins/static-files/Makefile index e0905a1..b928506 100644 --- a/plugins/static-files/Makefile +++ b/plugins/static-files/Makefile @@ -52,8 +52,8 @@ LIBS+= \ #-lstdc++fs else LIBS+= \ --lstdc++ -#-lstdc++fs +-lstdc++ \ +-lstdc++fs endif PROGSRC=\ @@ -1,7 +1,19 @@ +#include <boost/beast/version.hpp> + +// Support both boost in Debian unstable (BOOST_LATEST) and in stable (boost 1.67) +#if BOOST_VERSION >= 107100 +#define BOOST_LATEST +#endif + #include <boost/beast/core.hpp> #include <boost/beast/http.hpp> #include <boost/beast/version.hpp> +#ifdef BOOST_LATEST #include <boost/beast/ssl.hpp> +#else +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ssl/stream.hpp> +#endif #include <boost/asio/dispatch.hpp> #include <boost/asio/strand.hpp> #include <boost/config.hpp> |