aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/module
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2024-02-28 16:32:43 +0000
committersaturneric <[email protected]>2024-02-28 16:32:43 +0000
commit12d70e1792a5b1ff08d4b58fb49fb9e58d6551a8 (patch)
tree1b747d6a3a034814104df6f531077de9c03ecd53 /src/core/module
parentfeat: add user agent header when doing http request (diff)
downloadGpgFrontend-12d70e1792a5b1ff08d4b58fb49fb9e58d6551a8.tar.gz
GpgFrontend-12d70e1792a5b1ff08d4b58fb49fb9e58d6551a8.zip
feat: upgrade module system
1. load module and resolve symbols at runtime 2. restrict sdk functions and structures to c style 3. add some core api to support it
Diffstat (limited to 'src/core/module')
-rw-r--r--src/core/module/Event.cpp44
-rw-r--r--src/core/module/Event.h10
-rw-r--r--src/core/module/GlobalModuleContext.cpp42
-rw-r--r--src/core/module/GlobalModuleContext.h4
-rw-r--r--src/core/module/Module.cpp104
-rw-r--r--src/core/module/Module.h19
-rw-r--r--src/core/module/ModuleManager.cpp79
-rw-r--r--src/core/module/ModuleManager.h8
8 files changed, 288 insertions, 22 deletions
diff --git a/src/core/module/Event.cpp b/src/core/module/Event.cpp
index fab26453..5a7b324c 100644
--- a/src/core/module/Event.cpp
+++ b/src/core/module/Event.cpp
@@ -28,6 +28,8 @@
#include "Event.h"
+#include "core/utils/CommonUtils.h"
+
namespace GpgFrontend::Module {
class Event::Impl {
@@ -67,7 +69,11 @@ class Event::Impl {
auto GetIdentifier() -> EventIdentifier { return event_identifier_; }
- void AddParameter(const QString& key, const ParameterValue& value) {
+ auto GetTriggerIdentifier() -> EventTriggerIdentifier {
+ return trigger_uuid_;
+ }
+
+ void AddParameter(const QString& key, const QString& value) {
data_[key] = value;
}
@@ -95,9 +101,35 @@ class Event::Impl {
}
}
+ auto ToModuleEvent() -> ModuleEvent* {
+ auto* event = static_cast<ModuleEvent*>(SecureMalloc(sizeof(ModuleEvent)));
+
+ event->id = GFStrDup(event_identifier_);
+
+ ModuleEventParam* l_param = nullptr;
+ ModuleEventParam* p_param;
+
+ int index = 0;
+ for (const auto& data : data_) {
+ p_param = static_cast<ModuleEventParam*>(
+ SecureMalloc(sizeof(ModuleEventParam)));
+ if (index++ == 0) event->params = p_param;
+
+ p_param->name = GFStrDup(data.first);
+ p_param->value = GFStrDup(data.second);
+ p_param->next = nullptr;
+
+ l_param->next = p_param;
+ l_param = p_param;
+ }
+
+ return event;
+ }
+
private:
EventIdentifier event_identifier_;
- std::map<QString, ParameterValue> data_;
+ EventTriggerIdentifier trigger_uuid_ = QUuid::createUuid().toString();
+ std::map<QString, QString> data_;
EventCallback callback_;
QThread* callback_thread_ = nullptr; ///<
};
@@ -128,7 +160,11 @@ auto Event::Event::GetIdentifier() -> EventIdentifier {
return p_->GetIdentifier();
}
-void Event::AddParameter(const QString& key, const ParameterValue& value) {
+auto Event::Event::GetTriggerIdentifier() -> EventTriggerIdentifier {
+ return p_->GetTriggerIdentifier();
+}
+
+void Event::AddParameter(const QString& key, const QString& value) {
p_->AddParameter(key, value);
}
@@ -136,4 +172,6 @@ void Event::ExecuteCallback(ListenerIdentifier l_id, DataObjectPtr d_o) {
p_->ExecuteCallback(std::move(l_id), d_o);
}
+auto Event::ToModuleEvent() -> ModuleEvent* { return p_->ToModuleEvent(); }
+
} // namespace GpgFrontend::Module \ No newline at end of file
diff --git a/src/core/module/Event.h b/src/core/module/Event.h
index 92268216..d7c35314 100644
--- a/src/core/module/Event.h
+++ b/src/core/module/Event.h
@@ -34,6 +34,7 @@
#include "core/GpgFrontendCore.h"
#include "core/model/DataObject.h"
+#include "module/sdk/Module.h"
namespace GpgFrontend::Module {
@@ -41,6 +42,7 @@ class Event;
using EventRefrernce = std::shared_ptr<Event>;
using EventIdentifier = QString;
+using EventTriggerIdentifier = QString;
using Evnets = std::vector<Event>;
class GPGFRONTEND_CORE_EXPORT Event {
@@ -52,7 +54,7 @@ class GPGFRONTEND_CORE_EXPORT Event {
std::function<void(EventIdentifier, ListenerIdentifier, DataObjectPtr)>;
struct ParameterInitializer {
QString key;
- ParameterValue value;
+ QString value;
};
explicit Event(const QString&,
@@ -75,10 +77,14 @@ class GPGFRONTEND_CORE_EXPORT Event {
auto GetIdentifier() -> EventIdentifier;
- void AddParameter(const QString& key, const ParameterValue& value);
+ auto GetTriggerIdentifier() -> EventTriggerIdentifier;
+
+ void AddParameter(const QString& key, const QString& value);
void ExecuteCallback(ListenerIdentifier, DataObjectPtr);
+ auto ToModuleEvent() -> ModuleEvent*;
+
private:
class Impl;
SecureUniquePtr<Impl> p_;
diff --git a/src/core/module/GlobalModuleContext.cpp b/src/core/module/GlobalModuleContext.cpp
index 9bc4f06b..cf3e134b 100644
--- a/src/core/module/GlobalModuleContext.cpp
+++ b/src/core/module/GlobalModuleContext.cpp
@@ -31,6 +31,7 @@
#include <set>
#include <unordered_map>
#include <unordered_set>
+#include <utility>
#include "core/module/Event.h"
#include "core/module/Module.h"
@@ -49,6 +50,18 @@ class GlobalModuleContext::Impl {
acquired_channel_.insert(kGpgFrontendNonAsciiChannel);
}
+ auto SearchModule(ModuleIdentifier module_id) -> ModulePtr {
+ // Search for the module in the register table.
+ auto module_info_opt = search_module_register_table(module_id);
+ if (!module_info_opt.has_value()) {
+ GF_CORE_LOG_ERROR("cannot find module id {} at register table",
+ module_id);
+ return nullptr;
+ }
+
+ return module_info_opt.value()->module;
+ }
+
auto GetChannel(ModuleRawPtr module) -> int {
// Search for the module in the register table.
auto module_info_opt =
@@ -97,7 +110,7 @@ class GlobalModuleContext::Impl {
return false;
}
- if (!module->Register()) {
+ if (module->Register() != 0) {
GF_CORE_LOG_ERROR("register module {} failed",
module->GetModuleIdentifier());
return false;
@@ -222,6 +235,9 @@ class GlobalModuleContext::Impl {
GF_CORE_LOG_DEBUG("event {}'s current listeners size: {}",
event->GetIdentifier(), listeners_set.size());
+ // register trigger id index table
+ module_on_triggering_events_table_[event->GetTriggerIdentifier()] = event;
+
// Iterate through each listener and execute the corresponding module
for (const auto& listener_module_id : listeners_set) {
// Search for the module's information in the registration table
@@ -272,7 +288,17 @@ class GlobalModuleContext::Impl {
return true;
}
- auto IsModuleActivated(const ModuleIdentifier& m_id) const -> bool {
+ auto SearchEvent(const EventTriggerIdentifier& trigger_id)
+ -> std::optional<EventRefrernce> {
+ if (module_on_triggering_events_table_.find(trigger_id) !=
+ module_on_triggering_events_table_.end()) {
+ return module_on_triggering_events_table_[trigger_id];
+ }
+ return {};
+ }
+
+ [[nodiscard]] auto IsModuleActivated(const ModuleIdentifier& m_id) const
+ -> bool {
auto m = search_module_register_table(m_id);
return m.has_value() && m->get()->activate;
}
@@ -290,6 +316,8 @@ class GlobalModuleContext::Impl {
module_register_table_;
std::map<EventIdentifier, std::unordered_set<ModuleIdentifier>>
module_events_table_;
+ std::map<EventTriggerIdentifier, EventRefrernce>
+ module_on_triggering_events_table_;
std::set<int> acquired_channel_;
TaskRunnerPtr default_task_runner_;
@@ -323,6 +351,11 @@ GlobalModuleContext::GlobalModuleContext()
GlobalModuleContext::~GlobalModuleContext() = default;
+auto GlobalModuleContext::SearchModule(ModuleIdentifier module_id)
+ -> ModulePtr {
+ return p_->SearchModule(std::move(module_id));
+}
+
// Function to get the task runner associated with a module.
auto GlobalModuleContext::GetTaskRunner(ModuleRawPtr module)
-> std::optional<TaskRunnerPtr> {
@@ -362,6 +395,11 @@ auto GlobalModuleContext::TriggerEvent(EventRefrernce event) -> bool {
return p_->TriggerEvent(std::move(event));
}
+auto GlobalModuleContext::SearchEvent(EventTriggerIdentifier trigger_id)
+ -> std::optional<EventRefrernce> {
+ return p_->SearchEvent(trigger_id);
+}
+
auto GlobalModuleContext::GetChannel(ModuleRawPtr module) -> int {
return p_->GetChannel(module);
}
diff --git a/src/core/module/GlobalModuleContext.h b/src/core/module/GlobalModuleContext.h
index 1c971bb5..7034fd77 100644
--- a/src/core/module/GlobalModuleContext.h
+++ b/src/core/module/GlobalModuleContext.h
@@ -58,6 +58,8 @@ class GPGFRONTEND_CORE_EXPORT GlobalModuleContext : public QObject {
~GlobalModuleContext() override;
+ auto SearchModule(ModuleIdentifier) -> ModulePtr;
+
auto GetChannel(ModuleRawPtr) -> int;
static auto GetDefaultChannel(ModuleRawPtr) -> int;
@@ -78,6 +80,8 @@ class GPGFRONTEND_CORE_EXPORT GlobalModuleContext : public QObject {
auto TriggerEvent(EventRefrernce) -> bool;
+ auto SearchEvent(EventTriggerIdentifier) -> std::optional<EventRefrernce>;
+
auto IsModuleActivated(ModuleIdentifier) -> bool;
private:
diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp
index 9076dc2c..e943ab09 100644
--- a/src/core/module/Module.cpp
+++ b/src/core/module/Module.cpp
@@ -43,7 +43,60 @@ class Module::Impl {
: m_ptr_(m_ptr),
identifier_(std::move(id)),
version_(std::move(version)),
- meta_data_(std::move(meta_data)) {}
+ meta_data_(std::move(meta_data)),
+ good_(true) {}
+
+ Impl(ModuleRawPtr m_ptr, QLibrary& module_library)
+ : m_ptr_(m_ptr), good_(false) {
+ for (auto& required_symbol : module_required_symbols_) {
+ *required_symbol.pointer =
+ reinterpret_cast<void*>(module_library.resolve(required_symbol.name));
+ if (*required_symbol.pointer == nullptr) {
+ GF_CORE_LOG_WARN(
+ "illegal module: {}, reason: cannot load symbol: {}, abort...",
+ module_library.fileName(), required_symbol.name);
+ return;
+ }
+ }
+
+ SPDLOG_INFO("module loaded, name: {}, verison: {}",
+ QString::fromUtf8(get_id_api_()),
+ QString::fromUtf8(get_version_api_()));
+
+ identifier_ = QString::fromUtf8(get_id_api_());
+ version_ = QString::fromUtf8(get_version_api_());
+
+ good_ = true;
+ }
+
+ [[nodiscard]] auto IsGood() const -> bool { return good_; }
+
+ auto Register() -> int {
+ if (good_ && register_api_ != nullptr) return register_api_();
+ return -1;
+ }
+
+ auto Active() -> int {
+ if (good_ && activate_api_ != nullptr) return activate_api_();
+ return -1;
+ }
+
+ auto Exec(const EventRefrernce& event) -> int {
+ if (good_ && execute_api_ != nullptr) {
+ return execute_api_(event->ToModuleEvent());
+ }
+ return -1;
+ }
+
+ auto Deactive() -> int {
+ if (good_ && deactivate_api_ != nullptr) return deactivate_api_();
+ return -1;
+ }
+
+ auto UnRegister() -> int {
+ if (good_ && unregister_api_ != nullptr) return unregister_api_();
+ return -1;
+ }
auto GetChannel() -> int { return get_gpc()->GetChannel(m_ptr_); }
@@ -68,9 +121,35 @@ class Module::Impl {
private:
GlobalModuleContext* gpc_{};
Module* m_ptr_;
- const ModuleIdentifier identifier_;
- const ModuleVersion version_;
- const ModuleMetaData meta_data_;
+ ModuleIdentifier identifier_;
+ ModuleVersion version_;
+ ModuleMetaData meta_data_;
+
+ bool good_;
+ ModuleAPIGetModuleID get_id_api_;
+ ModuleAPIGetModuleVersion get_version_api_;
+ ModuleAPIGetModuleMetaData get_metadata_api_;
+ ModuleAPIRegisterModule register_api_;
+ ModuleAPIActivateModule activate_api_;
+ ModuleAPIExecuteModule execute_api_;
+ ModuleAPIDeactivateModule deactivate_api_;
+ ModuleAPIUnregisterModule unregister_api_;
+
+ struct Symbol {
+ const char* name;
+ void** pointer;
+ };
+
+ QList<Symbol> module_required_symbols_ = {
+ {"GetModuleID", reinterpret_cast<void**>(&get_id_api_)},
+ {"GetModuleVersion", reinterpret_cast<void**>(&get_version_api_)},
+ {"GetModuleMetaData", reinterpret_cast<void**>(&get_metadata_api_)},
+ {"RegisterModule", reinterpret_cast<void**>(&register_api_)},
+ {"ActiveModule", reinterpret_cast<void**>(&activate_api_)},
+ {"ExecuteModule", reinterpret_cast<void**>(&execute_api_)},
+ {"DeactiveModule", reinterpret_cast<void**>(&deactivate_api_)},
+ {"UnregisterModule", reinterpret_cast<void**>(&unregister_api_)},
+ };
auto get_gpc() -> GlobalModuleContext* {
if (gpc_ == nullptr) {
@@ -84,8 +163,25 @@ Module::Module(ModuleIdentifier id, ModuleVersion version,
const ModuleMetaData& meta_data)
: p_(SecureCreateUniqueObject<Impl>(this, id, version, meta_data)) {}
+Module::Module(QLibrary& module_library)
+ : p_(SecureCreateUniqueObject<Impl>(this, module_library)) {}
+
Module::~Module() = default;
+auto Module::IsGood() -> bool { return p_->IsGood(); }
+
+auto Module::Register() -> int { return p_->Register(); }
+
+auto Module::Active() -> int { return p_->Active(); }
+
+auto Module::Exec(EventRefrernce event) -> int {
+ return p_->Exec(std::move(event));
+}
+
+auto Module::Deactive() -> int { return p_->Deactive(); }
+
+auto Module::UnRegister() -> int { return p_->UnRegister(); }
+
auto Module::getChannel() -> int { return p_->GetChannel(); }
auto Module::getDefaultChannel() -> int { return p_->GetDefaultChannel(); }
diff --git a/src/core/module/Module.h b/src/core/module/Module.h
index 2a5b54e7..5eb214cc 100644
--- a/src/core/module/Module.h
+++ b/src/core/module/Module.h
@@ -30,6 +30,7 @@
#include "core/module/Event.h"
#include "core/thread/TaskRunner.h"
+#include "module/sdk/Module.h"
namespace GpgFrontend::Module {
@@ -47,21 +48,27 @@ using TaskRunnerPtr = std::shared_ptr<Thread::TaskRunner>;
class GPGFRONTEND_CORE_EXPORT Module : public QObject {
Q_OBJECT
public:
- Module(ModuleIdentifier, ModuleVersion, const ModuleMetaData&);
+ Module(ModuleIdentifier, ModuleVersion, const ModuleMetaData &);
+
+ explicit Module(QLibrary &module_library);
~Module();
- virtual auto Register() -> bool = 0;
+ auto IsGood() -> bool;
+
+ virtual auto Register() -> int;
+
+ virtual auto Active() -> int;
- virtual auto Active() -> bool = 0;
+ virtual auto Exec(EventRefrernce) -> int;
- virtual auto Exec(EventRefrernce) -> int = 0;
+ virtual auto Deactive() -> int;
- virtual auto Deactive() -> bool = 0;
+ virtual auto UnRegister() -> int;
[[nodiscard]] auto GetModuleIdentifier() const -> ModuleIdentifier;
- void SetGPC(GlobalModuleContext*);
+ void SetGPC(GlobalModuleContext *);
protected:
auto getChannel() -> int;
diff --git a/src/core/module/ModuleManager.cpp b/src/core/module/ModuleManager.cpp
index 83e7c1ff..17191af2 100644
--- a/src/core/module/ModuleManager.cpp
+++ b/src/core/module/ModuleManager.cpp
@@ -29,16 +29,17 @@
#include "ModuleManager.h"
#include <memory>
+#include <utility>
#include "GpgConstants.h"
+#include "core/function/SecureMemoryAllocator.h"
+#include "core/function/basic/GpgFunctionObject.h"
#include "core/module/GlobalModuleContext.h"
#include "core/module/GlobalRegisterTable.h"
#include "core/module/Module.h"
#include "core/thread/Task.h"
-#include "function/SecureMemoryAllocator.h"
-#include "function/basic/GpgFunctionObject.h"
-#include "thread/TaskRunnerGetter.h"
-#include "utils/MemoryUtils.h"
+#include "core/thread/TaskRunnerGetter.h"
+#include "core/utils/MemoryUtils.h"
namespace GpgFrontend::Module {
@@ -50,13 +51,57 @@ class ModuleManager::Impl {
~Impl() = default;
+ auto LoadAndRegisterModule(const QString& module_library_path) -> void {
+ Thread::TaskRunnerGetter::GetInstance()
+ .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default)
+ ->PostTask(new Thread::Task(
+ [=](GpgFrontend::DataObjectPtr) -> int {
+ QLibrary module_library(module_library_path);
+ if (!module_library.load()) {
+ GF_CORE_LOG_WARN(
+ "module manager failed to load module, "
+ "reason: broken library: {} ",
+ module_library.fileName());
+ return -1;
+ }
+
+ auto module = SecureCreateSharedObject<Module>(module_library);
+ if (!module->IsGood()) {
+ GF_CORE_LOG_WARN(
+ "module manager failed to load module, "
+ "reason: illegal module: {}",
+ module_library.fileName());
+ return -1;
+ }
+
+ module->SetGPC(gmc_.get());
+ return gmc_->RegisterModule(module) ? 0 : -1;
+ },
+ __func__, nullptr));
+ }
+
+ auto SearchModule(ModuleIdentifier module_id) -> ModulePtr {
+ return gmc_->SearchModule(std::move(module_id));
+ }
+
void RegisterModule(const ModulePtr& module) {
Thread::TaskRunnerGetter::GetInstance()
.GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default)
->PostTask(new Thread::Task(
[=](GpgFrontend::DataObjectPtr) -> int {
module->SetGPC(gmc_.get());
- gmc_->RegisterModule(module);
+ return gmc_->RegisterModule(module) ? 0 : -1;
+ },
+ __func__, nullptr));
+ }
+
+ void ListenEvent(const ModuleIdentifier& module_id,
+ const EventIdentifier& event_id) {
+ Thread::TaskRunnerGetter::GetInstance()
+ .GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default)
+ ->PostTask(new Thread::Task(
+ [=](const GpgFrontend::DataObjectPtr&) -> int {
+ gmc_->ListenEvent(module_id, event_id);
return 0;
},
__func__, nullptr));
@@ -73,6 +118,11 @@ class ModuleManager::Impl {
__func__, nullptr));
}
+ auto SearchEvent(EventTriggerIdentifier trigger_id)
+ -> std::optional<EventRefrernce> {
+ return gmc_->SearchEvent(std::move(trigger_id));
+ }
+
void ActiveModule(const ModuleIdentifier& identifier) {
Thread::TaskRunnerGetter::GetInstance()
.GetTaskRunner(Thread::TaskRunnerGetter::kTaskRunnerType_Default)
@@ -113,6 +163,7 @@ class ModuleManager::Impl {
static ModuleMangerPtr global_module_manager;
SecureUniquePtr<GlobalModuleContext> gmc_;
SecureUniquePtr<GlobalRegisterTable> grt_;
+ QList<QLibrary> module_libraries_;
};
auto IsModuleAcivate(ModuleIdentifier id) -> bool {
@@ -141,14 +192,32 @@ ModuleManager::ModuleManager(int channel)
ModuleManager::~ModuleManager() = default;
+void ModuleManager::LoadModule(QString module_library_path) {
+ return p_->LoadAndRegisterModule(module_library_path);
+}
+
+auto ModuleManager::SearchModule(ModuleIdentifier module_id) -> ModulePtr {
+ return p_->SearchModule(std::move(module_id));
+}
+
void ModuleManager::RegisterModule(ModulePtr module) {
return p_->RegisterModule(module);
}
+void ModuleManager::ListenEvent(ModuleIdentifier module,
+ EventIdentifier event) {
+ return p_->ListenEvent(module, event);
+}
+
void ModuleManager::TriggerEvent(EventRefrernce event) {
return p_->TriggerEvent(event);
}
+auto ModuleManager::SearchEvent(EventTriggerIdentifier trigger_id)
+ -> std::optional<EventRefrernce> {
+ return p_->SearchEvent(std::move(trigger_id));
+}
+
void ModuleManager::ActiveModule(ModuleIdentifier id) {
return p_->ActiveModule(id);
}
diff --git a/src/core/module/ModuleManager.h b/src/core/module/ModuleManager.h
index 93b89e95..5bebe934 100644
--- a/src/core/module/ModuleManager.h
+++ b/src/core/module/ModuleManager.h
@@ -65,12 +65,20 @@ class GPGFRONTEND_CORE_EXPORT ModuleManager
virtual ~ModuleManager() override;
+ auto LoadModule(QString) -> void;
+
+ auto SearchModule(ModuleIdentifier) -> ModulePtr;
+
void RegisterModule(ModulePtr);
auto IsModuleActivated(ModuleIdentifier) -> bool;
+ void ListenEvent(ModuleIdentifier, EventIdentifier);
+
void TriggerEvent(EventRefrernce);
+ auto SearchEvent(EventTriggerIdentifier) -> std::optional<EventRefrernce>;
+
void ActiveModule(ModuleIdentifier);
void DeactiveModule(ModuleIdentifier);