aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp/transports
diff options
context:
space:
mode:
authorStefan Boberg <[email protected]>2023-10-13 14:46:49 +0200
committerGitHub <[email protected]>2023-10-13 14:46:49 +0200
commitc3fad0e98576ff5dee3ee63725459d46e201fa34 (patch)
tree91455786fac76ffb6a83ff24620329780ce08545 /src/zenhttp/transports
parentimproved http.sys initialization diagnostics and amended logic for dedicated ... (diff)
downloadzen-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.cpp38
-rw-r--r--src/zenhttp/transports/asiotransport.h2
-rw-r--r--src/zenhttp/transports/dlltransport.cpp115
-rw-r--r--src/zenhttp/transports/dlltransport.h23
-rw-r--r--src/zenhttp/transports/winsocktransport.cpp163
-rw-r--r--src/zenhttp/transports/winsocktransport.h2
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