aboutsummaryrefslogtreecommitdiff
path: root/src/zenhttp/servers/httpplugin.cpp
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/servers/httpplugin.cpp
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/servers/httpplugin.cpp')
-rw-r--r--src/zenhttp/servers/httpplugin.cpp233
1 files changed, 104 insertions, 129 deletions
diff --git a/src/zenhttp/servers/httpplugin.cpp b/src/zenhttp/servers/httpplugin.cpp
index 2e934473e..3c727763b 100644
--- a/src/zenhttp/servers/httpplugin.cpp
+++ b/src/zenhttp/servers/httpplugin.cpp
@@ -8,8 +8,8 @@
# include <zencore/except.h>
# include <zencore/logging.h>
+# include <zencore/thread.h>
# include <zencore/trace.h>
-# include <zencore/workthreadpool.h>
# include <zenhttp/httpserver.h>
# include <memory>
@@ -74,18 +74,22 @@ private:
//////////////////////////////////////////////////////////////////////////
-struct HttpPluginServerImpl : public TransportServer
+struct HttpPluginServerImpl : public HttpPluginServer, TransportServer
{
HttpPluginServerImpl();
~HttpPluginServerImpl();
- void AddPlugin(Ref<TransportPlugin> Plugin);
- void RemovePlugin(Ref<TransportPlugin> Plugin);
+ // HttpPluginServer
- void Start();
- void Stop();
+ virtual void RegisterService(HttpService& Service) override;
+ virtual int Initialize(int BasePort) override;
+ virtual void Run(bool IsInteractiveSession) override;
+ virtual void RequestExit() override;
+ virtual void Close() override;
+
+ virtual void AddPlugin(Ref<TransportPlugin> Plugin) override;
+ virtual void RemovePlugin(Ref<TransportPlugin> Plugin) override;
- void RegisterService(const char* InUrlPath, HttpService& Service);
HttpService* RouteRequest(std::string_view Url);
struct ServiceEntry
@@ -94,9 +98,11 @@ struct HttpPluginServerImpl : public TransportServer
HttpService* Service;
};
+ bool m_IsInitialized = false;
RwLock m_Lock;
std::vector<ServiceEntry> m_UriHandlers;
std::vector<Ref<TransportPlugin>> m_Plugins;
+ Event m_ShutdownEvent;
// TransportServer
@@ -568,149 +574,71 @@ HttpPluginServerImpl::CreateConnectionHandler(TransportConnection* Connection)
return Handler;
}
-void
-HttpPluginServerImpl::Start()
+int
+HttpPluginServerImpl::Initialize(int BasePort)
{
- RwLock::ExclusiveLockScope _(m_Lock);
-
- for (auto& Plugin : m_Plugins)
+ try
{
- try
- {
- Plugin->Initialize(this);
- }
- catch (std::exception& Ex)
+ RwLock::ExclusiveLockScope _(m_Lock);
+
+ for (auto& Plugin : m_Plugins)
{
- ZEN_WARN("exception caught during plugin initialization: {}", Ex.what());
+ try
+ {
+ Plugin->Initialize(this);
+ }
+ catch (std::exception& Ex)
+ {
+ ZEN_WARN("exception caught during plugin initialization: {}", Ex.what());
+ }
}
}
-}
-
-void
-HttpPluginServerImpl::Stop()
-{
- RwLock::ExclusiveLockScope _(m_Lock);
-
- for (auto& Plugin : m_Plugins)
+ catch (std::exception& ex)
{
- try
- {
- Plugin->Shutdown();
- }
- catch (std::exception& Ex)
- {
- ZEN_WARN("exception caught during plugin shutdown: {}", Ex.what());
- }
-
- Plugin = nullptr;
+ ZEN_WARN("Caught exception starting http plugin server: {}", ex.what());
}
- m_Plugins.clear();
-}
+ m_IsInitialized = true;
-void
-HttpPluginServerImpl::AddPlugin(Ref<TransportPlugin> Plugin)
-{
- RwLock::ExclusiveLockScope _(m_Lock);
- m_Plugins.emplace_back(std::move(Plugin));
+ return BasePort;
}
void
-HttpPluginServerImpl::RemovePlugin(Ref<TransportPlugin> Plugin)
+HttpPluginServerImpl::Close()
{
- RwLock::ExclusiveLockScope _(m_Lock);
- auto It = std::find(begin(m_Plugins), end(m_Plugins), Plugin);
- if (It != m_Plugins.end())
- {
- m_Plugins.erase(It);
- }
-}
+ if (!m_IsInitialized)
+ return;
-void
-HttpPluginServerImpl::RegisterService(const char* InUrlPath, HttpService& Service)
-{
- std::string_view UrlPath(InUrlPath);
- Service.SetUriPrefixLength(UrlPath.size());
- if (!UrlPath.empty() && UrlPath.back() == '/')
+ try
{
- UrlPath.remove_suffix(1);
- }
-
- RwLock::ExclusiveLockScope _(m_Lock);
- m_UriHandlers.push_back({std::string(UrlPath), &Service});
-}
-
-HttpService*
-HttpPluginServerImpl::RouteRequest(std::string_view Url)
-{
- RwLock::SharedLockScope _(m_Lock);
+ RwLock::ExclusiveLockScope _(m_Lock);
- HttpService* CandidateService = nullptr;
- std::string::size_type CandidateMatchSize = 0;
- for (const ServiceEntry& SvcEntry : m_UriHandlers)
- {
- const std::string& SvcUrl = SvcEntry.ServiceUrlPath;
- const std::string::size_type SvcUrlSize = SvcUrl.size();
- if ((SvcUrlSize >= CandidateMatchSize) && Url.compare(0, SvcUrlSize, SvcUrl) == 0 &&
- ((SvcUrlSize == Url.size()) || (Url[SvcUrlSize] == '/')))
+ for (auto& Plugin : m_Plugins)
{
- CandidateMatchSize = SvcUrl.size();
- CandidateService = SvcEntry.Service;
- }
- }
-
- return CandidateService;
-}
-
-//////////////////////////////////////////////////////////////////////////
-
-HttpPluginServer::HttpPluginServer(unsigned int ThreadCount)
-: m_ThreadCount(ThreadCount != 0 ? ThreadCount : Max(std::thread::hardware_concurrency(), 8u))
-, m_Impl(new HttpPluginServerImpl)
-{
-}
-
-HttpPluginServer::~HttpPluginServer()
-{
- if (m_Impl)
- {
- ZEN_ERROR("~HttpPluginServer() called without calling Close() first");
- }
-}
-
-int
-HttpPluginServer::Initialize(int BasePort)
-{
- try
- {
- m_Impl->Start();
- }
- catch (std::exception& ex)
- {
- ZEN_WARN("Caught exception starting http plugin server: {}", ex.what());
- }
+ try
+ {
+ Plugin->Shutdown();
+ }
+ catch (std::exception& Ex)
+ {
+ ZEN_WARN("exception caught during plugin shutdown: {}", Ex.what());
+ }
- return BasePort;
-}
+ Plugin = nullptr;
+ }
-void
-HttpPluginServer::Close()
-{
- try
- {
- m_Impl->Stop();
+ m_Plugins.clear();
}
catch (std::exception& ex)
{
ZEN_WARN("Caught exception stopping http plugin server: {}", ex.what());
}
- delete m_Impl;
- m_Impl = nullptr;
+ m_IsInitialized = false;
}
void
-HttpPluginServer::Run(bool IsInteractive)
+HttpPluginServerImpl::Run(bool IsInteractive)
{
const bool TestMode = !IsInteractive;
@@ -754,27 +682,74 @@ HttpPluginServer::Run(bool IsInteractive)
}
void
-HttpPluginServer::RequestExit()
+HttpPluginServerImpl::RequestExit()
{
m_ShutdownEvent.Set();
}
void
-HttpPluginServer::RegisterService(HttpService& Service)
+HttpPluginServerImpl::AddPlugin(Ref<TransportPlugin> Plugin)
{
- m_Impl->RegisterService(Service.BaseUri(), Service);
+ RwLock::ExclusiveLockScope _(m_Lock);
+ m_Plugins.emplace_back(std::move(Plugin));
}
void
-HttpPluginServer::AddPlugin(Ref<TransportPlugin> Plugin)
+HttpPluginServerImpl::RemovePlugin(Ref<TransportPlugin> Plugin)
{
- m_Impl->AddPlugin(Plugin);
+ RwLock::ExclusiveLockScope _(m_Lock);
+ auto It = std::find(begin(m_Plugins), end(m_Plugins), Plugin);
+ if (It != m_Plugins.end())
+ {
+ m_Plugins.erase(It);
+ }
}
void
-HttpPluginServer::RemovePlugin(Ref<TransportPlugin> Plugin)
+HttpPluginServerImpl::RegisterService(HttpService& Service)
+{
+ std::string_view UrlPath(Service.BaseUri());
+ Service.SetUriPrefixLength(UrlPath.size());
+
+ if (!UrlPath.empty() && UrlPath.back() == '/')
+ {
+ UrlPath.remove_suffix(1);
+ }
+
+ RwLock::ExclusiveLockScope _(m_Lock);
+ m_UriHandlers.push_back({std::string(UrlPath), &Service});
+}
+
+HttpService*
+HttpPluginServerImpl::RouteRequest(std::string_view Url)
+{
+ RwLock::SharedLockScope _(m_Lock);
+
+ HttpService* CandidateService = nullptr;
+ std::string::size_type CandidateMatchSize = 0;
+ for (const ServiceEntry& SvcEntry : m_UriHandlers)
+ {
+ const std::string& SvcUrl = SvcEntry.ServiceUrlPath;
+ const std::string::size_type SvcUrlSize = SvcUrl.size();
+ if ((SvcUrlSize >= CandidateMatchSize) && Url.compare(0, SvcUrlSize, SvcUrl) == 0 &&
+ ((SvcUrlSize == Url.size()) || (Url[SvcUrlSize] == '/')))
+ {
+ CandidateMatchSize = SvcUrl.size();
+ CandidateService = SvcEntry.Service;
+ }
+ }
+
+ return CandidateService;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+struct HttpPluginServerImpl;
+
+Ref<HttpPluginServer>
+CreateHttpPluginServer()
{
- m_Impl->RemovePlugin(Plugin);
+ return Ref<HttpPluginServer>(new HttpPluginServerImpl);
}
} // namespace zen