From 12d70e1792a5b1ff08d4b58fb49fb9e58d6551a8 Mon Sep 17 00:00:00 2001 From: saturneric Date: Thu, 29 Feb 2024 00:32:43 +0800 Subject: 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 --- src/core/module/Module.cpp | 104 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 4 deletions(-) (limited to 'src/core/module/Module.cpp') 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(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 module_required_symbols_ = { + {"GetModuleID", reinterpret_cast(&get_id_api_)}, + {"GetModuleVersion", reinterpret_cast(&get_version_api_)}, + {"GetModuleMetaData", reinterpret_cast(&get_metadata_api_)}, + {"RegisterModule", reinterpret_cast(®ister_api_)}, + {"ActiveModule", reinterpret_cast(&activate_api_)}, + {"ExecuteModule", reinterpret_cast(&execute_api_)}, + {"DeactiveModule", reinterpret_cast(&deactivate_api_)}, + {"UnregisterModule", reinterpret_cast(&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(this, id, version, meta_data)) {} +Module::Module(QLibrary& module_library) + : p_(SecureCreateUniqueObject(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(); } -- cgit v1.2.3 From c1f5b3336836e15d193582e9b8f3e044f7d8bc1b Mon Sep 17 00:00:00 2001 From: saturneric Date: Thu, 29 Feb 2024 18:15:57 +0800 Subject: feat: add module controller and continue to work on module system 1. speed up building by reducing build info sheader including 2. add module controller 3. continue to work on module system --- src/core/module/Module.cpp | 57 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'src/core/module/Module.cpp') diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp index e943ab09..0534d261 100644 --- a/src/core/module/Module.cpp +++ b/src/core/module/Module.cpp @@ -29,6 +29,7 @@ #include "Module.h" #include "core/module/GlobalModuleContext.h" +#include "core/utils/IOUtils.h" namespace GpgFrontend::Module { @@ -47,7 +48,10 @@ class Module::Impl { good_(true) {} Impl(ModuleRawPtr m_ptr, QLibrary& module_library) - : m_ptr_(m_ptr), good_(false) { + : m_ptr_(m_ptr), + module_hash_(CalculateBinaryChacksum(module_library.fileName())), + module_library_path_(module_library.fileName()), + good_(false) { for (auto& required_symbol : module_required_symbols_) { *required_symbol.pointer = reinterpret_cast(module_library.resolve(required_symbol.name)); @@ -59,13 +63,26 @@ class Module::Impl { } } - SPDLOG_INFO("module loaded, name: {}, verison: {}", - QString::fromUtf8(get_id_api_()), - QString::fromUtf8(get_version_api_())); + GF_CORE_LOG_INFO("module loaded, id: {}, verison: {}, hash: {}, path: {}", + QString::fromUtf8(get_id_api_()), + QString::fromUtf8(get_version_api_()), module_hash_, + module_library_path_); identifier_ = QString::fromUtf8(get_id_api_()); version_ = QString::fromUtf8(get_version_api_()); + ::ModuleMetaData* p_meta_data = get_metadata_api_(); + ::ModuleMetaData* l_meta_data; + + GF_CORE_LOG_DEBUG("AAAAAA: {}", static_cast(p_meta_data)); + while (p_meta_data != nullptr) { + meta_data_[QString::fromUtf8(p_meta_data->key)] = + QString::fromUtf8(p_meta_data->value); + l_meta_data = p_meta_data; + p_meta_data = p_meta_data->next; + SecureFree(l_meta_data); + } + good_ = true; } @@ -116,6 +133,20 @@ class Module::Impl { return identifier_; } + [[nodiscard]] auto GetModuleVersion() const -> ModuleVersion { + return version_; + } + + [[nodiscard]] auto GetModuleMetaData() const -> ModuleMetaData { + return meta_data_; + } + + [[nodiscard]] auto GetModulePath() const -> QString { + return module_library_path_; + } + + [[nodiscard]] auto GetModuleHash() const -> QString { return module_hash_; } + void SetGPC(GlobalModuleContext* gpc) { gpc_ = gpc; } private: @@ -124,6 +155,8 @@ class Module::Impl { ModuleIdentifier identifier_; ModuleVersion version_; ModuleMetaData meta_data_; + QString module_hash_; + QString module_library_path_; bool good_; ModuleAPIGetModuleID get_id_api_; @@ -198,5 +231,21 @@ auto Module::GetModuleIdentifier() const -> ModuleIdentifier { return p_->GetModuleIdentifier(); } +[[nodiscard]] auto Module::GetModuleVersion() const -> ModuleVersion { + return p_->GetModuleVersion(); +} + +[[nodiscard]] auto Module::GetModuleMetaData() const -> ModuleMetaData { + return p_->GetModuleMetaData(); +} + +[[nodiscard]] auto Module::GetModulePath() const -> QString { + return p_->GetModulePath(); +} + +[[nodiscard]] auto Module::GetModuleHash() const -> QString { + return p_->GetModuleHash(); +} + void Module::SetGPC(GlobalModuleContext* gpc) { p_->SetGPC(gpc); } } // namespace GpgFrontend::Module \ No newline at end of file -- cgit v1.2.3 From 84b04d88723ef05f7873082c235ecfd56facf934 Mon Sep 17 00:00:00 2001 From: saturneric Date: Thu, 29 Feb 2024 22:36:25 +0800 Subject: feat: add prefix GF to all sdk and module symbols --- src/core/module/Module.cpp | 57 ++++++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 25 deletions(-) (limited to 'src/core/module/Module.cpp') diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp index 0534d261..0c45dcbe 100644 --- a/src/core/module/Module.cpp +++ b/src/core/module/Module.cpp @@ -29,7 +29,9 @@ #include "Module.h" #include "core/module/GlobalModuleContext.h" +#include "core/utils/CommonUtils.h" #include "core/utils/IOUtils.h" +#include "module/sdk/GFSDKModule.h" namespace GpgFrontend::Module { @@ -63,18 +65,15 @@ class Module::Impl { } } - GF_CORE_LOG_INFO("module loaded, id: {}, verison: {}, hash: {}, path: {}", - QString::fromUtf8(get_id_api_()), - QString::fromUtf8(get_version_api_()), module_hash_, - module_library_path_); + identifier_ = GFUnStrDup(get_id_api_()); + version_ = GFUnStrDup(get_version_api_()); - identifier_ = QString::fromUtf8(get_id_api_()); - version_ = QString::fromUtf8(get_version_api_()); + GF_CORE_LOG_INFO("module loaded, id: {}, verison: {}, hash: {}, path: {}", + identifier_, version_, module_hash_, module_library_path_); - ::ModuleMetaData* p_meta_data = get_metadata_api_(); - ::ModuleMetaData* l_meta_data; + ::GFModuleMetaData* p_meta_data = get_metadata_api_(); + ::GFModuleMetaData* l_meta_data; - GF_CORE_LOG_DEBUG("AAAAAA: {}", static_cast(p_meta_data)); while (p_meta_data != nullptr) { meta_data_[QString::fromUtf8(p_meta_data->key)] = QString::fromUtf8(p_meta_data->value); @@ -157,16 +156,22 @@ class Module::Impl { ModuleMetaData meta_data_; QString module_hash_; QString module_library_path_; + QString gf_sdk_ver_; + QString qt_env_ver_; 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_; + + GFModuleAPIGetModuleGFSDKVersion get_sdk_ver_api_; + GFModuleAPIGetModuleQtEnvVersion get_qt_ver_api_; + + GFModuleAPIGetModuleID get_id_api_; + GFModuleAPIGetModuleVersion get_version_api_; + GFModuleAPIGetModuleMetaData get_metadata_api_; + GFModuleAPIRegisterModule register_api_; + GFModuleAPIActivateModule activate_api_; + GFModuleAPIExecuteModule execute_api_; + GFModuleAPIDeactivateModule deactivate_api_; + GFModuleAPIUnregisterModule unregister_api_; struct Symbol { const char* name; @@ -174,14 +179,16 @@ class Module::Impl { }; QList module_required_symbols_ = { - {"GetModuleID", reinterpret_cast(&get_id_api_)}, - {"GetModuleVersion", reinterpret_cast(&get_version_api_)}, - {"GetModuleMetaData", reinterpret_cast(&get_metadata_api_)}, - {"RegisterModule", reinterpret_cast(®ister_api_)}, - {"ActiveModule", reinterpret_cast(&activate_api_)}, - {"ExecuteModule", reinterpret_cast(&execute_api_)}, - {"DeactiveModule", reinterpret_cast(&deactivate_api_)}, - {"UnregisterModule", reinterpret_cast(&unregister_api_)}, + {"GFGetModuleGFSDKVersion", reinterpret_cast(&get_sdk_ver_api_)}, + {"GFGetModuleQtEnvVersion", reinterpret_cast(&get_qt_ver_api_)}, + {"GFGetModuleID", reinterpret_cast(&get_id_api_)}, + {"GFGetModuleVersion", reinterpret_cast(&get_version_api_)}, + {"GFGetModuleMetaData", reinterpret_cast(&get_metadata_api_)}, + {"GFRegisterModule", reinterpret_cast(®ister_api_)}, + {"GFActiveModule", reinterpret_cast(&activate_api_)}, + {"GFExecuteModule", reinterpret_cast(&execute_api_)}, + {"GFDeactiveModule", reinterpret_cast(&deactivate_api_)}, + {"GFUnregisterModule", reinterpret_cast(&unregister_api_)}, }; auto get_gpc() -> GlobalModuleContext* { -- cgit v1.2.3 From a74841f70cfe985ca12af353ed289925085241c1 Mon Sep 17 00:00:00 2001 From: saturneric Date: Fri, 1 Mar 2024 14:36:33 +0800 Subject: feat: validate module id format and compatibility of sdk and qt env --- src/core/module/Module.cpp | 80 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) (limited to 'src/core/module/Module.cpp') diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp index 0c45dcbe..39f4f4a9 100644 --- a/src/core/module/Module.cpp +++ b/src/core/module/Module.cpp @@ -32,6 +32,7 @@ #include "core/utils/CommonUtils.h" #include "core/utils/IOUtils.h" #include "module/sdk/GFSDKModule.h" +#include "utils/BuildInfoUtils.h" namespace GpgFrontend::Module { @@ -67,9 +68,63 @@ class Module::Impl { identifier_ = GFUnStrDup(get_id_api_()); version_ = GFUnStrDup(get_version_api_()); + gf_sdk_ver_ = GFUnStrDup(get_sdk_ver_api_()); + qt_env_ver_ = GFUnStrDup(get_qt_ver_api_()); + + if (!module_identifier_regex_exp_.match(identifier_).hasMatch()) { + GF_CORE_LOG_WARN( + "illegal module: {}, reasson invalid module id, abort...", + identifier_); + return; + } + + if (!module_version_regex_exp_.match(version_).hasMatch()) { + GF_CORE_LOG_WARN( + "illegal module: {}, reasson invalid version: {}, abort...", + identifier_, version_); + return; + } - GF_CORE_LOG_INFO("module loaded, id: {}, verison: {}, hash: {}, path: {}", - identifier_, version_, module_hash_, module_library_path_); + if (!module_version_regex_exp_.match(gf_sdk_ver_).hasMatch()) { + GF_CORE_LOG_WARN( + "illegal module: {}, reasson invalid sdk version: {}, abort...", + identifier_, gf_sdk_ver_); + return; + } + + if (GFCompareSoftwareVersion(gf_sdk_ver_, GetProjectVersion()) > 0) { + GF_CORE_LOG_WARN( + "uncompatible module: {}, sdk version: {} greater than " + "current sdk version: {}, abort...", + identifier_, gf_sdk_ver_, GetProjectVersion()); + return; + } + + auto qt_env_ver_regex_match = module_version_regex_exp_.match(qt_env_ver_); + if (!qt_env_ver_regex_match.hasMatch()) { + GF_CORE_LOG_WARN( + "illegal module: {}, reasson invalid qt env version: {}, abort...", + identifier_, qt_env_ver_); + return; + } + + auto qt_env_ver_major = qt_env_ver_regex_match.captured(1); + auto qt_env_ver_minor = qt_env_ver_regex_match.captured(2); + + if (qt_env_ver_major != QString::number(QT_VERSION_MAJOR) + "." || + qt_env_ver_minor != QString::number(QT_VERSION_MINOR) + ".") { + GF_CORE_LOG_WARN( + "uncompatible module: {}, qt version: {} is not binary uncompatible " + "with application's qt env version: {}, abort...", + identifier_, qt_env_ver_, QString::fromUtf8(QT_VERSION_STR)); + return; + } + + GF_CORE_LOG_INFO( + "module loaded, id: {}, verison: {}, " + "sdk version: {}, qt env version: {}, hash: {}, path: {}", + identifier_, version_, gf_sdk_ver_, qt_env_ver_, module_hash_, + module_library_path_); ::GFModuleMetaData* p_meta_data = get_metadata_api_(); ::GFModuleMetaData* l_meta_data; @@ -136,6 +191,14 @@ class Module::Impl { return version_; } + [[nodiscard]] auto GetModuleSDKVersion() const -> QString { + return gf_sdk_ver_; + } + + [[nodiscard]] auto GetModuleQtEnvVersion() const -> QString { + return qt_env_ver_; + } + [[nodiscard]] auto GetModuleMetaData() const -> ModuleMetaData { return meta_data_; } @@ -159,6 +222,11 @@ class Module::Impl { QString gf_sdk_ver_; QString qt_env_ver_; + QRegularExpression module_identifier_regex_exp_ = QRegularExpression( + R"(^([A-Za-z]{1}[A-Za-z\d_]*\.)+[A-Za-z][A-Za-z\d_]*$)"); + QRegularExpression module_version_regex_exp_ = + QRegularExpression(R"(^(\d+\.)?(\d+\.)?(\*|\d+)$)"); + bool good_; GFModuleAPIGetModuleGFSDKVersion get_sdk_ver_api_; @@ -254,5 +322,13 @@ auto Module::GetModuleIdentifier() const -> ModuleIdentifier { return p_->GetModuleHash(); } +[[nodiscard]] auto Module::GetModuleSDKVersion() const -> QString { + return p_->GetModuleSDKVersion(); +} + +[[nodiscard]] auto Module::GetModuleQtEnvVersion() const -> QString { + return p_->GetModuleQtEnvVersion(); +} + void Module::SetGPC(GlobalModuleContext* gpc) { p_->SetGPC(gpc); } } // namespace GpgFrontend::Module \ No newline at end of file -- cgit v1.2.3