#include "Listener.h" #include "BoostLog.h" #include "HttpSession.h" #include "SharedState.h" #include #include Listener::Listener(boost::asio::io_context &ioContext, const boost::asio::ip::tcp::endpoint &endpoint, const std::shared_ptr &state) : m_ioContext(ioContext), m_acceptor(ioContext), m_state(state) { boost::beast::error_code error; // Open the acceptor m_acceptor.open(endpoint.protocol(), error); if (error) { LOG(error) << error.message(); return; } // Allow address reuse m_acceptor.set_option(boost::asio::socket_base::reuse_address(true), error); if (error) { LOG(error) << error.message(); return; } // Bind to the server address m_acceptor.bind(endpoint, error); if (error) { LOG(error) << error.message(); return; } // Start listening for connections m_acceptor.listen(boost::asio::socket_base::max_listen_connections, error); if (error) { LOG(error) << error.message(); return; } } void Listener::startAccept() { 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::onAccept(boost::beast::error_code errorCode, std::shared_ptr socket) { if (errorCode) { if (errorCode == boost::asio::error::operation_aborted) return; LOG(error) << errorCode.message(); } else { // Launch a new session for this connection if (!m_state.expired()) { auto state = m_state.lock(); auto session = std::make_shared(std::move(*socket), state); session->run(); } } startAccept(); }