Older/Server/Listener.cpp
2023-07-21 16:17:01 +08:00

65 lines
2.0 KiB
C++

#include "Listener.h"
#include "HttpSession.h"
#include <boost/asio.hpp>
#include <iostream>
Listener::Listener(boost::asio::io_context &ioc, boost::asio::ip::tcp::endpoint endpoint,
std::shared_ptr<SharedState> const &state)
: m_ioContext(ioc), m_acceptor(ioc), m_state(state) {
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::ip::tcp::socket>(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<boost::asio::ip::tcp::socket> 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<HttpSession>(std::move(*socket), m_state);
session->run();
}
startAccept();
}