64 lines
1.9 KiB
C++
64 lines
1.9 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)
|
|
: 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::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));
|
|
session->run();
|
|
}
|
|
startAccept();
|
|
}
|