Commit 7b36af9b authored by Alessio Netti's avatar Alessio Netti
Browse files

Hostname resolution in REST API

- Also added support for multiple accept sockets when a single hostname
maps to multiple IPs
parent da72f15e
......@@ -185,7 +185,9 @@ public:
return;
}
ServerLOG(info) << "Starting...";
startAccept();
for(size_t idx=0; idx<_acceptors.size(); idx++) {
startAccept(idx);
}
_isRunning = true;
ServerLOG(info) << "Started!";
......@@ -203,8 +205,10 @@ public:
ServerLOG(info) << "Stopping...";
_isRunning = false;
_acceptor->cancel();
_acceptor->close();
for(auto &acc : _acceptors) {
acc->cancel();
acc->close();
}
ServerLOG(info) << "Stopped!";
}
......@@ -268,16 +272,17 @@ private:
* @brief Starts asynchronous wait for a connection. Returns immediately.
* On a connection attempt handle_request() is called.
*/
void startAccept() {
void startAccept(size_t idx) {
// Start asynchronous wait until we get a connection.
// On connection start launch the session, transferring ownership of the socket
// This will receive the new connection
auto newSocket = new tcp::socket(_io);
_acceptor->async_accept(*newSocket, _remoteEndpoint,
std::bind(&RESTHttpsServer::handle_session,
this,
std::ref(*newSocket),
std::ref(*_ctx)));
_acceptors[idx]->async_accept(*newSocket, _remoteEndpoint,
std::bind(&RESTHttpsServer::handle_session,
this,
std::ref(*newSocket),
std::ref(*_ctx),
idx));
}
/**
......@@ -288,8 +293,9 @@ private:
*
* @param socket Socket for the session
* @param ctx SSL context object
* @param accIdx Index of the acceptor associated to this session
*/
void handle_session(tcp::socket& socket, ssl::context& ctx);
void handle_session(tcp::socket& socket, ssl::context& ctx, size_t accIdx);
/**
* @brief Matches the request to the associated endpoint handler and sends a
......@@ -346,7 +352,7 @@ private:
boost::asio::io_context& _io; /**< Central io_context for all I/O */
std::shared_ptr<ssl::context> _ctx; /**< SSL context hold the certificates and is required for https support */
std::unique_ptr<tcp::acceptor> _acceptor; /**< Acceptor receives incoming connections */
std::vector<std::shared_ptr<tcp::acceptor>> _acceptors; /**< Acceptors receive incoming connections */
tcp::endpoint _remoteEndpoint; /**< Used to store information about the connecting client endpoint */
......
......@@ -96,24 +96,36 @@ RESTHttpsServer::RESTHttpsServer(serverSettings_t settings, boost::asio::io_cont
_ctx->use_tmp_dh(boost::asio::buffer(s_dh2048_pem));
try {
auto const address = boost::asio::ip::make_address(settings.host);
auto const port = static_cast<unsigned short>(std::stoul(settings.port));
_acceptor = std::unique_ptr<tcp::acceptor>(new tcp::acceptor(io, {address, port}));
_acceptor->set_option(tcp::acceptor::reuse_address(true));
// Resolving the hostname-port pair given in the configuration
boost::asio::ip::tcp::resolver resolver(io);
boost::system::error_code ec;
boost::asio::ip::tcp::resolver::query query(settings.host, settings.port);
boost::asio::ip::tcp::resolver::iterator iter = resolver.resolve(query, ec);
if(ec) {
ServerLOG(fatal) << "RestAPI cannot resolve hostname " << settings.host << " with port " << settings.port << "!" << std::endl;
throw std::runtime_error("RestAPI host resolution error");
}
// Instantiating one accept socket per resolved IP
for (; iter != boost::asio::ip::tcp::resolver::iterator(); ++iter) {
auto acceptor = std::shared_ptr<tcp::acceptor>(new tcp::acceptor(io, iter->endpoint()));
acceptor->set_option(tcp::acceptor::reuse_address(true));
_acceptors.push_back(acceptor);
}
} catch (const std::exception& e) {
ServerLOG(fatal) << "RestAPI address invalid! Please make sure IP address and port are valid!";
std::runtime_error re("RESTAPI config error");
std::runtime_error re("RestAPI config error");
throw re;
}
}
void RESTHttpsServer::handle_session(tcp::socket& socket, ssl::context& ctx) {
void RESTHttpsServer::handle_session(tcp::socket& socket, ssl::context& ctx, size_t accIdx) {
if(_isRunning) {
ServerLOG(debug) << _remoteEndpoint.address().to_string() << ":" << _remoteEndpoint.port() << " connecting";
// Launching a new async accept call
startAccept();
startAccept(accIdx);
} else {
delete &socket;
return;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment