mirror of
https://github.com/amnezia-vpn/amnezia-client.git
synced 2026-05-08 14:33:23 +00:00
fix: apple platform network switch fix (#2359)
* Apple platform network switch fix * macos_ne exclusion fixed
This commit is contained in:
@@ -126,8 +126,13 @@ extension PacketTunnelProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
vpnReachability.startTracking { [weak self] status in
|
vpnReachability.startTracking { [weak self] status in
|
||||||
guard status == .reachableViaWiFi else { return }
|
switch status {
|
||||||
self?.ovpnAdapter?.reconnect(afterTimeInterval: 5)
|
case .reachableViaWiFi, .reachableViaWWAN:
|
||||||
|
ovpnLog(.info, message: "Reachability changed, reconnecting OpenVPN session")
|
||||||
|
self?.ovpnAdapter?.reconnect(afterTimeInterval: 1)
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
startHandler = completionHandler
|
startHandler = completionHandler
|
||||||
|
|||||||
@@ -41,10 +41,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
var ovpnAdapter: OpenVPNAdapter?
|
var ovpnAdapter: OpenVPNAdapter?
|
||||||
private lazy var openVPNPacketFlowAdapter = PacketTunnelFlowAdapter(flow: packetFlow)
|
private lazy var openVPNPacketFlowAdapter = PacketTunnelFlowAdapter(flow: packetFlow)
|
||||||
private let pathMonitorQueue = DispatchQueue(label: Constants.processQueueName + ".path-monitor")
|
private let pathMonitorQueue = DispatchQueue(label: Constants.processQueueName + ".path-monitor")
|
||||||
|
private let networkChangeQueue = DispatchQueue(label: Constants.processQueueName + ".network-change")
|
||||||
private let pathMonitor = NWPathMonitor()
|
private let pathMonitor = NWPathMonitor()
|
||||||
private var didReceiveInitialPathUpdate = false
|
private var didReceiveInitialPathUpdate = false
|
||||||
private var currentPath: Network.NWPath?
|
private var currentPath: Network.NWPath?
|
||||||
private var currentPathSignature: String?
|
private var currentPathSignature: String?
|
||||||
|
private var pendingNetworkChangeWorkItem: DispatchWorkItem?
|
||||||
|
private var isApplyingNetworkChange = false
|
||||||
|
|
||||||
var splitTunnelType: Int?
|
var splitTunnelType: Int?
|
||||||
var splitTunnelSites: [String]?
|
var splitTunnelSites: [String]?
|
||||||
@@ -78,14 +81,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
|
|
||||||
guard hasMeaningfulChange, let proto = self.protoType else { return }
|
guard hasMeaningfulChange, let proto = self.protoType else { return }
|
||||||
|
|
||||||
// WireGuard/AWG manages network changes internally; avoid restarting the tunnel here.
|
// OpenVPN and WireGuard/AWG handle network changes internally.
|
||||||
if proto == .wireguard {
|
// Restarting them here can race their own reconnect logic and break tunnel setup.
|
||||||
|
if proto == .wireguard || proto == .openvpn {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
DispatchQueue.main.async {
|
self.scheduleNetworkChangeHandling(for: proto, path: path)
|
||||||
self.handle(networkChange: path) { _ in }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pathMonitor.start(queue: pathMonitorQueue)
|
pathMonitor.start(queue: pathMonitorQueue)
|
||||||
|
|
||||||
@@ -259,9 +261,47 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func handle(networkChange changePath: Network.NWPath, completion: @escaping (Error?) -> Void) {
|
private func handle(networkChange changePath: Network.NWPath, completion: @escaping (Error?) -> Void) {
|
||||||
|
guard protoType == .xray else {
|
||||||
|
updateActiveInterfaceIndex(for: changePath)
|
||||||
|
completion(nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
updateActiveInterfaceIndex(for: changePath)
|
updateActiveInterfaceIndex(for: changePath)
|
||||||
wg_log(.info, message: "Tunnel restarted.")
|
reasserting = true
|
||||||
startTunnel(options: nil, completionHandler: completion)
|
xrayLog(.info, message: "Applying network change to xray tunnel")
|
||||||
|
stopXray { }
|
||||||
|
startXray { [weak self] error in
|
||||||
|
self?.reasserting = false
|
||||||
|
completion(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func scheduleNetworkChangeHandling(for proto: TunnelProtoType, path: Network.NWPath) {
|
||||||
|
guard proto == .xray else { return }
|
||||||
|
|
||||||
|
pendingNetworkChangeWorkItem?.cancel()
|
||||||
|
|
||||||
|
let workItem = DispatchWorkItem { [weak self] in
|
||||||
|
guard let self else { return }
|
||||||
|
|
||||||
|
if self.isApplyingNetworkChange {
|
||||||
|
xrayLog(.debug, message: "Skipping network change while restart is already in progress")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.isApplyingNetworkChange = true
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.handle(networkChange: path) { [weak self] _ in
|
||||||
|
self?.networkChangeQueue.async {
|
||||||
|
self?.isApplyingNetworkChange = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pendingNetworkChangeWorkItem = workItem
|
||||||
|
networkChangeQueue.asyncAfter(deadline: .now() + 1.0, execute: workItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user