diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-04-04 19:24:16 +0200 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-04-04 19:24:16 +0200 |
commit | 1fcaed7a34cce8e55bb071d503bb583f715e7d37 (patch) | |
tree | 9c6bcaa267a66b902f308ee253a79da874780e55 | |
parent | 938fbe7a2f2f10a3abb530a9463e57fc20f40038 (diff) |
Serve configured sockets
-rw-r--r-- | TODO | 3 | ||||
-rw-r--r-- | config.cpp | 21 | ||||
-rw-r--r-- | config.h | 5 | ||||
-rw-r--r-- | http.cpp | 54 | ||||
-rw-r--r-- | http.h | 13 | ||||
-rw-r--r-- | https.cpp | 57 | ||||
-rw-r--r-- | https.h | 21 | ||||
-rw-r--r-- | server.cpp | 56 | ||||
-rw-r--r-- | server.h | 12 | ||||
-rw-r--r-- | webserver.conf | 20 |
10 files changed, 179 insertions, 83 deletions
@@ -1,7 +1,4 @@ -HTTP+HTTPS: https://www.boost.org/doc/libs/1_72_0/libs/beast/doc/html/beast/examples.html#beast.examples.servers Certbot: https://certbot.eff.org/lets-encrypt/debianbuster-other Webbox Debian 10 alternative hosts www, lists, ... - -Selective sites per Socket @@ -40,7 +40,7 @@ void Config::readConfigfile(std::string filename) if (x.first == "name"s) { site_struct.name = x.second.data(); } else if (x.first == "host"s) { - site_struct.host = x.second.data(); + site_struct.hosts.insert(x.second.data()); } else if (x.first == "path"s) { Path path; auto attrs = x.second.get_child("<xmlattr>"); @@ -91,6 +91,15 @@ void Config::readConfigfile(std::string filename) } } } + + // expand socket sites + for (auto& socket: m_sockets) { + if (socket.serve_sites.empty()) { + for (const auto& site: m_sites) { + socket.serve_sites.push_back(site.name); + } + } + } } Config::Config(const std::string& filename) @@ -143,7 +152,10 @@ void Config::dump() const std::cout << std::endl; for (const auto& site: m_sites) { - std::cout << "Site: " << site.name << ": " << site.host << std::endl; + std::cout << "Site: " << site.name << ":"; + for (const auto& host: site.hosts) + std::cout << " " << host; + std::cout << std::endl; if (site.paths.size() == 0) std::cout << " Warning: No paths configured." << std::endl; for (const auto& path: site.paths) { @@ -160,6 +172,11 @@ void Config::dump() const std::cout << " Key: " << socket.key_path.generic_string() << std::endl; std::cout << " Cert: " << socket.cert_path.generic_string() << std::endl; } + std::cout << " Serving:"; + for (const auto& site: socket.serve_sites) { + std::cout << " " << site; + } + std::cout << std::endl; } std::cout << "=============================================" << std::endl; } @@ -3,6 +3,7 @@ #include <filesystem> #include <string> #include <unordered_map> +#include <unordered_set> #include <vector> namespace fs = std::filesystem; @@ -23,7 +24,7 @@ struct Path struct Site { std::string name; - std::string host; + std::unordered_set<std::string> hosts; std::vector<Path> paths; }; @@ -38,7 +39,7 @@ struct Socket std::string address; std::string port; SocketProtocol protocol; - std::vector<std::string> serve_sites; // if empty, serve all configured sites // TODO: implement + std::vector<std::string> serve_sites; // if empty, automatically expand to all configured sites fs::path cert_path; fs::path key_path; }; @@ -153,6 +153,7 @@ handle_request( // Build the path to the requested file std::string path = path_cat(doc_root, req.target()); + std::cout << "DEBUG: " << req["host"] << std::endl; if(req.target().back() == '/') path.append("index.html"); @@ -446,35 +447,28 @@ private: namespace HTTP { -int server(Config& config) -{ - // TODO: Config - auto const address = net::ip::make_address(config.Sockets()[0].address); - auto const port = static_cast<unsigned short>(std::atoi(config.Sockets()[0].port.data())); - auto const doc_root = std::make_shared<std::string>(config.Sites()[0].paths[0].params.at("target")); - auto const threads = std::max<int>(1, config.Threads()); - - // The io_context is required for all I/O - net::io_context ioc{threads}; - - // Create and launch a listening port - std::make_shared<listener>( - ioc, - tcp::endpoint{address, port}, - doc_root)->run(); - - // Run the I/O service on the requested number of threads - std::vector<std::thread> v; - v.reserve(threads - 1); - for(auto i = threads - 1; i > 0; --i) - v.emplace_back( - [&ioc] - { - ioc.run(); - }); - ioc.run(); - - return EXIT_SUCCESS; -} + Server::Server(Config& config, boost::asio::io_context& ioc, const Socket& socket): ::Server(config, ioc), m_socket(socket) + { + } + + Server::~Server() + { + } + + int Server::start() + { + // TODO: Config + auto const address = net::ip::make_address(m_socket.address); + auto const port = static_cast<unsigned short>(std::atoi(m_socket.port.data())); + auto const doc_root = std::make_shared<std::string>(m_config.Sites()[0].paths[0].params.at("target")); + + // Create and launch a listening port + std::make_shared<listener>( + m_ioc, + tcp::endpoint{address, port}, + doc_root)->run(); + + return EXIT_SUCCESS; + } } // namespace HTTP @@ -1,9 +1,20 @@ #pragma once +#include <boost/asio/dispatch.hpp> +#include <boost/asio/strand.hpp> + #include "config.h" +#include "server.h" namespace HTTP { -int server(Config& config); +class Server: public ::Server +{ + const Socket& m_socket; +public: + Server(Config& config, boost::asio::io_context& ioc, const Socket& socket); + virtual ~Server(); + int start() override; +}; } // namespace HTTP @@ -515,42 +515,31 @@ private: namespace HTTPS { -int server(Config& config) +Server::Server(Config& config, boost::asio::io_context& ioc, const Socket& socket): ::Server(config, ioc), m_socket(socket) { - // TODO: Config - auto const address = net::ip::make_address(config.Sockets()[0].address); - auto const port = static_cast<unsigned short>(std::atoi(config.Sockets()[0].port.data())); - auto const doc_root = std::make_shared<std::string>(config.Sites()[0].paths[0].params.at("target")); - auto const threads = std::max<int>(1, config.Threads()); - - // The io_context is required for all I/O - net::io_context ioc{threads}; - - // The SSL context is required, and holds certificates - ssl::context ctx{ssl::context::tlsv13}; - - // This holds the self-signed certificate used by the server - load_server_certificate(ctx, config.Sockets()[0].cert_path, config.Sockets()[0].key_path); // TODO: config - - // Create and launch a listening port - std::make_shared<listener>( - ioc, - ctx, - tcp::endpoint{address, port}, - doc_root)->run(); - - // Run the I/O service on the requested number of threads - std::vector<std::thread> v; - v.reserve(threads - 1); - for(auto i = threads - 1; i > 0; --i) - v.emplace_back( - [&ioc] - { - ioc.run(); - }); - ioc.run(); + // This holds the self-signed certificate used by the server + load_server_certificate(m_ctx, m_socket.cert_path, m_socket.key_path); +} + +Server::~Server() +{ +} - return EXIT_SUCCESS; +int Server::start() +{ + // TODO: Config + auto const address = net::ip::make_address(m_socket.address); + auto const port = static_cast<unsigned short>(std::atoi(m_socket.port.data())); + auto const doc_root = std::make_shared<std::string>(m_config.Sites()[0].paths[0].params.at("target")); + + // Create and launch a listening port + std::make_shared<listener>( + m_ioc, + m_ctx, + tcp::endpoint{address, port}, + doc_root)->run(); + + return EXIT_SUCCESS; } } // namespace HTTPS @@ -1,9 +1,28 @@ #pragma once +#include <boost/asio/dispatch.hpp> +#include <boost/asio/strand.hpp> +#include <boost/beast/ssl.hpp> +#include <boost/asio/ssl.hpp> + #include "config.h" +#include "server.h" + +namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> namespace HTTPS { -int server(Config& config); +class Server: public ::Server +{ + // The SSL context is required, and holds certificates + ssl::context m_ctx{ssl::context::tlsv13}; + const Socket& m_socket; + +public: + Server(Config& config, boost::asio::io_context& ioc, const Socket& socket); + virtual ~Server(); + + int start() override; +}; } @@ -1,10 +1,62 @@ +#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/strand.hpp> +#include <boost/config.hpp> + +#include <thread> +#include <vector> + #include "server.h" #include "http.h" #include "https.h" +namespace beast = boost::beast; // from <boost/beast.hpp> +namespace http = beast::http; // from <boost/beast/http.hpp> +namespace net = boost::asio; // from <boost/asio.hpp> +namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> + +Server::Server(Config& config, boost::asio::io_context& ioc): m_config(config), m_ioc(ioc) +{ +} + +Server::~Server() +{ +} + int server(Config& config) { - //return HTTP::server(config); - return HTTPS::server(config); + auto const threads = std::max<int>(1, config.Threads()); + + boost::asio::io_context ioc{threads}; + + std::vector<std::shared_ptr<Server>> servers; + + const auto& sockets {config.Sockets()}; + for (const auto& socket: sockets) { + if (socket.protocol == SocketProtocol::HTTP) { + servers.push_back(std::make_shared<HTTP::Server>(config, ioc, socket)); + } else { + servers.push_back(std::make_shared<HTTPS::Server>(config, ioc, socket)); + } + servers.back()->start(); + } + + // Run the I/O service on the requested number of threads + std::vector<std::thread> v; + v.reserve(threads - 1); + for(auto i = threads - 1; i > 0; --i) + v.emplace_back( + [&ioc] + { + ioc.run(); + }); + ioc.run(); + + return EXIT_SUCCESS; } + @@ -6,4 +6,16 @@ using namespace std::string_literals; static const std::string VersionString{ "Webserver "s + std::string{VERSION} }; +class Server +{ +protected: + Config& m_config; + boost::asio::io_context& m_ioc; + +public: + Server(Config& config, boost::asio::io_context& ioc); + virtual ~Server(); + virtual int start() = 0; +}; + int server(Config& config); diff --git a/webserver.conf b/webserver.conf index 2036f67..46d4120 100644 --- a/webserver.conf +++ b/webserver.conf @@ -11,6 +11,8 @@ <site> <name>antcom.de</name> <host>lists.antcom.de</host> + <host>antcom.de</host> + <host>www.antcom.de</host> <path requested="/" type="files"> <target>/home/ernie/homepage/test</target> </path> @@ -21,11 +23,15 @@ </path> --> </site> - <!-- <site> - <name>reichwein.it</name> - <host>reichwein.it</host> + <name>marx</name> + <host>marx.antcom.de</host> + <path requested="/" type="files"> + <target>/home/ernie/homepage/test1</target> + </path> </site> + <!-- + reichwein.it danielareichwein.de rolandreichwein.de kneipenband.com @@ -36,20 +42,18 @@ <address>127.0.0.1</address> <port>8080</port> <protocol>http</protocol> - <certpath>/home/ernie/code/webserver/fullchain.pem</certpath> - <keypath>/home/ernie/code/webserver/privkey.pem</keypath> <!-- <site>antcom.de</site> <site>reichwein.it</site> --> </socket> - <!-- <socket> <address>127.0.0.1</address> - <port>443</port> + <port>8081</port> <protocol>https</protocol> + <certpath>/home/ernie/code/webserver/fullchain.pem</certpath> + <keypath>/home/ernie/code/webserver/privkey.pem</keypath> </socket> - --> </sockets> </webserver> |