mirror of
https://github.com/passepartoutvpn/wireguard-apple.git
synced 2025-03-06 05:32:07 +00:00
TunnelsManager: Handle waiting on a stale tunnel
If we have a stale tunnel on which we don't get status updates we rely
on a timer to update the status (see commit 34a7e5b
). Previously, if
the user tries to activate another tunnel, that resulted in both tunnels
waiting indefinitely. This commit fixes that.
This commit is contained in:
parent
efc593f7da
commit
fe69fe57e4
@ -24,6 +24,7 @@ class TunnelsManager {
|
|||||||
weak var tunnelsListDelegate: TunnelsManagerListDelegate?
|
weak var tunnelsListDelegate: TunnelsManagerListDelegate?
|
||||||
weak var activationDelegate: TunnelsManagerActivationDelegate?
|
weak var activationDelegate: TunnelsManagerActivationDelegate?
|
||||||
private var statusObservationToken: AnyObject?
|
private var statusObservationToken: AnyObject?
|
||||||
|
private var waiteeObservationToken: AnyObject?
|
||||||
|
|
||||||
init(tunnelProviders: [NETunnelProviderManager]) {
|
init(tunnelProviders: [NETunnelProviderManager]) {
|
||||||
tunnels = tunnelProviders.map { TunnelContainer(tunnel: $0) }.sorted { $0.name < $1.name }
|
tunnels = tunnelProviders.map { TunnelContainer(tunnel: $0) }.sorted { $0.name < $1.name }
|
||||||
@ -205,6 +206,7 @@ class TunnelsManager {
|
|||||||
if let tunnelInOperation = tunnels.first(where: { $0.status != .inactive }) {
|
if let tunnelInOperation = tunnels.first(where: { $0.status != .inactive }) {
|
||||||
wg_log(.info, message: "Tunnel '\(tunnel.name)' waiting for deactivation of '\(tunnelInOperation.name)'")
|
wg_log(.info, message: "Tunnel '\(tunnel.name)' waiting for deactivation of '\(tunnelInOperation.name)'")
|
||||||
tunnel.status = .waiting
|
tunnel.status = .waiting
|
||||||
|
activateWaitingTunnelOnDeactivation(of: tunnelInOperation)
|
||||||
if tunnelInOperation.status != .deactivating {
|
if tunnelInOperation.status != .deactivating {
|
||||||
startDeactivation(of: tunnelInOperation)
|
startDeactivation(of: tunnelInOperation)
|
||||||
}
|
}
|
||||||
@ -232,6 +234,18 @@ class TunnelsManager {
|
|||||||
tunnels.forEach { $0.refreshStatus() }
|
tunnels.forEach { $0.refreshStatus() }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func activateWaitingTunnelOnDeactivation(of tunnel: TunnelContainer) {
|
||||||
|
waiteeObservationToken = tunnel.observe(\.status) { [weak self] tunnel, _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
if tunnel.status == .inactive {
|
||||||
|
if let waitingTunnel = self.tunnels.first(where: { $0.status == .waiting }) {
|
||||||
|
waitingTunnel.startActivation(activationDelegate: self.activationDelegate)
|
||||||
|
}
|
||||||
|
self.waiteeObservationToken = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private func startObservingTunnelStatuses() {
|
private func startObservingTunnelStatuses() {
|
||||||
guard statusObservationToken == nil else { return }
|
guard statusObservationToken == nil else { return }
|
||||||
|
|
||||||
@ -268,13 +282,6 @@ class TunnelsManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
tunnel.refreshStatus()
|
tunnel.refreshStatus()
|
||||||
|
|
||||||
// In case some other tunnel is waiting for this tunnel to get deactivated
|
|
||||||
if session.status == .disconnected || session.status == .invalid {
|
|
||||||
if let waitingTunnel = self.tunnels.first(where: { $0.status == .waiting }) {
|
|
||||||
waitingTunnel.startActivation(activationDelegate: self.activationDelegate)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,18 +315,21 @@ class TunnelContainer: NSObject {
|
|||||||
var isAttemptingActivation = false {
|
var isAttemptingActivation = false {
|
||||||
didSet {
|
didSet {
|
||||||
if isAttemptingActivation {
|
if isAttemptingActivation {
|
||||||
|
self.activationTimer?.invalidate()
|
||||||
let activationTimer = Timer(timeInterval: 5 /* seconds */, repeats: true) { [weak self] _ in
|
let activationTimer = Timer(timeInterval: 5 /* seconds */, repeats: true) { [weak self] _ in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.refreshStatus()
|
wg_log(.debug, message: "Status update notification timeout for tunnel '\(self.name)'. Tunnel status is now '\(self.tunnelProvider.connection.status)'.")
|
||||||
if self.status == .inactive || self.status == .active {
|
switch self.tunnelProvider.connection.status {
|
||||||
self.isAttemptingActivation = false // This also invalidates the timer
|
case .connected, .disconnected, .invalid:
|
||||||
|
self.activationTimer?.invalidate()
|
||||||
|
self.activationTimer = nil
|
||||||
|
default:
|
||||||
|
break
|
||||||
}
|
}
|
||||||
|
self.refreshStatus()
|
||||||
}
|
}
|
||||||
self.activationTimer = activationTimer
|
self.activationTimer = activationTimer
|
||||||
RunLoop.main.add(activationTimer, forMode: .default)
|
RunLoop.main.add(activationTimer, forMode: .default)
|
||||||
} else {
|
|
||||||
activationTimer?.invalidate()
|
|
||||||
activationTimer = nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user