diff options
| author | Stefan Boberg <[email protected]> | 2023-10-13 14:46:49 +0200 |
|---|---|---|
| committer | GitHub <[email protected]> | 2023-10-13 14:46:49 +0200 |
| commit | c3fad0e98576ff5dee3ee63725459d46e201fa34 (patch) | |
| tree | 91455786fac76ffb6a83ff24620329780ce08545 /src/zenhttp/transports | |
| parent | improved http.sys initialization diagnostics and amended logic for dedicated ... (diff) | |
| download | zen-c3fad0e98576ff5dee3ee63725459d46e201fa34.tar.xz zen-c3fad0e98576ff5dee3ee63725459d46e201fa34.zip | |
support for multiple http servers (#473)
* added support for having multiple http servers active in one session
* added configuration API to pluggable transports
* removed pimpl pattern from some pluggable transports implementations
Diffstat (limited to 'src/zenhttp/transports')
| -rw-r--r-- | src/zenhttp/transports/asiotransport.cpp | 38 | ||||
| -rw-r--r-- | src/zenhttp/transports/asiotransport.h | 2 | ||||
| -rw-r--r-- | src/zenhttp/transports/dlltransport.cpp | 115 | ||||
| -rw-r--r-- | src/zenhttp/transports/dlltransport.h | 23 | ||||
| -rw-r--r-- | src/zenhttp/transports/winsocktransport.cpp | 163 | ||||
| -rw-r--r-- | src/zenhttp/transports/winsocktransport.h | 2 |
6 files changed, 166 insertions, 177 deletions
diff --git a/src/zenhttp/transports/asiotransport.cpp b/src/zenhttp/transports/asiotransport.cpp index b8fef8f5f..ab053a748 100644 --- a/src/zenhttp/transports/asiotransport.cpp +++ b/src/zenhttp/transports/asiotransport.cpp @@ -31,18 +31,19 @@ struct AsioTransportAcceptor; class AsioTransportPlugin : public TransportPlugin, RefCounted { public: - AsioTransportPlugin(uint16_t BasePort, unsigned int ThreadCount); + AsioTransportPlugin(); ~AsioTransportPlugin(); virtual uint32_t AddRef() const override; virtual uint32_t Release() const override; + virtual void Configure(const char* OptionTag, const char* OptionValue) override; virtual void Initialize(TransportServer* ServerInterface) override; virtual void Shutdown() override; virtual bool IsAvailable() override; private: bool m_IsOk = true; - uint16_t m_BasePort = 0; + uint16_t m_BasePort = 8558; int m_ThreadCount = 0; asio::io_service m_IoService; @@ -349,9 +350,7 @@ AsioTransportConnection::OnResponseDataSent(const asio::error_code& Ec, std::siz ////////////////////////////////////////////////////////////////////////// -AsioTransportPlugin::AsioTransportPlugin(uint16_t BasePort, unsigned int ThreadCount) -: m_BasePort(BasePort) -, m_ThreadCount(ThreadCount != 0 ? ThreadCount : Max(std::thread::hardware_concurrency(), 8u)) +AsioTransportPlugin::AsioTransportPlugin() : m_ThreadCount(Max(std::thread::hardware_concurrency(), 8u)) { } @@ -372,6 +371,31 @@ AsioTransportPlugin::Release() const } void +AsioTransportPlugin::Configure(const char* OptionTag, const char* OptionValue) +{ + using namespace std::literals; + + if (OptionTag == "port"sv) + { + if (auto PortNum = ParseInt<uint16_t>(OptionValue)) + { + m_BasePort = *PortNum; + } + } + else if (OptionTag == "threads"sv) + { + if (auto ThreadCount = ParseInt<int>(OptionValue)) + { + m_ThreadCount = *ThreadCount; + } + } + else + { + // Unknown configuration option + } +} + +void AsioTransportPlugin::Initialize(TransportServer* ServerInterface) { ZEN_ASSERT(m_ThreadCount > 0); @@ -429,9 +453,9 @@ AsioTransportPlugin::IsAvailable() } TransportPlugin* -CreateAsioTransportPlugin(uint16_t BasePort, unsigned int ThreadCount) +CreateAsioTransportPlugin() { - return new AsioTransportPlugin(BasePort, ThreadCount); + return new AsioTransportPlugin(); } } // namespace zen diff --git a/src/zenhttp/transports/asiotransport.h b/src/zenhttp/transports/asiotransport.h index b10174b85..25f122b5b 100644 --- a/src/zenhttp/transports/asiotransport.h +++ b/src/zenhttp/transports/asiotransport.h @@ -8,7 +8,7 @@ namespace zen { -TransportPlugin* CreateAsioTransportPlugin(uint16_t BasePort, unsigned int ThreadCount); +TransportPlugin* CreateAsioTransportPlugin(); } // namespace zen diff --git a/src/zenhttp/transports/dlltransport.cpp b/src/zenhttp/transports/dlltransport.cpp index 04fb6caaa..5c0084e44 100644 --- a/src/zenhttp/transports/dlltransport.cpp +++ b/src/zenhttp/transports/dlltransport.cpp @@ -86,28 +86,29 @@ struct LoadedDll Ref<TransportPlugin> Plugin; }; -class DllTransportPluginImpl +class DllTransportPluginImpl : public DllTransportPlugin, RefCounted { public: - DllTransportPluginImpl(uint16_t BasePort, unsigned int ThreadCount); + DllTransportPluginImpl(); ~DllTransportPluginImpl(); - uint16_t Start(TransportServer* ServerInterface); - void Stop(); - bool IsAvailable(); - void LoadDll(std::string_view Name); + virtual uint32_t AddRef() const override; + virtual uint32_t Release() const override; + virtual void Configure(const char* OptionTag, const char* OptionValue) override; + virtual void Initialize(TransportServer* ServerInterface) override; + virtual void Shutdown() override; + virtual bool IsAvailable() override; + + virtual void LoadDll(std::string_view Name) override; + virtual void ConfigureDll(std::string_view Name, const char* OptionTag, const char* OptionValue) override; private: TransportServer* m_ServerInterface = nullptr; RwLock m_Lock; std::vector<LoadedDll> m_Transports; - uint16_t m_BasePort = 0; - int m_ThreadCount = 0; }; -DllTransportPluginImpl::DllTransportPluginImpl(uint16_t BasePort, unsigned int ThreadCount) -: m_BasePort(BasePort) -, m_ThreadCount(ThreadCount != 0 ? ThreadCount : Max(std::thread::hardware_concurrency(), 8u)) +DllTransportPluginImpl::DllTransportPluginImpl() { } @@ -115,8 +116,28 @@ DllTransportPluginImpl::~DllTransportPluginImpl() { } -uint16_t -DllTransportPluginImpl::Start(TransportServer* ServerIface) +uint32_t +DllTransportPluginImpl::AddRef() const +{ + return RefCounted::AddRef(); +} + +uint32_t +DllTransportPluginImpl::Release() const +{ + return RefCounted::Release(); +} + +void +DllTransportPluginImpl::Configure(const char* OptionTag, const char* OptionValue) +{ + // No configuration options + + ZEN_UNUSED(OptionTag, OptionValue); +} + +void +DllTransportPluginImpl::Initialize(TransportServer* ServerIface) { m_ServerInterface = ServerIface; @@ -133,12 +154,10 @@ DllTransportPluginImpl::Start(TransportServer* ServerIface) // TODO: report } } - - return m_BasePort; } void -DllTransportPluginImpl::Stop() +DllTransportPluginImpl::Shutdown() { RwLock::ExclusiveLockScope _(m_Lock); @@ -162,8 +181,24 @@ DllTransportPluginImpl::IsAvailable() } void +DllTransportPluginImpl::ConfigureDll(std::string_view Name, const char* OptionTag, const char* OptionValue) +{ + RwLock::ExclusiveLockScope _(m_Lock); + + for (auto& Transport : m_Transports) + { + if (Transport.Name == Name) + { + Transport.Plugin->Configure(OptionTag, OptionValue); + } + } +} + +void DllTransportPluginImpl::LoadDll(std::string_view Name) { + RwLock::ExclusiveLockScope _(m_Lock); + ExtendableStringBuilder<128> DllPath; DllPath << Name << ".dll"; HMODULE DllHandle = LoadLibraryA(DllPath.c_str()); @@ -197,52 +232,10 @@ DllTransportPluginImpl::LoadDll(std::string_view Name) m_Transports.emplace_back(std::move(NewDll)); } -////////////////////////////////////////////////////////////////////////// - -DllTransportPlugin::DllTransportPlugin(uint16_t BasePort, unsigned int ThreadCount) -: m_Impl(std::make_unique<DllTransportPluginImpl>(BasePort, ThreadCount)) -{ -} - -DllTransportPlugin::~DllTransportPlugin() -{ - m_Impl->Stop(); -} - -uint32_t -DllTransportPlugin::AddRef() const -{ - return RefCounted::AddRef(); -} - -uint32_t -DllTransportPlugin::Release() const -{ - return RefCounted::Release(); -} - -void -DllTransportPlugin::Initialize(TransportServer* ServerInterface) -{ - m_Impl->Start(ServerInterface); -} - -void -DllTransportPlugin::Shutdown() -{ - m_Impl->Stop(); -} - -bool -DllTransportPlugin::IsAvailable() -{ - return m_Impl->IsAvailable(); -} - -void -DllTransportPlugin::LoadDll(std::string_view Name) +DllTransportPlugin* +CreateDllTransportPlugin() { - return m_Impl->LoadDll(Name); + return new DllTransportPluginImpl; } } // namespace zen diff --git a/src/zenhttp/transports/dlltransport.h b/src/zenhttp/transports/dlltransport.h index 2dccdd0f9..9346a10ce 100644 --- a/src/zenhttp/transports/dlltransport.h +++ b/src/zenhttp/transports/dlltransport.h @@ -8,30 +8,19 @@ namespace zen { -class DllTransportPluginImpl; - /** Transport plugin which supports dynamic loading of external transport * provider modules */ -class DllTransportPlugin : public TransportPlugin, RefCounted + +class DllTransportPlugin : public TransportPlugin { public: - DllTransportPlugin(uint16_t BasePort, unsigned int ThreadCount); - ~DllTransportPlugin(); - - virtual uint32_t AddRef() const override; - virtual uint32_t Release() const override; - - virtual void Initialize(TransportServer* ServerInterface) override; - virtual void Shutdown() override; - virtual bool IsAvailable() override; - - void LoadDll(std::string_view Name); - -private: - std::unique_ptr<DllTransportPluginImpl> m_Impl; + virtual void LoadDll(std::string_view Name) = 0; + virtual void ConfigureDll(std::string_view Name, const char* OptionTag, const char* OptionValue) = 0; }; +DllTransportPlugin* CreateDllTransportPlugin(); + } // namespace zen #endif diff --git a/src/zenhttp/transports/winsocktransport.cpp b/src/zenhttp/transports/winsocktransport.cpp index ad3302550..2397dd7cf 100644 --- a/src/zenhttp/transports/winsocktransport.cpp +++ b/src/zenhttp/transports/winsocktransport.cpp @@ -20,27 +20,6 @@ ZEN_THIRD_PARTY_INCLUDES_END namespace zen { -class SocketTransportPluginImpl; - -class SocketTransportPlugin : public TransportPlugin, RefCounted -{ -public: - SocketTransportPlugin(uint16_t BasePort, unsigned int ThreadCount); - ~SocketTransportPlugin(); - - virtual uint32_t AddRef() const override; - virtual uint32_t Release() const override; - virtual void Initialize(TransportServer* ServerInterface) override; - virtual void Shutdown() override; - virtual bool IsAvailable() override; - -private: - bool m_IsOk = true; - uint16_t m_BasePort = 0; - int m_ThreadCount = 0; - SocketTransportPluginImpl* m_Impl; -}; - struct SocketTransportConnection : public TransportConnection { public: @@ -172,19 +151,23 @@ SocketTransportConnection::Shutdown(bool Receive, bool Transmit) ////////////////////////////////////////////////////////////////////////// -class SocketTransportPluginImpl +class SocketTransportPluginImpl : public TransportPlugin, RefCounted { public: - SocketTransportPluginImpl(uint16_t BasePort, unsigned int ThreadCount); + SocketTransportPluginImpl(); ~SocketTransportPluginImpl(); - uint16_t Start(uint16_t Port, TransportServer* ServerInterface); - void Stop(); + virtual uint32_t AddRef() const override; + virtual uint32_t Release() const override; + virtual void Configure(const char* OptionTag, const char* OptionValue) override; + virtual void Initialize(TransportServer* ServerInterface) override; + virtual void Shutdown() override; + virtual bool IsAvailable() override; private: TransportServer* m_ServerInterface = nullptr; - uint16_t m_BasePort = 0; - int m_ThreadCount = 0; + uint16_t m_BasePort = 8558; + int m_ThreadCount = 8; bool m_IsOk = true; SOCKET m_ListenSocket{}; @@ -193,9 +176,7 @@ private: std::unique_ptr<WorkerThreadPool> m_WorkerThreadpool; }; -SocketTransportPluginImpl::SocketTransportPluginImpl(uint16_t BasePort, unsigned int ThreadCount) -: m_BasePort(BasePort) -, m_ThreadCount(ThreadCount) +SocketTransportPluginImpl::SocketTransportPluginImpl() { # if ZEN_PLATFORM_WINDOWS WSADATA wsaData; @@ -205,13 +186,11 @@ SocketTransportPluginImpl::SocketTransportPluginImpl(uint16_t BasePort, unsigned WSACleanup(); } # endif - - m_WorkerThreadpool = std::make_unique<WorkerThreadPool>(m_ThreadCount, "http_conn"); } SocketTransportPluginImpl::~SocketTransportPluginImpl() { - Stop(); + Shutdown(); # if ZEN_PLATFORM_WINDOWS if (m_IsOk) @@ -221,36 +200,81 @@ SocketTransportPluginImpl::~SocketTransportPluginImpl() # endif } -uint16_t -SocketTransportPluginImpl::Start(uint16_t Port, TransportServer* ServerInterface) +uint32_t +SocketTransportPluginImpl::AddRef() const +{ + return RefCounted::AddRef(); +} + +uint32_t +SocketTransportPluginImpl::Release() const +{ + return RefCounted::Release(); +} + +void +SocketTransportPluginImpl::Configure(const char* OptionTag, const char* OptionValue) +{ + using namespace std::literals; + + if (OptionTag == "port"sv) + { + if (auto PortNum = ParseInt<uint16_t>(OptionValue)) + { + m_BasePort = *PortNum; + } + } + else if (OptionTag == "threads"sv) + { + if (auto ThreadCount = ParseInt<int>(OptionValue)) + { + m_ThreadCount = *ThreadCount; + } + } + else + { + // Unknown configuration option + } +} + +bool +SocketTransportPluginImpl::IsAvailable() { - m_ServerInterface = ServerInterface; - m_ListenSocket = socket(AF_INET6, SOCK_STREAM, 0); + return true; +} + +void +SocketTransportPluginImpl::Initialize(TransportServer* ServerInterface) +{ + m_ServerInterface = ServerInterface; + m_WorkerThreadpool = std::make_unique<WorkerThreadPool>(m_ThreadCount, "http_conn"); + + m_ListenSocket = socket(AF_INET6, SOCK_STREAM, 0); if (m_ListenSocket == SOCKET_ERROR || m_ListenSocket == INVALID_SOCKET) { ZEN_ERROR("socket creation failed in HTTP plugin server init: {}", WSAGetLastError()); - return 0; + return; } sockaddr_in6 Server{}; Server.sin6_family = AF_INET6; - Server.sin6_port = htons(Port); + Server.sin6_port = htons(m_BasePort); Server.sin6_addr = in6addr_any; if (int Result = bind(m_ListenSocket, (sockaddr*)&Server, sizeof(Server)); Result == SOCKET_ERROR) { ZEN_ERROR("bind call failed in HTTP plugin server init: {}", WSAGetLastError()); - return 0; + return; } if (int Result = listen(m_ListenSocket, AF_INET6); Result == SOCKET_ERROR) { ZEN_ERROR("listen call failed in HTTP plugin server init: {}", WSAGetLastError()); - return 0; + return; } m_KeepRunning.test_and_set(); @@ -292,19 +316,20 @@ SocketTransportPluginImpl::Start(uint16_t Port, TransportServer* ServerInterface ZEN_INFO("HTTP plugin server accept thread exit"); }); - - return Port; } void -SocketTransportPluginImpl::Stop() +SocketTransportPluginImpl::Shutdown() { // TODO: all pending/ongoing work should be drained here as well m_KeepRunning.clear(); - closesocket(m_ListenSocket); - m_ListenSocket = 0; + if (m_ListenSocket) + { + closesocket(m_ListenSocket); + m_ListenSocket = 0; + } if (m_AcceptThread.joinable()) { @@ -314,52 +339,10 @@ SocketTransportPluginImpl::Stop() ////////////////////////////////////////////////////////////////////////// -SocketTransportPlugin::SocketTransportPlugin(uint16_t BasePort, unsigned int ThreadCount) -: m_BasePort(BasePort) -, m_ThreadCount(ThreadCount != 0 ? ThreadCount : Max(std::thread::hardware_concurrency(), 8u)) -, m_Impl(new SocketTransportPluginImpl(BasePort, m_ThreadCount)) -{ -} - -SocketTransportPlugin::~SocketTransportPlugin() -{ - delete m_Impl; -} - -uint32_t -SocketTransportPlugin::AddRef() const -{ - return RefCounted::AddRef(); -} - -uint32_t -SocketTransportPlugin::Release() const -{ - return RefCounted::Release(); -} - -void -SocketTransportPlugin::Initialize(TransportServer* ServerInterface) -{ - m_Impl->Start(m_BasePort, ServerInterface); -} - -void -SocketTransportPlugin::Shutdown() -{ - m_Impl->Stop(); -} - -bool -SocketTransportPlugin::IsAvailable() -{ - return true; -} - TransportPlugin* -CreateSocketTransportPlugin(uint16_t BasePort, unsigned int ThreadCount) +CreateSocketTransportPlugin() { - return new SocketTransportPlugin(BasePort, ThreadCount); + return new SocketTransportPluginImpl; } } // namespace zen diff --git a/src/zenhttp/transports/winsocktransport.h b/src/zenhttp/transports/winsocktransport.h index 2b2a55aef..59f25d5d3 100644 --- a/src/zenhttp/transports/winsocktransport.h +++ b/src/zenhttp/transports/winsocktransport.h @@ -8,7 +8,7 @@ namespace zen { -TransportPlugin* CreateSocketTransportPlugin(uint16_t BasePort, unsigned int ThreadCount); +TransportPlugin* CreateSocketTransportPlugin(); } // namespace zen |