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>  | 
