diff options
| author | Dan Engelbrecht <[email protected]> | 2023-11-09 20:50:46 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-11-09 20:50:46 +0100 |
| commit | c289d408765fe47d54987bd49fcf277f2419104a (patch) | |
| tree | d76ac1fae0a2413f080c4ecfb0e7f281ed50f271 /src/zenhttp/servers/httpasio.cpp | |
| parent | 0.2.31-pre1 (diff) | |
| download | zen-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.cpp | 47 |
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 |