From e43725473c8e00f156bfb20c5cb77ebbfaf74886 Mon Sep 17 00:00:00 2001 From: NickVs2015 Date: Fri, 30 Jan 2026 14:36:29 +0300 Subject: [PATCH] feat: fix auto switch --- client/amnezia_application.h | 2 - client/core/controllers/coreController.cpp | 9 ++ client/core/controllers/coreController.h | 3 - .../controllers/api/apiConfigsController.cpp | 2 + .../ui/controllers/api/apiConfigsController.h | 1 + .../ui/controllers/connectionController.cpp | 116 +++++++++--------- client/ui/controllers/connectionController.h | 9 ++ 7 files changed, 81 insertions(+), 61 deletions(-) diff --git a/client/amnezia_application.h b/client/amnezia_application.h index 4dfcf39ab..c2f790354 100644 --- a/client/amnezia_application.h +++ b/client/amnezia_application.h @@ -44,8 +44,6 @@ public: QQmlApplicationEngine *qmlEngine() const; QNetworkAccessManager *networkManager(); QClipboard *getClipboard(); - CoreController *coreController() const { return m_coreController.data(); } - public slots: void forceQuit(); diff --git a/client/core/controllers/coreController.cpp b/client/core/controllers/coreController.cpp index 26267219a..7704850b8 100644 --- a/client/core/controllers/coreController.cpp +++ b/client/core/controllers/coreController.cpp @@ -125,6 +125,15 @@ void CoreController::initControllers() connect(m_installController.get(), &InstallController::profileCleared, m_protocolsModel.get(), &ProtocolsModel::updateModel); + connect(m_connectionController.get(), &ConnectionController::requestSetCurrentProtocol, + m_apiConfigsController.get(), &ApiConfigsController::setCurrentProtocol, Qt::QueuedConnection); + connect(m_connectionController.get(), &ConnectionController::requestUpdateServiceFromGateway, + m_apiConfigsController.get(), &ApiConfigsController::updateServiceFromGateway, Qt::QueuedConnection); + + connect(m_apiConfigsController.get(), &ApiConfigsController::updateServiceFromGatewayCompleted, + m_connectionController.get(), &ConnectionController::onUpdateServiceFromGatewayCompleted, + Qt::QueuedConnection); + m_importController.reset(new ImportController(m_serversModel, m_containersModel, m_settings)); m_engine->rootContext()->setContextProperty("ImportController", m_importController.get()); diff --git a/client/core/controllers/coreController.h b/client/core/controllers/coreController.h index 6d9d2de2a..998e7d8d0 100644 --- a/client/core/controllers/coreController.h +++ b/client/core/controllers/coreController.h @@ -62,9 +62,6 @@ public: QQmlApplicationEngine *engine, QObject *parent = nullptr); QSharedPointer pageController() const; - QSharedPointer serversModel() const { return m_serversModel; } - ConnectionController *connectionController() const { return m_connectionController.get(); } - ApiConfigsController *apiConfigsController() const { return m_apiConfigsController.data(); } void setQmlRoot(); void openConnectionByIndex(int serverIndex); diff --git a/client/ui/controllers/api/apiConfigsController.cpp b/client/ui/controllers/api/apiConfigsController.cpp index 17339ac52..a78929177 100644 --- a/client/ui/controllers/api/apiConfigsController.cpp +++ b/client/ui/controllers/api/apiConfigsController.cpp @@ -709,9 +709,11 @@ bool ApiConfigsController::updateServiceFromGateway(const int serverIndex, const } else { emit changeApiCountryFinished(tr("Successfully changed the country of connection to %1").arg(newCountryName)); } + emit updateServiceFromGatewayCompleted(true, serverIndex); return true; } else { emit errorOccurred(errorCode); + emit updateServiceFromGatewayCompleted(false, serverIndex); return false; } } diff --git a/client/ui/controllers/api/apiConfigsController.h b/client/ui/controllers/api/apiConfigsController.h index f53ffa964..3ac064c65 100644 --- a/client/ui/controllers/api/apiConfigsController.h +++ b/client/ui/controllers/api/apiConfigsController.h @@ -49,6 +49,7 @@ signals: void changeApiCountryFinished(const QString &message); void reloadServerFromApiFinished(const QString &message); void updateServerFromApiFinished(); + void updateServiceFromGatewayCompleted(bool success, int serverIndex); void vpnKeyExportReady(); diff --git a/client/ui/controllers/connectionController.cpp b/client/ui/controllers/connectionController.cpp index 1ce818d05..dcbb57fea 100644 --- a/client/ui/controllers/connectionController.cpp +++ b/client/ui/controllers/connectionController.cpp @@ -7,7 +7,6 @@ #endif #include "utilities.h" -#include "amnezia_application.h" #include "core/controllers/vpnConfigurationController.h" #include "core/api/apiUtils.h" #include "containers/containers_defs.h" @@ -194,63 +193,21 @@ void ConnectionController::onAwgStateTimeout() return; } - const QJsonObject serverConfig = m_serversModel->getServerConfig(serverIndex); + qDebug().noquote() + << "AWG connect timeout: trying to switch API protocol to VLESS" + << "and reload config from gateway for premium server index" << serverIndex; - bool apiSwitched = false; - bool hasXray = false; + // Store state for async operation + m_pendingApiServerIndex = serverIndex; + m_apiSwitched = false; + m_waitingForApiUpdate = true; - if (auto app = amnApp) { - if (auto core = app->coreController()) { - if (auto api = core->apiConfigsController()) { - qDebug().noquote() - << "AWG connect timeout: trying to switch API protocol to VLESS" - << "and reload config from gateway for premium server index" << serverIndex; - - m_serversModel->setProcessedServerIndex(serverIndex); - api->setCurrentProtocol(QStringLiteral("vless")); - apiSwitched = api->updateServiceFromGateway(serverIndex, QString(), QString(), true); - - if (apiSwitched) { - const QJsonObject newServerConfig = m_serversModel->getServerConfig(serverIndex); - const QJsonArray newContainers = newServerConfig.value(config_key::containers).toArray(); - for (const QJsonValue &value : newContainers) { - const QJsonObject obj = value.toObject(); - const DockerContainer c = - ContainerProps::containerFromString(obj.value(config_key::container).toString()); - if (c == DockerContainer::Xray) { - hasXray = true; - break; - } - } - } - } - } - } - - if (!hasXray) { - qDebug().noquote() - << "AWG connect timeout: no XRay available for server index" << serverIndex - << "(API switch attempt success =" << (apiSwitched ? "YES" : "NO") << ")"; - return; - } - - qDebug().noquote() << "AWG connect timeout (10s), switching default container to XRay for server index" - << serverIndex << "and reconnecting"; - - m_serversModel->setDefaultContainer(serverIndex, static_cast(DockerContainer::Xray)); - - if (auto app = amnApp) { - if (auto core = app->coreController()) { - if (auto api = core->apiConfigsController()) { - m_serversModel->setProcessedServerIndex(serverIndex); - api->setCurrentProtocol(QStringLiteral("vless")); - } - } - } - - if (!m_isConnected && !m_isConnectionInProgress) { - emit prepareConfig(); - } + m_serversModel->setProcessedServerIndex(serverIndex); + + emit requestSetCurrentProtocol(QStringLiteral("vless")); + emit requestUpdateServiceFromGateway(serverIndex, QString(), QString(), true); + + return; }); } @@ -306,6 +263,53 @@ bool ConnectionController::isConnected() const return m_isConnected; } +void ConnectionController::onUpdateServiceFromGatewayCompleted(bool success, int serverIndex) +{ + if (!m_waitingForApiUpdate || m_pendingApiServerIndex != serverIndex) { + return; + } + + m_waitingForApiUpdate = false; + m_apiSwitched = success; + bool hasXray = false; + + if (success) { + const QJsonObject newServerConfig = m_serversModel->getServerConfig(serverIndex); + const QJsonArray newContainers = newServerConfig.value(config_key::containers).toArray(); + for (const QJsonValue &value : newContainers) { + const QJsonObject obj = value.toObject(); + const DockerContainer c = + ContainerProps::containerFromString(obj.value(config_key::container).toString()); + if (c == DockerContainer::Xray) { + hasXray = true; + break; + } + } + } + + if (!hasXray) { + qDebug().noquote() + << "AWG connect timeout: no XRay available for server index" << serverIndex + << "(API switch attempt success =" << (m_apiSwitched ? "YES" : "NO") << ")"; + m_pendingApiServerIndex = -1; + return; + } + + qDebug().noquote() << "AWG connect timeout (10s), switching default container to XRay for server index" + << serverIndex << "and reconnecting"; + + m_serversModel->setDefaultContainer(serverIndex, static_cast(DockerContainer::Xray)); + + m_serversModel->setProcessedServerIndex(serverIndex); + emit requestSetCurrentProtocol(QStringLiteral("vless")); + + m_pendingApiServerIndex = -1; + + if (!m_isConnected && !m_isConnectionInProgress) { + emit prepareConfig(); + } +} + void ConnectionController::checkAndStartAwgStateTimer() { const int serverIndex = m_serversModel->getDefaultServerIndex(); diff --git a/client/ui/controllers/connectionController.h b/client/ui/controllers/connectionController.h index ed58c3d53..c3593c4d0 100644 --- a/client/ui/controllers/connectionController.h +++ b/client/ui/controllers/connectionController.h @@ -41,6 +41,7 @@ public slots: void onTranslationsUpdated(); void checkAndStartAwgStateTimer(); + void onUpdateServiceFromGatewayCompleted(bool success, int serverIndex); private slots: void onAwgStateTimeout(); @@ -57,6 +58,9 @@ signals: void preparingConfig(); void prepareConfig(); + void requestSetCurrentProtocol(const QString &protocolName); + void requestUpdateServiceFromGateway(int serverIndex, const QString &newCountryCode, const QString &newCountryName, bool reloadServiceConfig); + private: Vpn::ConnectionState getCurrentConnectionState(); @@ -76,6 +80,11 @@ private: QString m_connectionStateText = tr("Connect"); Vpn::ConnectionState m_state; + + // State for async API operations + int m_pendingApiServerIndex = -1; + bool m_apiSwitched = false; + bool m_waitingForApiUpdate = false; }; #endif // CONNECTIONCONTROLLER_H