#include "Listener.h" #include "HttpSession.h" #include #include Listener::Listener(boost::asio::io_context &ioc, boost::asio::ip::tcp::endpoint endpoint) : m_ioContext(ioc), m_acceptor(ioc) { boost::beast::error_code ec; // Open the acceptor m_acceptor.open(endpoint.protocol(), ec); if (ec) { fail(ec, "open"); return; } // Allow address reuse m_acceptor.set_option(boost::asio::socket_base::reuse_address(true), ec); if (ec) { fail(ec, "set_option"); return; } // Bind to the server address m_acceptor.bind(endpoint, ec); if (ec) { fail(ec, "bind"); return; } // Start listening for connections m_acceptor.listen(boost::asio::socket_base::max_listen_connections, ec); if (ec) { fail(ec, "listen"); return; } } void Listener::startAccept() { // The new connection gets its own strand auto client = std::make_shared(boost::asio::make_strand(m_ioContext)); m_acceptor.async_accept( *client, [self{shared_from_this()}, client](const boost::system::error_code &ec) { self->onAccept(ec, client); }); } void Listener::fail(boost::beast::error_code ec, char const *what) { // Don't report on canceled operations if (ec == boost::asio::error::operation_aborted) return; std::cerr << what << ": " << ec.message() << "\n"; } // Handle a connection void Listener::onAccept(boost::beast::error_code ec, std::shared_ptr socket) { if (ec) { if (ec == boost::asio::error::operation_aborted) return; std::cerr << "accept: " << ec.message() << "\n"; } else { // Launch a new session for this connection auto session = std::make_shared(std::move(*socket)); session->run(); } startAccept(); }