fix(vpn): arm bypass proactively on detected tunnel, drop post-failure fallback
This commit is contained in:
+4
-28
@@ -90,9 +90,6 @@ class Api {
|
|||||||
|
|
||||||
int get sessionEpoch => _sessionEpoch;
|
int get sessionEpoch => _sessionEpoch;
|
||||||
|
|
||||||
/// Залипает на время сессии: VPN-путь не сработал — идём мимо туннеля.
|
|
||||||
bool _bypassActive = false;
|
|
||||||
|
|
||||||
int _nextSeq() => _seq = (_seq + 1) & 0xFFFF;
|
int _nextSeq() => _seq = (_seq + 1) & 0xFFFF;
|
||||||
|
|
||||||
// Публичное API
|
// Публичное API
|
||||||
@@ -110,20 +107,17 @@ class Api {
|
|||||||
_armConnectWatchdog(gen);
|
_armConnectWatchdog(gen);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
bool bypassArmed;
|
bool useBypass;
|
||||||
try {
|
try {
|
||||||
bypassArmed = await VpnBypassService.instance.shouldArm().timeout(
|
useBypass = await VpnBypassService.instance.shouldArm().timeout(
|
||||||
_shouldArmTimeout,
|
_shouldArmTimeout,
|
||||||
);
|
);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger.w('connect: shouldArm завис/упал ($e) — без обхода VPN');
|
logger.w('connect: shouldArm завис/упал ($e) — без обхода VPN');
|
||||||
bypassArmed = false;
|
useBypass = false;
|
||||||
}
|
}
|
||||||
if (gen != _connectGen) return;
|
if (gen != _connectGen) return;
|
||||||
|
|
||||||
if (!bypassArmed) _bypassActive = false;
|
|
||||||
final useBypass = _bypassActive && bypassArmed;
|
|
||||||
|
|
||||||
({String host, int port}) endpoint;
|
({String host, int port}) endpoint;
|
||||||
try {
|
try {
|
||||||
endpoint = await ServerConfig.loadEndpoint().timeout(_endpointTimeout);
|
endpoint = await ServerConfig.loadEndpoint().timeout(_endpointTimeout);
|
||||||
@@ -168,13 +162,7 @@ class Api {
|
|||||||
info = await session.connect();
|
info = await session.connect();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (gen != _connectGen) return;
|
if (gen != _connectGen) return;
|
||||||
await _handleConnectFailure(
|
await _handleConnectFailure(e, phase: 'Ошибка хэндшейка');
|
||||||
e,
|
|
||||||
phase: 'Ошибка хэндшейка',
|
|
||||||
bypassArmed: bypassArmed,
|
|
||||||
useBypass: useBypass,
|
|
||||||
bypassWhy: 'хэндшейк не прошёл',
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
if (useBypass) {
|
if (useBypass) {
|
||||||
@@ -242,31 +230,19 @@ class Api {
|
|||||||
Future<void> _handleConnectFailure(
|
Future<void> _handleConnectFailure(
|
||||||
Object error, {
|
Object error, {
|
||||||
required String phase,
|
required String phase,
|
||||||
required bool bypassArmed,
|
|
||||||
required bool useBypass,
|
|
||||||
required String bypassWhy,
|
|
||||||
}) async {
|
}) async {
|
||||||
logger.e('$phase: $error');
|
logger.e('$phase: $error');
|
||||||
_cancelConnectWatchdog();
|
_cancelConnectWatchdog();
|
||||||
if (_sessionState != SessionState.disconnected) {
|
if (_sessionState != SessionState.disconnected) {
|
||||||
_cleanup();
|
_cleanup();
|
||||||
_setSessionState(SessionState.disconnected);
|
_setSessionState(SessionState.disconnected);
|
||||||
_armBypassIfPossible(bypassArmed, useBypass, bypassWhy);
|
|
||||||
_scheduleReconnect();
|
_scheduleReconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _armBypassIfPossible(bool armed, bool alreadyBypassing, String why) {
|
|
||||||
if (armed && !alreadyBypassing && !_bypassActive) {
|
|
||||||
_bypassActive = true;
|
|
||||||
logger.w('VPN bypass: $why — следующая попытка мимо VPN');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Отключается без автореконнекта.
|
/// Отключается без автореконнекта.
|
||||||
Future<void> disconnect() async {
|
Future<void> disconnect() async {
|
||||||
_autoReconnect = false;
|
_autoReconnect = false;
|
||||||
_bypassActive = false;
|
|
||||||
_connectGen++;
|
_connectGen++;
|
||||||
_reconnectTimer?.cancel();
|
_reconnectTimer?.cancel();
|
||||||
_cleanup();
|
_cleanup();
|
||||||
|
|||||||
+3
-3
@@ -428,9 +428,9 @@ class KometAppState extends State<KometApp>
|
|||||||
|
|
||||||
_vpnBypassSub = VpnBypassService.instance.events.listen((r) {
|
_vpnBypassSub = VpnBypassService.instance.events.listen((r) {
|
||||||
final msg = r.bound
|
final msg = r.bound
|
||||||
? 'Соединение через VPN не работает — '
|
? 'Обход VPN включён — прямое подключение через '
|
||||||
'используется ${r.boundInterface ?? r.transport ?? 'прямое подключение'}'
|
'${r.boundInterface ?? r.transport ?? 'сеть без VPN'}'
|
||||||
: 'Соединение через VPN не работает, обойти не удалось'
|
: 'Обход VPN не удался, подключение через туннель'
|
||||||
'${r.reason != null ? ' (${r.reason})' : ''}';
|
'${r.reason != null ? ' (${r.reason})' : ''}';
|
||||||
|
|
||||||
final now = DateTime.now();
|
final now = DateTime.now();
|
||||||
|
|||||||
Reference in New Issue
Block a user