From 80fa7888023bc2d04ed706904d90fcd9bcb40595 Mon Sep 17 00:00:00 2001 From: cd-amn Date: Tue, 2 Jun 2026 16:36:51 +0400 Subject: [PATCH] refactor: prepare XrayProtocol for Tunnel two-phase lifecycle --- client/core/protocols/xrayProtocol.cpp | 20 +++++++++++++++++++- client/core/protocols/xrayProtocol.h | 8 ++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/client/core/protocols/xrayProtocol.cpp b/client/core/protocols/xrayProtocol.cpp index 87c295708..35c4beb52 100644 --- a/client/core/protocols/xrayProtocol.cpp +++ b/client/core/protocols/xrayProtocol.cpp @@ -67,6 +67,8 @@ ErrorCode XrayProtocol::start() { qDebug() << "XrayProtocol::start()"; + m_phase = Phase::Active; + // Inject SOCKS5 auth into the inbound before starting xray. // Re-uses existing credentials if the config already has them (e.g. imported config). amnezia::serialization::inbounds::InboundCredentials creds; @@ -119,6 +121,11 @@ void XrayProtocol::stop() { qDebug() << "XrayProtocol::stop()"; + if (m_phase != Phase::Active) { + return; + } + m_phase = Phase::Stopping; + IpcClient::withInterface([this](QSharedPointer iface) { auto restoreResolvers = iface->restoreResolvers(); if (!restoreResolvers.waitForFinished() || !restoreResolvers.returnValue()) @@ -153,9 +160,16 @@ void XrayProtocol::stop() m_tun2socksProcess.reset(); } + m_phase = Phase::Inactive; setConnectionState(Vpn::ConnectionState::Disconnected); } +void XrayProtocol::setPrimary(const QJsonObject &config) +{ + Q_UNUSED(config) + emit primaryReady(); +} + ErrorCode XrayProtocol::startTun2Socks() { m_tun2socksProcess = IpcClient::CreatePrivilegedProcess(); @@ -208,13 +222,17 @@ ErrorCode XrayProtocol::startTun2Socks() } } - if (resourceBusy && m_tun2socksRetryCount < maxTun2SocksRetries) { + if (m_phase == Phase::Active && resourceBusy + && m_tun2socksRetryCount < maxTun2SocksRetries) { m_tun2socksRetryCount++; qWarning() << QString("Tun2socks: TUN resource busy, retrying (%1/%2) in %3ms...") .arg(m_tun2socksRetryCount) .arg(maxTun2SocksRetries) .arg(tun2socksRetryDelayMs); QTimer::singleShot(tun2socksRetryDelayMs, this, [this]() { + if (m_phase != Phase::Active) { + return; + } if (ErrorCode err = startTun2Socks(); err != ErrorCode::NoError) { stop(); setLastError(err); diff --git a/client/core/protocols/xrayProtocol.h b/client/core/protocols/xrayProtocol.h index 9aab50a42..d80542aac 100644 --- a/client/core/protocols/xrayProtocol.h +++ b/client/core/protocols/xrayProtocol.h @@ -20,8 +20,15 @@ public: ErrorCode start() override; void stop() override; + void setPrimary(const QJsonObject &config) override; private: + enum class Phase { + Inactive, + Active, + Stopping, + }; + ErrorCode setupRouting(); ErrorCode startTun2Socks(); @@ -40,6 +47,7 @@ private: static constexpr int tun2socksRetryDelayMs = 400; QString m_tunName; + Phase m_phase = Phase::Inactive; }; #endif // XRAYPROTOCOL_H