From 585f8e4e0fa0280db06e2bfbfe955458633423c4 Mon Sep 17 00:00:00 2001 From: Safibulae Date: Mon, 23 Mar 2026 15:18:04 -0300 Subject: [PATCH] macOS: skip VPN reconnect on same-SSID WiFi AP roams When macOS roams between access points on the same SSID (e.g. enterprise WiFi), NetworkInterface fields like metric or physicalAddress can change while interfaceName and networkOrSsid remain identical. The existing operator!= on NetworkInterface compares all 11 fields, so these cosmetic changes enter the "Unidentified interface change" branch in onNetworkStateChanged() and still emit networkChanged(), which triggers a full tunnel teardown and rebuild via ConnectionManager::updateConnectionSettings(). This causes 15-20 seconds of connectivity loss per roam event, which on multi-AP networks can happen repeatedly. This patch gates the networkChanged() emission on whether the change is significant (interface name or SSID actually changed). Minor changes such as same-SSID AP roams still update the cached state but no longer trigger a reconnect. The tunnel stays up through the roam, which WireGuard and AmneziaWG handle natively at the protocol level. Fixes #307 --- .../networkdetectionmanager_mac.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/client/engine/engine/networkdetectionmanager/networkdetectionmanager_mac.cpp b/src/client/engine/engine/networkdetectionmanager/networkdetectionmanager_mac.cpp index 962cb0c8b..770d244cc 100644 --- a/src/client/engine/engine/networkdetectionmanager/networkdetectionmanager_mac.cpp +++ b/src/client/engine/engine/networkdetectionmanager/networkdetectionmanager_mac.cpp @@ -42,8 +42,11 @@ void NetworkDetectionManager_mac::onNetworkStateChanged() if (networkInterface != lastNetworkInterface_) { + bool significantChange = false; + if (networkInterface.interfaceName != lastNetworkInterface_.interfaceName) { + significantChange = true; if (networkInterface.interfaceIndex == -1) { qCInfo(LOG_BASIC) << "Primary Adapter down: " << lastNetworkInterface_.interfaceName; @@ -62,6 +65,7 @@ void NetworkDetectionManager_mac::onNetworkStateChanged() } else if (networkInterface.networkOrSsid != lastNetworkInterface_.networkOrSsid) { + significantChange = true; qCInfo(LOG_BASIC) << "Primary Network Changed: " << networkInterface.interfaceName << " : " << networkInterface.networkOrSsid; @@ -75,12 +79,14 @@ void NetworkDetectionManager_mac::onNetworkStateChanged() } else { - qCInfo(LOG_BASIC) << "Unidentified interface change"; - // Can happen when changing interfaces + qCInfo(LOG_BASIC) << "Minor interface change on" << networkInterface.interfaceName + << "(e.g. same-SSID AP roam), skipping reconnect"; } lastNetworkInterface_ = networkInterface; - emit networkChanged(networkInterface); + if (significantChange) { + emit networkChanged(networkInterface); + } } else if (wifiAdapterUp != lastWifiAdapterUp_) {