diff options
Diffstat (limited to 'src/core/module/Module.cpp')
-rw-r--r-- | src/core/module/Module.cpp | 236 |
1 files changed, 232 insertions, 4 deletions
diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp index 9076dc2c..9c875fce 100644 --- a/src/core/module/Module.cpp +++ b/src/core/module/Module.cpp @@ -29,6 +29,10 @@ #include "Module.h" #include "core/module/GlobalModuleContext.h" +#include "core/utils/CommonUtils.h" +#include "core/utils/IOUtils.h" +#include "module/sdk/GFSDKModule.h" +#include "utils/BuildInfoUtils.h" namespace GpgFrontend::Module { @@ -43,7 +47,127 @@ 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), + 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<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; + } + } + + 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; + } + + 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: {}, version: {}, " + "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_(); + + while (p_meta_data != nullptr) { + ::GFModuleMetaData* l_meta_data; + 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; + } + + [[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 EventReference& 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_); } @@ -63,14 +187,77 @@ class Module::Impl { return identifier_; } + [[nodiscard]] auto GetModuleVersion() const -> ModuleVersion { + 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_; + } + + [[nodiscard]] auto GetModulePath() const -> QString { + return module_library_path_; + } + + [[nodiscard]] auto GetModuleHash() const -> QString { return module_hash_; } + void SetGPC(GlobalModuleContext* gpc) { gpc_ = gpc; } private: GlobalModuleContext* gpc_{}; Module* m_ptr_; - const ModuleIdentifier identifier_; - const ModuleVersion version_; - const ModuleMetaData meta_data_; + ModuleIdentifier identifier_; + ModuleVersion version_; + ModuleMetaData meta_data_; + QString module_hash_; + QString module_library_path_; + 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_; + 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; + void** pointer; + }; + + QList<Symbol> module_required_symbols_ = { + {"GFGetModuleGFSDKVersion", reinterpret_cast<void**>(&get_sdk_ver_api_)}, + {"GFGetModuleQtEnvVersion", reinterpret_cast<void**>(&get_qt_ver_api_)}, + {"GFGetModuleID", reinterpret_cast<void**>(&get_id_api_)}, + {"GFGetModuleVersion", reinterpret_cast<void**>(&get_version_api_)}, + {"GFGetModuleMetaData", reinterpret_cast<void**>(&get_metadata_api_)}, + {"GFRegisterModule", reinterpret_cast<void**>(®ister_api_)}, + {"GFActiveModule", reinterpret_cast<void**>(&activate_api_)}, + {"GFExecuteModule", reinterpret_cast<void**>(&execute_api_)}, + {"GFDeactiveModule", reinterpret_cast<void**>(&deactivate_api_)}, + {"GFUnregisterModule", reinterpret_cast<void**>(&unregister_api_)}, + }; auto get_gpc() -> GlobalModuleContext* { if (gpc_ == nullptr) { @@ -84,8 +271,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(EventReference 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(); } @@ -102,5 +306,29 @@ 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(); +} + +[[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 |