65 lines
2.0 KiB
C++
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();
|
|||
|
}
|