From cf38d96543b2086a863ef4823ee769ec45cc45a4 Mon Sep 17 00:00:00 2001 From: zousar <2936246+zousar@users.noreply.github.com> Date: Thu, 27 Jan 2022 01:01:05 -0700 Subject: Handle HTTP port collisions when initializing server (#40) --- zenhttp/httpsys.cpp | 55 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 41 insertions(+), 14 deletions(-) (limited to 'zenhttp/httpsys.cpp') diff --git a/zenhttp/httpsys.cpp b/zenhttp/httpsys.cpp index b3d109b6a..3c57f7ce3 100644 --- a/zenhttp/httpsys.cpp +++ b/zenhttp/httpsys.cpp @@ -746,7 +746,7 @@ HttpSysServer::~HttpSysServer() } } -void +int HttpSysServer::InitializeServer(int BasePort) { using namespace std::literals; @@ -762,7 +762,7 @@ HttpSysServer::InitializeServer(int BasePort) { ZEN_ERROR("Failed to create server session for '{}': {:#x}", WideToUtf8(WildcardUrlPath), Result); - return; + return BasePort; } Result = HttpCreateUrlGroup(m_HttpSessionId, &m_HttpUrlGroupId, 0); @@ -771,17 +771,29 @@ HttpSysServer::InitializeServer(int BasePort) { ZEN_ERROR("Failed to create URL group for '{}': {:#x}", WideToUtf8(WildcardUrlPath), Result); - return; + return BasePort; } + int EffectivePort = BasePort; + Result = HttpAddUrlToUrlGroup(m_HttpUrlGroupId, WildcardUrlPath.c_str(), HTTP_URL_CONTEXT(0), 0); + // Sharing violation implies the port is being used by another process + for (int PortOffset = 1; (Result == ERROR_SHARING_VIOLATION) && (PortOffset < 10); ++PortOffset) + { + EffectivePort = BasePort + (PortOffset * 100); + WildcardUrlPath.Reset(); + WildcardUrlPath << u8"http://*:"sv << int64_t(EffectivePort) << u8"/"sv; + + Result = HttpAddUrlToUrlGroup(m_HttpUrlGroupId, WildcardUrlPath.c_str(), HTTP_URL_CONTEXT(0), 0); + } + m_BaseUris.clear(); if (Result == NO_ERROR) { m_BaseUris.push_back(WildcardUrlPath.c_str()); } - else + else if (Result == ERROR_ACCESS_DENIED) { // If we can't register the wildcard path, we fall back to local paths // This local paths allow requests originating locally to function, but will not allow @@ -792,14 +804,26 @@ HttpSysServer::InitializeServer(int BasePort) const std::u8string_view Hosts[] = {u8"[::1]"sv, u8"localhost"sv, u8"127.0.0.1"sv}; - for (const std::u8string_view Host : Hosts) + ULONG InternalResult = ERROR_SHARING_VIOLATION; + for (int PortOffset = 0; (InternalResult == ERROR_SHARING_VIOLATION) && (PortOffset < 10); ++PortOffset) { - WideStringBuilder<64> LocalUrlPath; - LocalUrlPath << u8"http://"sv << Host << u8":"sv << int64_t(BasePort) << u8"/"sv; + EffectivePort = BasePort + (PortOffset * 100); - if (HttpAddUrlToUrlGroup(m_HttpUrlGroupId, LocalUrlPath.c_str(), HTTP_URL_CONTEXT(0), 0) == NO_ERROR) + for (const std::u8string_view Host : Hosts) { - m_BaseUris.push_back(LocalUrlPath.c_str()); + WideStringBuilder<64> LocalUrlPath; + LocalUrlPath << u8"http://"sv << Host << u8":"sv << int64_t(EffectivePort) << u8"/"sv; + + InternalResult = HttpAddUrlToUrlGroup(m_HttpUrlGroupId, LocalUrlPath.c_str(), HTTP_URL_CONTEXT(0), 0); + + if (InternalResult == NO_ERROR) + { + m_BaseUris.push_back(LocalUrlPath.c_str()); + } + else + { + break; + } } } } @@ -808,7 +832,7 @@ HttpSysServer::InitializeServer(int BasePort) { ZEN_ERROR("Failed to add base URL to URL group for '{}': {:#x}", WideToUtf8(WildcardUrlPath), Result); - return; + return BasePort; } HTTP_BINDING_INFO HttpBindingInfo = {{0}, 0}; @@ -823,7 +847,7 @@ HttpSysServer::InitializeServer(int BasePort) { ZEN_ERROR("Failed to create request queue for '{}': {:#x}", WideToUtf8(m_BaseUris.front()), Result); - return; + return EffectivePort; } HttpBindingInfo.Flags.Present = 1; @@ -835,7 +859,7 @@ HttpSysServer::InitializeServer(int BasePort) { ZEN_ERROR("Failed to set server binding property for '{}': {:#x}", WideToUtf8(m_BaseUris.front()), Result); - return; + return EffectivePort; } // Create I/O completion port @@ -853,6 +877,8 @@ HttpSysServer::InitializeServer(int BasePort) ZEN_INFO("Started http.sys server at '{}'", WideToUtf8(m_BaseUris.front())); } + + return EffectivePort; } void @@ -1603,11 +1629,12 @@ InitialRequestHandler::HandleCompletion(ULONG IoResult, ULONG_PTR NumberOfBytesT // HttpServer interface implementation // -void +int HttpSysServer::Initialize(int BasePort) { - InitializeServer(BasePort); + int EffectivePort = InitializeServer(BasePort); StartServer(); + return EffectivePort; } void -- cgit v1.2.3