diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2021-06-20 11:20:47 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2021-06-20 11:20:47 +0200 |
commit | 1967e3465c7e82d84dc8441ba1993a55050766fb (patch) | |
tree | 1a8703b9dac00f659a774c7892db528df25f7d22 | |
parent | a1dbf3f04bde8f98c11f43722e90b20dc832e78c (diff) |
Basic blog module.
EventManager, ContentManager
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/Content.hpp | 10 | ||||
-rw-r--r-- | src/ContentManager.cpp | 57 | ||||
-rw-r--r-- | src/ContentManager.hpp | 15 | ||||
-rw-r--r-- | src/EventManager.cpp | 70 | ||||
-rw-r--r-- | src/EventManager.hpp | 10 | ||||
-rw-r--r-- | src/content/blog/Blog.cpp | 28 | ||||
-rw-r--r-- | src/content/blog/Blog.hpp | 16 | ||||
-rw-r--r-- | src/main.cpp | 16 |
9 files changed, 189 insertions, 42 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ae0b1c7..9972193 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,9 @@ cmake_minimum_required(VERSION 3.1.9) project(cpp-web) -if(NOT CMAKE_BUILD_TYPE) - set(CMAKE_BUILD_TYPE Release ... FORCE) -endif() - set(CMAKE_CXX_FLAGS "-Wall -Wextra -std=c++17") -set(CMAKE_CXX_FLAGS_DEBUG "-g3") -set(CMAKE_CXX_FLAGS_RELEASE "-Os -fno-pic -fomit-frame-pointer -flto -fno-rtti -ffunction-sections -fdata-sections -fsanitize=address -fsanitize=leak -fsanitize=leak") +set(CMAKE_CXX_FLAGS_DEBUG "-g3 -fpic -fomit-frame-pointer -flto -fno-rtti -ffunction-sections -fdata-sections -fsanitize=address -fsanitize=leak") +set(CMAKE_CXX_FLAGS_RELEASE "-Os") set(CMAKE_EXE_LINKER_FLAGS "-flto") set(INJA_SRCDIR "${PROJECT_SOURCE_DIR}/deps/inja" CACHE STRING "Path to the inja source directory.") @@ -19,6 +15,7 @@ include_directories(${CPP_HTTPLIB_SRCDIR} ${INJA_SRCDIR}/single_include ${INJA_S file(GLOB_RECURSE SOURCES "src/*.cpp") add_executable(cpp-web ${SOURCES}) #target_compile_definitions(cpp-web PUBLIC CPPHTTPLIB_THREAD_POOL_COUNT=4) +#target_compile_options(cpp-web PUBLIC "-std=c++14") if(CMAKE_BUILD_TYPE MATCHES Release) set_target_properties(cpp-web PROPERTIES LINK_FLAGS "-no-pie -flto -Wl,--gc-sections -Wl,-z,norelro -Wl,--hash-style=gnu -Wl,--build-id=none") endif() diff --git a/src/Content.hpp b/src/Content.hpp index e337074..de5f531 100644 --- a/src/Content.hpp +++ b/src/Content.hpp @@ -5,14 +5,16 @@ #include <tuple> #include <vector> -typedef std::vector<std::tuple<std::string, std::string>> Redirections; +typedef std::vector<std::string> Redirections; class Content { public: - virtual bool Init(std::string & basePath) = 0; + virtual bool Init() = 0; virtual void Shutdown() = 0; - virtual bool Render() = 0; - virtual Redirections const GetRedirections() = 0; + virtual bool Render(std::string & out) = 0; + + virtual std::string const & GetBasePath() const = 0; + virtual Redirections const & GetRedirections() const = 0; }; #endif diff --git a/src/ContentManager.cpp b/src/ContentManager.cpp index 1ba7654..951c10e 100644 --- a/src/ContentManager.cpp +++ b/src/ContentManager.cpp @@ -1,6 +1,61 @@ #include "ContentManager.hpp" -bool ContentManager::Register(Content const & ctnt) +bool ContentManager::RegisterModule(std::shared_ptr<Content> ctnt) { + std::string const & basePath = ctnt->GetBasePath(); + Redirections const & rs = ctnt->GetRedirections(); + + m_ContentModules[basePath] = ctnt; + for (auto & redirect : rs) + { + m_ContentModules[redirect] = ctnt; + } + + return false; +} + +bool ContentManager::InitAll(void) +{ + bool ret = true; + + for (auto & content : m_ContentModules) + { + if (content.second->Init() == false) + { + ret = false; + } + } + + return ret; +} + +void ContentManager::ShutdownAll(void) +{ + std::unordered_map<std::shared_ptr<Content>, bool> shutdownModules; + + for (auto & content : m_ContentModules) + { + auto const & search = shutdownModules.find(content.second); + if (search != shutdownModules.end()) + { + continue; + } else { + content.second->Shutdown(); + shutdownModules[content.second] = true; + } + } + + m_ContentModules.clear(); +} + +bool ContentManager::Render(std::string & basePath) +{ + (void)basePath; + return false; } + +ContentModules const & ContentManager::GetAllModules() const +{ + return m_ContentModules; +} diff --git a/src/ContentManager.hpp b/src/ContentManager.hpp index 75b9173..033be59 100644 --- a/src/ContentManager.hpp +++ b/src/ContentManager.hpp @@ -3,17 +3,24 @@ #include "Content.hpp" -#include <map> +#include <memory> +#include <unordered_map> + +typedef std::unordered_map<std::string, std::shared_ptr<Content>> ContentModules; class ContentManager { public: ContentManager() {} - ~ContentManager() {} + ~ContentManager() { ShutdownAll(); } - bool Register(Content const & ctnt); + bool RegisterModule(std::shared_ptr<Content> ctnt); + bool InitAll(void); + void ShutdownAll(void); + bool Render(std::string & basePath); + ContentModules const & GetAllModules() const; private: - std::map<std::string, Content const &> m_ContentModules; + ContentModules m_ContentModules; }; #endif diff --git a/src/EventManager.cpp b/src/EventManager.cpp index b946b5f..6921b82 100644 --- a/src/EventManager.cpp +++ b/src/EventManager.cpp @@ -9,11 +9,52 @@ #include <signal.h> extern "C" { -static void EvCallbackInterceptor(struct evhttp_request *const req, +static void GenerateInternalErrorPage(struct evhttp_request * const req, + std::string text) +{ + evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", + "text/html"); + + struct evbuffer *const output = evbuffer_new(); + if (output != nullptr) { + evbuffer_add(output, text.c_str(), text.size()); + evhttp_send_reply(req, 500, "Internal Error", output); + evbuffer_free(output); + } +} + +static void EvGenericInterceptor(struct evhttp_request *const req, void *ev_c_callback) { if (ev_c_callback != nullptr) { struct ev_callback *const evcb = (struct ev_callback *)ev_c_callback; evcb->cb(req, evcb->ud); + } else { + GenerateInternalErrorPage(req, "EvGenericInterceptor: ev_c_callback == nullptr"); + } +} + +static void EvContentManagerInterceptor(struct evhttp_request * const req, + void * ev_c_callback) { + if (ev_c_callback != nullptr) { + Content * const cntnt = (Content *)ev_c_callback; + std::string out; + if (cntnt->Render(out) == false) { + std::string text; + text = "ContentModule(\"" + cntnt->GetBasePath() + "\")->Render() failed.\n"; + GenerateInternalErrorPage(req, text); + } else { + evhttp_add_header(evhttp_request_get_output_headers(req), "Content-Type", + "text/html"); + + struct evbuffer *const output = evbuffer_new(); + if (output != nullptr) { + evbuffer_add(output, out.c_str(), out.size()); + evhttp_send_reply(req, 200, "OK", output); + evbuffer_free(output); + } + } + } else { + GenerateInternalErrorPage(req, "EvContentManagerInterceptor: ev_c_callback == nullptr"); } } @@ -63,14 +104,21 @@ bool EventManager::Init(std::string host, uint16_t port) { return false; } - for (auto &uc : m_UrlCallbacks) { - struct ev_callback *const evcb = &std::get<1>(uc); - if (evhttp_set_cb(m_EvHttp, std::get<0>(uc).c_str(), EvCallbackInterceptor, + for (auto & uc : m_UrlCallbacks) { + struct ev_callback * const evcb = &std::get<1>(uc); + if (evhttp_set_cb(m_EvHttp, std::get<0>(uc).c_str(), EvGenericInterceptor, evcb) != 0) { return false; } } - evhttp_set_gencb(m_EvHttp, EvCallbackInterceptor, &m_DefaultCallback); + for (auto & cm : m_ContentModules) { + std::shared_ptr<Content> content = cm.second; + if (evhttp_set_cb(m_EvHttp, cm.first.c_str(), EvContentManagerInterceptor, + content.get()) != 0) { + return false; + } + } + evhttp_set_gencb(m_EvHttp, EvGenericInterceptor, &m_DefaultCallback); m_EvSocket = evhttp_bind_socket_with_handle(m_EvHttp, host.c_str(), port); if (m_EvSocket == nullptr) { @@ -91,11 +139,19 @@ bool EventManager::Init(std::string host, uint16_t port) { return true; } -void EventManager::setDefaultCallback(EvFunction fn, EvUserData dat) { +void EventManager::SetDefaultCallback(EvFunction fn, EvUserData dat) { m_DefaultCallback.cb = fn; m_DefaultCallback.ud = dat; } -void EventManager::addCallback(std::string url, EvFunction fn, EvUserData dat) { +void EventManager::AddCallback(std::string url, EvFunction fn, EvUserData dat) { m_UrlCallbacks.push_back(EvUrlCallback(url, {fn, dat})); } + +void EventManager::AddContentManager(ContentManager const & cmgr) +{ + ContentModules new_mods = m_ContentModules; + + new_mods.insert(cmgr.GetAllModules().begin(), cmgr.GetAllModules().end()); + m_ContentModules = new_mods; +} diff --git a/src/EventManager.hpp b/src/EventManager.hpp index 2e4184e..73b95ea 100644 --- a/src/EventManager.hpp +++ b/src/EventManager.hpp @@ -1,6 +1,8 @@ #ifndef EVENT_MANAGER_H #define EVENT_MANAGER_H 1 +#include "ContentManager.hpp" + #include <event2/buffer.h> #include <event2/event.h> #include <event2/http.h> @@ -20,7 +22,7 @@ struct ev_callback { typedef std::tuple<std::string, struct ev_callback> EvUrlCallback; -static inline void default_evhttp_callback(struct evhttp_request *const req, +static inline void default_evhttp_callback(struct evhttp_request * const req, EvUserData ud) { (void)ud; @@ -42,12 +44,14 @@ public: ~EventManager(); bool Init(std::string = "127.0.0.1", uint16_t port = 9000); - void setDefaultCallback(EvFunction fn, EvUserData dat); - void addCallback(std::string url, EvFunction fn, EvUserData dat); + void SetDefaultCallback(EvFunction fn, EvUserData dat); + void AddCallback(std::string url, EvFunction fn, EvUserData dat); + void AddContentManager(ContentManager const & cmgr); private: struct ev_callback m_DefaultCallback; std::vector<EvUrlCallback> m_UrlCallbacks; + ContentModules m_ContentModules; struct event_config *m_EvConfig = nullptr; struct event_base *m_EvBase = nullptr; diff --git a/src/content/blog/Blog.cpp b/src/content/blog/Blog.cpp index d79f207..3f1433d 100644 --- a/src/content/blog/Blog.cpp +++ b/src/content/blog/Blog.cpp @@ -1,23 +1,33 @@ #include "Blog.hpp" -bool Blog::Init(std::string & basePath) +Blog::Blog(std::string basePath) : m_BasePath(basePath), m_Redirections() { - (void)basePath; + m_Redirections.push_back(basePath + "-data"); +} + +bool Blog::Init(void) +{ + return true; +} - return false; +void Blog::Shutdown(void) +{ } -void Blog::Shutdown() +bool Blog::Render(std::string & out) { + out = "blog-bla"; + + return true; } -bool Blog::Render() +std::string const & Blog::GetBasePath(void) const { - return false; + return m_BasePath; } -Redirections const -Blog::GetRedirections() +Redirections const & +Blog::GetRedirections(void) const { - return Redirections(); + return m_Redirections; } diff --git a/src/content/blog/Blog.hpp b/src/content/blog/Blog.hpp index c903a22..316ce92 100644 --- a/src/content/blog/Blog.hpp +++ b/src/content/blog/Blog.hpp @@ -6,10 +6,18 @@ class Blog : public Content { public: - bool Init(std::string & basePath); - void Shutdown(); - bool Render(); - Redirections const GetRedirections(); + explicit Blog(std::string basePath); + + bool Init(void); + void Shutdown(void); + bool Render(std::string & out); + + std::string const & GetBasePath() const; + Redirections const & GetRedirections() const; + +private: + std::string m_BasePath; + Redirections m_Redirections; }; #endif diff --git a/src/main.cpp b/src/main.cpp index feabb19..cfa08c6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -86,12 +86,20 @@ int main(int argc, char **argv) { } fs.Scan(); - Blog blog; - ContentManager ctmgr; - ctmgr.Register(blog); + ctmgr.RegisterModule(std::make_shared<Blog>("/blog")); + + if (ctmgr.InitAll() == false) + { + std::cout << "InitAll() failed." << std::endl; + return 1; + } EventManager evmgr; - evmgr.setDefaultCallback(example_inja_render, {}); + //evmgr.SetDefaultCallback(example_inja_render, {}); + evmgr.AddCallback("/bla", example_inja_render, {}); + evmgr.AddContentManager(ctmgr); evmgr.Init(host, port); + + //ctmgr.ShutdownAll(); } |