diff --git a/reporting/server/Listener.h b/reporting/server/Listener.h new file mode 100644 index 00000000..9f9d0ce8 --- /dev/null +++ b/reporting/server/Listener.h @@ -0,0 +1,194 @@ +//------------------------------------------------------------------------------ +/* + This file is part of rippled: https://github.com/ripple/rippled + Copyright (c) 2020 Ripple Labs Inc. + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef LISTENER_H +#define LISTENER_H + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +class SubscriptionManager; + +template +class Detector : public std::enable_shared_from_this> +{ + using std::enable_shared_from_this>::shared_from_this; + + boost::beast::tcp_stream stream_; + ssl::context& ctx_; + ReportingETL& etl_; + boost::beast::flat_buffer buffer_; + +public: + Detector( + tcp::socket&& socket, + ssl::context& ctx, + ReportingETL& etl) + : stream_(std::move(socket)) + , ctx_(ctx) + , etl_(etl) + { + } + + // Launch the detector + void + run() + { + // Set the timeout. + boost::beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30)); + // Detect a TLS handshake + async_detect_ssl( + stream_, + buffer_, + boost::beast::bind_front_handler( + &Detector::on_detect, + shared_from_this())); + } + + void + on_detect(boost::beast::error_code ec, bool result) + { + if(ec) + return httpFail(ec, "detect"); + + if(result) + { + // Launch SSL session + std::make_shared( + stream_.release_socket(), + ctx_, + etl_, + std::move(buffer_))->run(); + return; + } + + // Launch plain session + std::make_shared( + stream_.release_socket(), + etl_, + std::move(buffer_))->run(); + } +}; + +template +class Listener : public std::enable_shared_from_this> +{ + using std::enable_shared_from_this>::shared_from_this; + + net::io_context& ioc_; + ssl::context& ctx_; + tcp::acceptor acceptor_; + ReportingETL& etl_; + +public: + Listener( + net::io_context& ioc, + ssl::context& ctx, + tcp::endpoint endpoint, + ReportingETL& etl) + : ioc_(ioc) + , ctx_(ctx) + , acceptor_(net::make_strand(ioc)) + , etl_(etl) + { + boost::beast::error_code ec; + + // Open the acceptor + acceptor_.open(endpoint.protocol(), ec); + if(ec) + { + httpFail(ec, "open"); + return; + } + + // Allow address reuse + acceptor_.set_option(net::socket_base::reuse_address(true), ec); + if(ec) + { + httpFail(ec, "set_option"); + return; + } + + // Bind to the server address + acceptor_.bind(endpoint, ec); + if(ec) + { + httpFail(ec, "bind"); + return; + } + + // Start listening for connections + acceptor_.listen( + net::socket_base::max_listen_connections, ec); + if(ec) + { + httpFail(ec, "listen"); + return; + } + } + + // Start accepting incoming connections + void + run() + { + do_accept(); + } + +private: + void + do_accept() + { + // The new connection gets its own strand + acceptor_.async_accept( + net::make_strand(ioc_), + boost::beast::bind_front_handler( + &Listener::on_accept, + shared_from_this())); + } + + void + on_accept(boost::beast::error_code ec, tcp::socket socket) + { + if(ec) + { + httpFail(ec, "listener_accept"); + } + else + { + // Create the detector session and run it + std::make_shared>( + std::move(socket), + ctx_, + etl_)->run(); + } + + // Accept another connection + do_accept(); + } +}; + +#endif // LISTENER_H \ No newline at end of file diff --git a/server/websocket_server_async.cpp b/server/websocket_server_async.cpp index 370849f4..147fad40 100644 --- a/server/websocket_server_async.cpp +++ b/server/websocket_server_async.cpp @@ -167,8 +167,7 @@ main(int argc, char* argv[]) auto const threads = std::max(1, std::atoi(argv[1])); auto const config = parse_config(argv[2]); - - std::optional ctx = parse_certs(argv[3], argv[4]); + auto const ctx = parse_certs(argv[3], argv[4]); if (argc > 5) { @@ -187,6 +186,7 @@ main(int argc, char* argv[]) if (!ctx) { std::cerr << "Couldn't parse SSL certificates" << std::endl; + return EXIT_FAILURE; } boost::asio::io_context ioc{threads};