From 6dbf9968e1919499677feac91a542a9f293495a6 Mon Sep 17 00:00:00 2001 From: QxQ <59914293+U-v-U@users.noreply.github.com> Date: Wed, 14 Oct 2020 22:59:39 +0800 Subject: [PATCH] refactor: more refactors, fixed previously introduced SingleApplication bug --- makespec/BUILDVERSION | 2 +- src/base/Qv2rayBaseApplication.hpp | 7 +-- src/core/settings/SettingsBackend.cpp | 4 +- src/main.cpp | 61 +++++--------------- src/ui/Qv2rayPlatformApplication.cpp | 57 ++++++++++++++---- src/ui/Qv2rayPlatformApplication.hpp | 21 +++++-- src/ui/widgets/Qv2rayWidgetApplication.cpp | 21 +++---- src/ui/widgets/Qv2rayWidgetApplication.hpp | 6 +- src/ui/widgets/windows/w_MainWindow.cpp | 2 +- test/src/components/latency/TestRealPing.cpp | 8 --- 10 files changed, 91 insertions(+), 98 deletions(-) diff --git a/makespec/BUILDVERSION b/makespec/BUILDVERSION index 9719c24c..a21cde55 100644 --- a/makespec/BUILDVERSION +++ b/makespec/BUILDVERSION @@ -1 +1 @@ -6001 +6002 diff --git a/src/base/Qv2rayBaseApplication.hpp b/src/base/Qv2rayBaseApplication.hpp index 075010f0..e2d26201 100644 --- a/src/base/Qv2rayBaseApplication.hpp +++ b/src/base/Qv2rayBaseApplication.hpp @@ -21,9 +21,8 @@ namespace Qv2ray EXIT_NORMAL = 0, EXIT_NEW_VERSION_TRIGGER = EXIT_NORMAL, EXIT_SECONDARY_INSTANCE = EXIT_NORMAL, - EXIT_PREINITIALIZATION_FAILED = -1, + EXIT_INITIALIZATION_FAILED = -1, EXIT_PRECONDITION_FAILED = -2, - EXIT_CRASHED = -9, }; struct Qv2rayStartupArguments @@ -58,7 +57,6 @@ namespace Qv2ray public: Qv2ray::base::config::Qv2rayConfigObject *ConfigObject; QString ConfigPath; - Qv2rayExitReason ExitReason; Qv2rayStartupArguments StartupArguments; public: @@ -68,9 +66,6 @@ namespace Qv2ray public: virtual QStringList GetAssetsPaths(const QString &dirName) const final; // - virtual bool Initialize() = 0; - virtual Qv2rayExitReason RunQv2ray() = 0; - // virtual void MessageBoxWarn(QWidget *parent, const QString &title, const QString &text, MessageOpt button) = 0; virtual void MessageBoxInfo(QWidget *parent, const QString &title, const QString &text, MessageOpt button) = 0; virtual MessageOpt MessageBoxAsk(QWidget *parent, const QString &title, const QString &text, const QList &buttons) = 0; diff --git a/src/core/settings/SettingsBackend.cpp b/src/core/settings/SettingsBackend.cpp index a4d5ec46..023f4c68 100644 --- a/src/core/settings/SettingsBackend.cpp +++ b/src/core/settings/SettingsBackend.cpp @@ -212,8 +212,8 @@ namespace Qv2ray::core::config return false; } - GlobalConfig.kernelConfig.KernelPath(QString(QV2RAY_DEFAULT_VCORE_PATH)); - GlobalConfig.kernelConfig.AssetsPath(QString(QV2RAY_DEFAULT_VASSETS_PATH)); + GlobalConfig.kernelConfig.KernelPath(QV2RAY_DEFAULT_VCORE_PATH); + GlobalConfig.kernelConfig.AssetsPath(QV2RAY_DEFAULT_VASSETS_PATH); GlobalConfig.logLevel = 3; GlobalConfig.uiConfig.language = QLocale::system().name(); GlobalConfig.defaultRouteConfig.dnsConfig.servers.append({ "1.1.1.1" }); diff --git a/src/main.cpp b/src/main.cpp index 355f2b26..96e40cfe 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -15,7 +15,6 @@ #include "utils/QvHelpers.hpp" -#include #include #ifndef Q_OS_WIN @@ -180,30 +179,6 @@ LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS) } #endif -void ProcessExitReason(Qv2rayExitReason reason) -{ // app.MessageBoxWarn(nullptr, app.tr("Cannot start Qv2ray"), app.tr("Qv2ray early initialization failed.")); - // return QVEXIT_EARLY_SETUP_FAIL; - switch (reason) - { - case EXIT_CRASHED: - { - break; - } - case EXIT_NORMAL: - { - break; - } - case EXIT_PREINITIALIZATION_FAILED: - { - break; - } - case EXIT_PRECONDITION_FAILED: - { - break; - } - } -} - int main(int argc, char *argv[]) { globalArgc = argc; @@ -258,31 +233,22 @@ int main(int argc, char *argv[]) QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps, true); #endif - // Check OpenSSL version for auto-update and subscriptions - auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString(); - auto osslCurVersion = QSslSocket::sslLibraryVersionString(); - LOG("Current OpenSSL version: " + osslCurVersion); - - if (!QSslSocket::supportsSsl()) + Qv2rayApplication app(argc, argv); + if (const auto list = app.CheckPrerequisites(); !list.isEmpty()) { - LOG("Required OpenSSL version: " + osslReqVersion); - LOG("OpenSSL library MISSING, Quitting."); - BootstrapMessageBox(QObject::tr("Dependency Missing"), - QObject::tr("Cannot find openssl libs") + NEWLINE + - QObject::tr("This could be caused by a missing of `openssl` package in your system.") + NEWLINE + - QObject::tr("If you are using an AppImage from Github Action, please report a bug.") + NEWLINE + // - NEWLINE + QObject::tr("Technical Details") + NEWLINE + // - "OSsl.Rq.V=" + osslReqVersion + NEWLINE + // - "OSsl.Cr.V=" + osslCurVersion); - BootstrapMessageBox(QObject::tr("Cannot start Qv2ray"), QObject::tr("Cannot start Qv2ray without OpenSSL")); - return -1; + BootstrapMessageBox("Qv2ray Prerequisites Check Failed", list.join(NEWLINE)); + return Qv2rayExitReason::EXIT_PRECONDITION_FAILED; } - Qv2rayApplication app(argc, argv); if (!app.Initialize()) { - LOG("Qv2ray initialization failed:", app.ExitReason); - ProcessExitReason(app.ExitReason); + const auto reason = app.GetExitReason(); + if (reason == EXIT_INITIALIZATION_FAILED) + { + BootstrapMessageBox("Qv2ray Initialization Failed", "PreInitialization Failed." NEWLINE "For more information, please see the log."); + LOG("Qv2ray initialization failed:", reason); + } + return reason; } #ifndef Q_OS_WIN @@ -291,10 +257,11 @@ int main(int argc, char *argv[]) #endif app.RunQv2ray(); - if (app.ExitReason == EXIT_NEW_VERSION_TRIGGER) + const auto reason = app.GetExitReason(); + if (reason == EXIT_NEW_VERSION_TRIGGER) { LOG("Starting new version of Qv2ray: " + app.StartupArguments._qvNewVersionPath); QProcess::startDetached(app.StartupArguments._qvNewVersionPath, {}); } - return app.ExitReason; + return reason; } diff --git a/src/ui/Qv2rayPlatformApplication.cpp b/src/ui/Qv2rayPlatformApplication.cpp index 0cac664d..895a68d1 100644 --- a/src/ui/Qv2rayPlatformApplication.cpp +++ b/src/ui/Qv2rayPlatformApplication.cpp @@ -1,6 +1,8 @@ #include "Qv2rayPlatformApplication.hpp" #include "core/settings/SettingsBackend.hpp" + +#include #define QV_MODULE_NAME "PlatformApplication" #ifdef QT_DEBUG @@ -9,13 +11,42 @@ const static inline QString QV2RAY_URL_SCHEME = "qv2ray-debug"; const static inline QString QV2RAY_URL_SCHEME = "qv2ray"; #endif -bool Qv2rayPlatformApplication::initializeInternal() +QStringList Qv2rayPlatformApplication::CheckPrerequisites() +{ + QStringList errors; + if (!QSslSocket::supportsSsl()) + { + // Check OpenSSL version for auto-update and subscriptions + const auto osslReqVersion = QSslSocket::sslLibraryBuildVersionString(); + const auto osslCurVersion = QSslSocket::sslLibraryVersionString(); + LOG("Current OpenSSL version: " + osslCurVersion); + LOG("Required OpenSSL version: " + osslReqVersion); + errors << "Qv2ray cannot run without OpenSSL."; + errors << "This is usually caused by using the wrong version of OpenSSL"; + errors << "Required=" + osslReqVersion + "Current=" + osslCurVersion; + } + return errors + checkPrerequisitesInternal(); +} + +bool Qv2rayPlatformApplication::Initialize() { QString errorMessage; bool canContinue; - auto hasError = parseCommandLine(&errorMessage, &canContinue); - if (hasError && !canContinue) - return false; + const auto hasError = parseCommandLine(&errorMessage, &canContinue); + if (hasError) + { + LOG("Command line:" A(errorMessage)); + if (!canContinue) + { + LOG("Fatal, Qv2ray cannot continue."); + return false; + } + else + { + LOG("Non-fatal error, continue starting up."); + } + } + #ifdef Q_OS_WIN const auto appPath = QDir::toNativeSeparators(applicationFilePath()); const auto regPath = "HKEY_CURRENT_USER\\Software\\Classes\\" + QV2RAY_URL_SCHEME; @@ -37,15 +68,18 @@ bool Qv2rayPlatformApplication::initializeInternal() if (isSecondary()) { StartupArguments.version = QV2RAY_VERSION_STRING; + StartupArguments.buildVersion = QV2RAY_VERSION_BUILD; StartupArguments.fullArgs = arguments(); if (StartupArguments.arguments.isEmpty()) StartupArguments.arguments << Qv2rayStartupArguments::NORMAL; bool status = sendMessage(JsonToString(StartupArguments.toJson(), QJsonDocument::Compact).toUtf8()); if (!status) LOG("Cannot send message."); - return true; + SetExitReason(EXIT_SECONDARY_INSTANCE); + return false; } #endif + #ifdef QV2RAY_GUI #ifdef Q_OS_LINUX #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) @@ -58,6 +92,7 @@ bool Qv2rayPlatformApplication::initializeInternal() SaveGlobalSettings(); }); #endif + #ifdef Q_OS_WIN SetCurrentDirectory(applicationDirPath().toStdWString().c_str()); // Set special font in Windows @@ -71,12 +106,10 @@ bool Qv2rayPlatformApplication::initializeInternal() // Install a default translater. From the OS/DE Qv2rayTranslator = std::make_unique(); Qv2rayTranslator->InstallTranslation(QLocale::system().name()); - // - // - LocateConfiguration(); - // const auto allTranslations = Qv2rayTranslator->GetAvailableLanguages(); const auto osLanguage = QLocale::system().name(); + // + LocateConfiguration(); if (!allTranslations.contains(GlobalConfig.uiConfig.language)) { // If we need to reset the language. @@ -102,12 +135,12 @@ bool Qv2rayPlatformApplication::initializeInternal() return true; } -bool Qv2rayPlatformApplication::runInternal() +Qv2rayExitReason Qv2rayPlatformApplication::RunQv2ray() { PluginHost = new QvPluginHost(); RouteManager = new RouteHandler(); ConnectionManager = new QvConfigHandler(); - return true; + return runQv2rayInternal(); } void Qv2rayPlatformApplication::quitInternal() @@ -118,7 +151,7 @@ void Qv2rayPlatformApplication::quitInternal() ConnectionManager->SaveConnectionConfig(); PluginHost->SavePluginSettings(); SaveGlobalSettings(); - TerminateUI(); + terminateUIInternal(); delete ConnectionManager; delete RouteManager; delete PluginHost; diff --git a/src/ui/Qv2rayPlatformApplication.hpp b/src/ui/Qv2rayPlatformApplication.hpp index bee7ac43..05c8b49c 100644 --- a/src/ui/Qv2rayPlatformApplication.hpp +++ b/src/ui/Qv2rayPlatformApplication.hpp @@ -51,21 +51,30 @@ class Qv2rayPlatformApplication public: Qv2rayPlatformApplication(int &argc, char *argv[]) : QVBASEAPPLICATION(QVBASEAPPLICATION_CTORARGS), Qv2rayApplicationInterface(){}; virtual ~Qv2rayPlatformApplication(){}; - inline void QuitApplication(int retCode = 0) + virtual Qv2rayExitReason GetExitReason() const final { - QCoreApplication::exit(retCode); + return _exitReason; } + virtual QStringList CheckPrerequisites() final; + virtual bool Initialize() final; + virtual Qv2rayExitReason RunQv2ray() final; + protected: - bool initializeInternal(); - bool runInternal(); - void quitInternal(); - virtual void TerminateUI() = 0; + virtual QStringList checkPrerequisitesInternal() = 0; + virtual Qv2rayExitReason runQv2rayInternal() = 0; + virtual void terminateUIInternal() = 0; + virtual void SetExitReason(Qv2rayExitReason r) final + { + _exitReason = r; + } #ifndef QV2RAY_NO_SINGLEAPPLICATON virtual void onMessageReceived(quint32 clientId, QByteArray msg) = 0; #endif private: + void quitInternal(); + Qv2rayExitReason _exitReason; bool parseCommandLine(QString *errorMessage, bool *canContinue); }; diff --git a/src/ui/widgets/Qv2rayWidgetApplication.cpp b/src/ui/widgets/Qv2rayWidgetApplication.cpp index f074fd40..4b614894 100644 --- a/src/ui/widgets/Qv2rayWidgetApplication.cpp +++ b/src/ui/widgets/Qv2rayWidgetApplication.cpp @@ -25,17 +25,12 @@ Qv2rayWidgetApplication::Qv2rayWidgetApplication(int &argc, char *argv[]) : Qv2r { } -bool Qv2rayWidgetApplication::Initialize() +QStringList Qv2rayWidgetApplication::checkPrerequisitesInternal() { - const auto result = initializeInternal(); - if (!result) - return false; - setQuitOnLastWindowClosed(false); - hTray = new QSystemTrayIcon(); - return true; + return {}; } -void Qv2rayWidgetApplication::TerminateUI() +void Qv2rayWidgetApplication::terminateUIInternal() { delete mainWindow; delete hTray; @@ -73,7 +68,7 @@ void Qv2rayWidgetApplication::onMessageReceived(quint32 clientId, QByteArray _ms if (result == Yes) { StartupArguments._qvNewVersionPath = newPath; - QuitApplication(EXIT_NEW_VERSION_TRIGGER); + SetExitReason(EXIT_NEW_VERSION_TRIGGER); } } @@ -83,7 +78,8 @@ void Qv2rayWidgetApplication::onMessageReceived(quint32 clientId, QByteArray _ms { case Qv2rayStartupArguments::EXIT: { - QuitApplication(); + SetExitReason(EXIT_NORMAL); + quit(); break; } case Qv2rayStartupArguments::NORMAL: @@ -128,9 +124,10 @@ void Qv2rayWidgetApplication::onMessageReceived(quint32 clientId, QByteArray _ms } #endif -Qv2rayExitReason Qv2rayWidgetApplication::RunQv2ray() +Qv2rayExitReason Qv2rayWidgetApplication::runQv2rayInternal() { - runInternal(); + setQuitOnLastWindowClosed(false); + hTray = new QSystemTrayIcon(); StyleManager = new QvStyleManager(); StyleManager->ApplyStyle(GlobalConfig.uiConfig.theme); // Show MainWindow diff --git a/src/ui/widgets/Qv2rayWidgetApplication.hpp b/src/ui/widgets/Qv2rayWidgetApplication.hpp index 9f43aeb4..0c653a3f 100644 --- a/src/ui/widgets/Qv2rayWidgetApplication.hpp +++ b/src/ui/widgets/Qv2rayWidgetApplication.hpp @@ -13,8 +13,6 @@ namespace Qv2ray Q_OBJECT public: explicit Qv2rayWidgetApplication(int &argc, char *argv[]); - bool Initialize() override; - Qv2rayExitReason RunQv2ray() override; QJsonObject UIStates; public: @@ -31,8 +29,10 @@ namespace Qv2ray } private: + QStringList checkPrerequisitesInternal() override; + Qv2rayExitReason runQv2rayInternal() override; bool isInitialized; - void TerminateUI() override; + void terminateUIInternal() override; #ifndef QV2RAY_NO_SINGLEAPPLICATON void onMessageReceived(quint32 clientID, QByteArray msg) override; #endif diff --git a/src/ui/widgets/windows/w_MainWindow.cpp b/src/ui/widgets/windows/w_MainWindow.cpp index b27c890c..1ecc3a9e 100644 --- a/src/ui/widgets/windows/w_MainWindow.cpp +++ b/src/ui/widgets/windows/w_MainWindow.cpp @@ -484,7 +484,7 @@ void MainWindow::on_activatedTray(QSystemTrayIcon::ActivationReason reason) void MainWindow::Action_Exit() { ConnectionManager->StopConnection(); - QvWidgetApplication->QuitApplication(); + QvWidgetApplication->quit(); } void MainWindow::on_preferencesBtn_clicked() diff --git a/test/src/components/latency/TestRealPing.cpp b/test/src/components/latency/TestRealPing.cpp index 84d2b610..1802dd9c 100644 --- a/test/src/components/latency/TestRealPing.cpp +++ b/test/src/components/latency/TestRealPing.cpp @@ -12,14 +12,6 @@ class QvTestApplication { public: explicit QvTestApplication() : QCoreApplication(fakeArgc, fakeArgv), Qv2rayApplicationInterface(){}; - virtual bool Initialize() override - { - return true; - }; - virtual Qv2rayExitReason RunQv2ray() override - { - return {}; - }; virtual void MessageBoxWarn(QWidget *, const QString &, const QString &, MessageOpt) override{}; virtual void MessageBoxInfo(QWidget *, const QString &, const QString &, MessageOpt) override{}; virtual MessageOpt MessageBoxAsk(QWidget *, const QString &, const QString &, const QList &) override