aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2021-06-20 11:20:47 +0200
committerToni Uhlig <matzeton@googlemail.com>2021-06-20 11:20:47 +0200
commit1967e3465c7e82d84dc8441ba1993a55050766fb (patch)
tree1a8703b9dac00f659a774c7892db528df25f7d22
parenta1dbf3f04bde8f98c11f43722e90b20dc832e78c (diff)
Basic blog module.
EventManager, ContentManager Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--CMakeLists.txt9
-rw-r--r--src/Content.hpp10
-rw-r--r--src/ContentManager.cpp57
-rw-r--r--src/ContentManager.hpp15
-rw-r--r--src/EventManager.cpp70
-rw-r--r--src/EventManager.hpp10
-rw-r--r--src/content/blog/Blog.cpp28
-rw-r--r--src/content/blog/Blog.hpp16
-rw-r--r--src/main.cpp16
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();
}