62 lines
1.9 KiB
C++
62 lines
1.9 KiB
C++
#include "Listener.h"
|
|
#include "BoostLog.h"
|
|
#include "HttpSession.h"
|
|
#include "SharedState.h"
|
|
#include <boost/asio/strand.hpp>
|
|
#include <boost/beast/core/error.hpp>
|
|
|
|
Listener::Listener(boost::asio::io_context &ioContext, const boost::asio::ip::tcp::endpoint &endpoint,
|
|
const std::shared_ptr<SharedState> &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::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::onAccept(boost::beast::error_code errorCode, std::shared_ptr<boost::asio::ip::tcp::socket> 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<HttpSession>(std::move(*socket), state);
|
|
session->run();
|
|
}
|
|
}
|
|
startAccept();
|
|
}
|