]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
VPN: When activating while another tunnel is active, deactivate the other tunnel
authorRoopesh Chander <roop@roopc.net>
Sat, 10 Nov 2018 10:20:56 +0000 (15:50 +0530)
committerRoopesh Chander <roop@roopc.net>
Sat, 10 Nov 2018 11:14:28 +0000 (16:44 +0530)
Signed-off-by: Roopesh Chander <roop@roopc.net>
WireGuard/WireGuard/UI/iOS/ErrorPresenter.swift
WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift
WireGuard/WireGuard/VPN/TunnelsManager.swift

index d06f632c6a9ec4875c96c0cf5294cff5da747f68..fd56588eabb276051c842b5ea8e90442659e6fd6 100644 (file)
@@ -23,21 +23,6 @@ class ErrorPresenter {
         // TunnelActivationError
         case TunnelActivationError.tunnelActivationFailed:
             return ("Activation failure", "The tunnel could not be activated due to an internal error")
-        case TunnelActivationError.attemptingActivationWhenAnotherTunnelIsBusy(let otherTunnelStatus):
-            let statusString: String = {
-                switch (otherTunnelStatus) {
-                case .active: fallthrough
-                case .reasserting: fallthrough
-                case .restarting:
-                    return "active"
-                case .activating: fallthrough
-                case .deactivating:
-                    return "being deactivated"
-                case .inactive:
-                    fatalError()
-                }
-            }()
-            return ("Activation failure", "Another tunnel is currently \(statusString)")
 
         default:
             os_log("ErrorPresenter: Error not presented: %{public}@", log: OSLog.default, type: .error, "\(error)")
index 5209b3ac383a1e2767f2a984af1ef740959bc380..92d5c6440851fb579b305a10d796a91c1b4084fa 100644 (file)
@@ -259,6 +259,8 @@ class TunnelDetailTableViewStatusCell: UITableViewCell {
             text = "Reactivating"
         case .restarting:
             text = "Restarting"
+        case .waiting:
+            text = "Waiting"
         }
         textLabel?.text = text
         DispatchQueue.main.async { [weak statusSwitch] in
index d07f439a711ca824fdbe2a172415c352414410d9..8827ea382aaf13b6f5944f132cb7bf30bf0ebfab 100644 (file)
@@ -14,7 +14,6 @@ protocol TunnelsManagerDelegate: class {
 
 enum TunnelActivationError: Error {
     case tunnelActivationFailed
-    case attemptingActivationWhenAnotherTunnelIsBusy(otherTunnelStatus: TunnelStatus)
     case attemptingActivationWhenTunnelIsNotInactive
     case attemptingDeactivationWhenTunnelIsInactive
 }
@@ -191,13 +190,15 @@ class TunnelsManager {
             completionHandler(TunnelActivationError.attemptingActivationWhenTunnelIsNotInactive)
             return
         }
-        for t in tunnels {
-            if t.status != .inactive {
-                completionHandler(TunnelActivationError.attemptingActivationWhenAnotherTunnelIsBusy(otherTunnelStatus: t.status))
-                return
+        if let tunnelInOperation = tunnels.first(where: { $0.status != .inactive }) {
+            tunnel.status = .waiting
+            tunnelInOperation.onDeactivationComplete = {
+                tunnel.startActivation(completionHandler: completionHandler)
             }
+            startDeactivation(of: tunnelInOperation)
+        } else {
+            tunnel.startActivation(completionHandler: completionHandler)
         }
-        tunnel.startActivation(completionHandler: completionHandler)
     }
 
     func startDeactivation(of tunnel: TunnelContainer) {
@@ -218,6 +219,8 @@ class TunnelContainer: NSObject {
     @objc dynamic var name: String
     @objc dynamic var status: TunnelStatus
 
+    var onDeactivationComplete: (() -> Void)?
+
     fileprivate let tunnelProvider: NETunnelProviderManager
     private var statusObservationToken: AnyObject?
 
@@ -245,10 +248,11 @@ class TunnelContainer: NSObject {
     }
 
     fileprivate func startActivation(completionHandler: @escaping (Error?) -> Void) {
-        assert(status == .inactive || status == .restarting)
+        assert(status == .inactive || status == .restarting || status == .waiting)
 
         guard let tunnelConfiguration = tunnelConfiguration() else { fatalError() }
 
+        onDeactivationComplete = nil
         startActivation(tunnelConfiguration: tunnelConfiguration,
                         completionHandler: completionHandler)
     }
@@ -356,6 +360,8 @@ class TunnelContainer: NSObject {
                 s.status = TunnelStatus(from: connection.status)
                 if (s.status == .inactive) {
                     s.statusObservationToken = nil
+                    s.onDeactivationComplete?()
+                    s.onDeactivationComplete = nil
                 }
         }
     }
@@ -369,6 +375,7 @@ class TunnelContainer: NSObject {
     case reasserting // Not a possible state at present
 
     case restarting // Restarting tunnel (done after saving modifications to an active tunnel)
+    case waiting    // Waiting for another tunnel to be brought down
 
     init(from vpnStatus: NEVPNStatus) {
         switch (vpnStatus) {