aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp/servers/httpasio.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2023-11-09 20:50:46 +0100
committerGitHub <[email protected]>2023-11-09 20:50:46 +0100
commitc289d408765fe47d54987bd49fcf277f2419104a (patch)
treed76ac1fae0a2413f080c4ecfb0e7f281ed50f271 /src/zenhttp/servers/httpasio.cpp
parent0.2.31-pre1 (diff)
downloadzen-c289d408765fe47d54987bd49fcf277f2419104a.tar.xz
zen-c289d408765fe47d54987bd49fcf277f2419104a.zip
option for zenserver - `--http-forceloopback` (#516)
* New option for zenserver - `--http-forceloopback` which forces opening of the server http server using loopback (local) connection (UE-199776) * add fallback to local connection for asio if we get access denied on public port
Diffstat (limited to 'src/zenhttp/servers/httpasio.cpp')
-rw-r--r--src/zenhttp/servers/httpasio.cpp47
1 files changed, 30 insertions, 17 deletions
diff --git a/src/zenhttp/servers/httpasio.cpp b/src/zenhttp/servers/httpasio.cpp
index 75852fe89..c62aca001 100644
--- a/src/zenhttp/servers/httpasio.cpp
+++ b/src/zenhttp/servers/httpasio.cpp
@@ -62,7 +62,7 @@ public:
HttpAsioServerImpl();
~HttpAsioServerImpl();
- int Start(uint16_t Port, int ThreadCount);
+ int Start(uint16_t Port, bool ForceLooopback, int ThreadCount);
void Stop();
void RegisterService(const char* UrlPath, HttpService& Service);
HttpService* RouteRequest(std::string_view Url);
@@ -569,7 +569,7 @@ HttpServerConnection::HandleRequest()
struct HttpAcceptor
{
- HttpAcceptor(HttpAsioServerImpl& Server, asio::io_service& IoService, uint16_t BasePort)
+ HttpAcceptor(HttpAsioServerImpl& Server, asio::io_service& IoService, uint16_t BasePort, bool ForceLoopback)
: m_Server(Server)
, m_IoService(IoService)
, m_Acceptor(m_IoService, asio::ip::tcp::v6())
@@ -587,25 +587,36 @@ struct HttpAcceptor
m_Acceptor.set_option(asio::socket_base::receive_buffer_size(128 * 1024));
m_Acceptor.set_option(asio::socket_base::send_buffer_size(256 * 1024));
- uint16_t EffectivePort = BasePort;
+ asio::ip::address_v6 BindAddress = ForceLoopback ? asio::ip::address_v6::loopback() : asio::ip::address_v6::any();
+ uint16_t EffectivePort = BasePort;
asio::error_code BindErrorCode;
- m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), EffectivePort), BindErrorCode);
+ m_Acceptor.bind(asio::ip::tcp::endpoint(BindAddress, EffectivePort), BindErrorCode);
+ if (BindErrorCode == asio::error::access_denied && !BindAddress.is_loopback())
+ {
+ // Access denied for a public port - lets try fall back to local port only
+ BindAddress = asio::ip::address_v6::loopback();
+ m_Acceptor.bind(asio::ip::tcp::endpoint(BindAddress, EffectivePort), BindErrorCode);
+ }
// Sharing violation implies the port is being used by another process
for (uint16_t PortOffset = 1; (BindErrorCode == asio::error::address_in_use) && (PortOffset < 10); ++PortOffset)
{
EffectivePort = BasePort + (PortOffset * 100);
- m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), EffectivePort), BindErrorCode);
+ m_Acceptor.bind(asio::ip::tcp::endpoint(BindAddress, EffectivePort), BindErrorCode);
}
if (BindErrorCode == asio::error::access_denied)
{
EffectivePort = 0;
- m_Acceptor.bind(asio::ip::tcp::endpoint(asio::ip::address_v6::any(), EffectivePort), BindErrorCode);
+ m_Acceptor.bind(asio::ip::tcp::endpoint(BindAddress, EffectivePort), BindErrorCode);
}
if (BindErrorCode)
{
ZEN_ERROR("Unable open asio service, error '{}'", BindErrorCode.message());
}
+ else if (BindAddress.is_loopback())
+ {
+ ZEN_INFO("Registered local-only handler 'http://{}:{}/' - this is not accessible from remote hosts", "[::1]", EffectivePort);
+ }
#if ZEN_PLATFORM_WINDOWS
// On Windows, loopback connections can take advantage of a faster code path optionally with this flag.
@@ -627,7 +638,7 @@ struct HttpAcceptor
#endif
m_Acceptor.listen();
- ZEN_INFO("Started asio server at port '{}'", EffectivePort);
+ ZEN_INFO("Started asio server at 'http://{}:{}'", BindAddress.is_loopback() ? "[::1]" : "*", EffectivePort);
}
void Start()
@@ -831,13 +842,13 @@ HttpAsioServerImpl::~HttpAsioServerImpl()
}
int
-HttpAsioServerImpl::Start(uint16_t Port, int ThreadCount)
+HttpAsioServerImpl::Start(uint16_t Port, bool ForceLooopback, int ThreadCount)
{
ZEN_ASSERT(ThreadCount > 0);
ZEN_INFO("starting asio http with {} service threads", ThreadCount);
- m_Acceptor.reset(new asio_http::HttpAcceptor(*this, m_IoService, Port));
+ m_Acceptor.reset(new asio_http::HttpAcceptor(*this, m_IoService, Port, ForceLooopback));
m_Acceptor->Start();
// This should consist of a set of minimum threads and grow on demand to
@@ -926,7 +937,7 @@ namespace zen {
class HttpAsioServer : public HttpServer
{
public:
- HttpAsioServer(unsigned int ThreadCount);
+ HttpAsioServer(bool ForceLoopback, unsigned int ThreadCount);
~HttpAsioServer();
virtual void RegisterService(HttpService& Service) override;
@@ -937,14 +948,16 @@ public:
private:
Event m_ShutdownEvent;
- int m_BasePort = 0;
- unsigned int m_ThreadCount = 0;
+ int m_BasePort = 0;
+ bool m_ForceLoopback = false;
+ unsigned int m_ThreadCount = 0;
std::unique_ptr<asio_http::HttpAsioServerImpl> m_Impl;
};
-HttpAsioServer::HttpAsioServer(unsigned int ThreadCount)
-: m_ThreadCount(ThreadCount != 0 ? ThreadCount : Max(std::thread::hardware_concurrency(), 8u))
+HttpAsioServer::HttpAsioServer(bool ForceLoopback, unsigned int ThreadCount)
+: m_ForceLoopback(ForceLoopback)
+, m_ThreadCount(ThreadCount != 0 ? ThreadCount : Max(std::thread::hardware_concurrency(), 8u))
, m_Impl(std::make_unique<asio_http::HttpAsioServerImpl>())
{
ZEN_DEBUG("Request object size: {} ({:#x})", sizeof(HttpRequestParser), sizeof(HttpRequestParser));
@@ -981,7 +994,7 @@ HttpAsioServer::RegisterService(HttpService& Service)
int
HttpAsioServer::Initialize(int BasePort)
{
- m_BasePort = m_Impl->Start(gsl::narrow<uint16_t>(BasePort), m_ThreadCount);
+ m_BasePort = m_Impl->Start(gsl::narrow<uint16_t>(BasePort), m_ForceLoopback, m_ThreadCount);
return m_BasePort;
}
@@ -1036,9 +1049,9 @@ HttpAsioServer::RequestExit()
}
Ref<HttpServer>
-CreateHttpAsioServer(unsigned int ThreadCount)
+CreateHttpAsioServer(bool ForceLoopback, unsigned int ThreadCount)
{
- return Ref<HttpServer>{new HttpAsioServer(ThreadCount)};
+ return Ref<HttpServer>{new HttpAsioServer(ForceLoopback, ThreadCount)};
}
} // namespace zen