]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
Error handling: Add info on the underlying system error to error alerts
authorRoopesh Chander <roop@roopc.net>
Mon, 17 Dec 2018 13:26:26 +0000 (18:56 +0530)
committerRoopesh Chander <roop@roopc.net>
Mon, 17 Dec 2018 13:34:17 +0000 (19:04 +0530)
Signed-off-by: Roopesh Chander <roop@roopc.net>
WireGuard/WireGuard.xcodeproj/project.pbxproj
WireGuard/WireGuard/Tunnel/TunnelErrors.swift [new file with mode: 0644]
WireGuard/WireGuard/Tunnel/TunnelsManager.swift

index 7bb7d0a61b10323b5557eeab3284e587b941bb86..be93450bd722d33c1dfecd8dc7e66a7e6424a62f 100644 (file)
@@ -37,6 +37,7 @@
                6F7774EA217229DB006A79B3 /* IPAddressRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774E9217229DB006A79B3 /* IPAddressRange.swift */; };
                6F7774EF21722D97006A79B3 /* TunnelsManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774EE21722D97006A79B3 /* TunnelsManager.swift */; };
                6F7774F321774263006A79B3 /* TunnelEditTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7774F221774263006A79B3 /* TunnelEditTableViewController.swift */; };
+               6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F7F7E5E21C7D74B00527607 /* TunnelErrors.swift */; };
                6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */; };
                6F919ED9218C65C50023B400 /* wireguard_doc_logo_22x29.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */; };
                6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */ = {isa = PBXBuildFile; fileRef = 6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */; };
                6F7774E9217229DB006A79B3 /* IPAddressRange.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPAddressRange.swift; sourceTree = "<group>"; };
                6F7774EE21722D97006A79B3 /* TunnelsManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelsManager.swift; sourceTree = "<group>"; };
                6F7774F221774263006A79B3 /* TunnelEditTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelEditTableViewController.swift; sourceTree = "<group>"; };
+               6F7F7E5E21C7D74B00527607 /* TunnelErrors.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelErrors.swift; sourceTree = "<group>"; };
                6F919EC2218A2AE90023B400 /* ErrorPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorPresenter.swift; sourceTree = "<group>"; };
                6F919ED5218C65C50023B400 /* wireguard_doc_logo_22x29.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_22x29.png; sourceTree = "<group>"; };
                6F919ED6218C65C50023B400 /* wireguard_doc_logo_44x58.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = wireguard_doc_logo_44x58.png; sourceTree = "<group>"; };
                                5F4541A821C451D100994C13 /* TunnelStatus.swift */,
                                6FB1017821C57DE600766195 /* MockTunnels.swift */,
                                5F4541AD21C7704300994C13 /* NEVPNStatus+CustomStringConvertible.swift */,
+                               6F7F7E5E21C7D74B00527607 /* TunnelErrors.swift */,
                        );
                        path = Tunnel;
                        sourceTree = "<group>";
                                6F6899A62180447E0012E523 /* x25519.c in Sources */,
                                6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */,
                                6FDEF80021863C0100D8FBF6 /* ioapi.c in Sources */,
+                               6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */,
                                6FDEF7FC21863B6100D8FBF6 /* zip.c in Sources */,
                                6F628C3F217F3413003482A3 /* DNSServer.swift in Sources */,
                                6F628C3D217F09E9003482A3 /* TunnelViewModel.swift in Sources */,
diff --git a/WireGuard/WireGuard/Tunnel/TunnelErrors.swift b/WireGuard/WireGuard/Tunnel/TunnelErrors.swift
new file mode 100644 (file)
index 0000000..889f0a7
--- /dev/null
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: MIT
+// Copyright © 2018 WireGuard LLC. All Rights Reserved.
+
+import NetworkExtension
+
+enum TunnelsManagerError: WireGuardAppError {
+    case tunnelNameEmpty
+    case tunnelAlreadyExistsWithThatName
+    case systemErrorOnListingTunnels(systemError: Error)
+    case systemErrorOnAddTunnel(systemError: Error)
+    case systemErrorOnModifyTunnel(systemError: Error)
+    case systemErrorOnRemoveTunnel(systemError: Error)
+
+    var alertText: AlertText {
+        switch self {
+        case .tunnelNameEmpty:
+            return ("No name provided", "Cannot create tunnel with an empty name")
+        case .tunnelAlreadyExistsWithThatName:
+            return ("Name already exists", "A tunnel with that name already exists")
+        case .systemErrorOnListingTunnels(let systemError):
+            return ("Unable to list tunnels", systemError.UIString)
+        case .systemErrorOnAddTunnel(let systemError):
+            return ("Unable to create tunnel", systemError.UIString)
+        case .systemErrorOnModifyTunnel(let systemError):
+            return ("Unable to modify tunnel", systemError.UIString)
+        case .systemErrorOnRemoveTunnel(let systemError):
+            return ("Unable to remove tunnel", systemError.UIString)
+        }
+    }
+}
+
+enum TunnelsManagerActivationAttemptError: WireGuardAppError {
+    case tunnelIsNotInactive
+    case anotherTunnelIsOperational(otherTunnelName: String)
+    case failedWhileStarting(systemError: Error) // startTunnel() throwed
+    case failedWhileSaving(systemError: Error) // save config after re-enabling throwed
+    case failedWhileLoading(systemError: Error) // reloading config throwed
+    case failedBecauseOfTooManyErrors(lastSystemError: Error) // recursion limit reached
+
+    var alertText: AlertText {
+        switch self {
+        case .tunnelIsNotInactive:
+            return ("Activation failure", "The tunnel is already active or in the process of being activated")
+        case .anotherTunnelIsOperational(let otherTunnelName):
+            return ("Activation failure", "Please disconnect '\(otherTunnelName)' before enabling this tunnel.")
+        case .failedWhileStarting(let systemError),
+             .failedWhileSaving(let systemError),
+             .failedWhileLoading(let systemError),
+             .failedBecauseOfTooManyErrors(let systemError):
+            return ("Activation failure", "The tunnel could not be activated. " + systemError.UIString)
+        }
+    }
+}
+
+enum TunnelsManagerActivationError: WireGuardAppError {
+    case activationFailed
+    case activationFailedWithExtensionError(title: String, message: String)
+    var alertText: AlertText {
+        switch self {
+        case .activationFailed:
+            return ("Activation failure", "The tunnel could not be activated. Please ensure that you are connected to the Internet.")
+        case .activationFailedWithExtensionError(let title, let message):
+            return (title, message)
+        }
+    }
+}
+
+extension Error {
+    var UIString: String {
+        if let systemError = self as? NEVPNError {
+            switch systemError {
+            case NEVPNError.configurationInvalid:
+                return "The configuration is invalid"
+            case NEVPNError.configurationDisabled:
+                return "The configuration is disabled"
+            case NEVPNError.connectionFailed:
+                return "The connection failed"
+            case NEVPNError.configurationStale:
+                return "The configuration is stale"
+            case NEVPNError.configurationReadWriteFailed:
+                return "Reading or writing the configuration failed"
+            case NEVPNError.configurationUnknown:
+                return "Unknown system error"
+            default:
+                return ""
+            }
+        } else {
+            return localizedDescription
+        }
+    }
+}
index 2785be4ca4124bee8fadc5b8271ac7ac990858ef..10df606fcac0b6dd69c7c57d0365c355a5cb33be 100644 (file)
@@ -19,65 +19,6 @@ protocol TunnelsManagerActivationDelegate: class {
     func tunnelActivationSucceeded(tunnel: TunnelContainer) // status changed to connected
 }
 
-enum TunnelsManagerActivationAttemptError: WireGuardAppError {
-    case tunnelIsNotInactive
-    case anotherTunnelIsOperational(otherTunnelName: String)
-    case failedWhileStarting // startTunnel() throwed
-    case failedWhileSaving // save config after re-enabling throwed
-    case failedWhileLoading // reloading config throwed
-    case failedBecauseOfTooManyErrors // recursion limit reached
-
-    var alertText: AlertText {
-        switch self {
-        case .tunnelIsNotInactive:
-            return ("Activation failure", "The tunnel is already active or in the process of being activated")
-        case .anotherTunnelIsOperational(let otherTunnelName):
-            return ("Activation failure", "Please disconnect '\(otherTunnelName)' before enabling this tunnel.")
-        case .failedWhileStarting, .failedWhileSaving, .failedWhileLoading, .failedBecauseOfTooManyErrors:
-            return ("Activation failure", "The tunnel could not be activated.")
-        }
-    }
-}
-
-enum TunnelsManagerActivationError: WireGuardAppError {
-    case activationFailed
-    case activationFailedWithExtensionError(title: String, message: String)
-    var alertText: AlertText {
-        switch self {
-        case .activationFailed:
-            return ("Activation failure", "The tunnel could not be activated. Please ensure that you are connected to the Internet.")
-        case .activationFailedWithExtensionError(let title, let message):
-            return (title, message)
-        }
-    }
-}
-
-enum TunnelsManagerError: WireGuardAppError {
-    case tunnelNameEmpty
-    case tunnelAlreadyExistsWithThatName
-    case systemErrorOnListingTunnels
-    case systemErrorOnAddTunnel
-    case systemErrorOnModifyTunnel
-    case systemErrorOnRemoveTunnel
-
-    var alertText: AlertText {
-        switch self {
-        case .tunnelNameEmpty:
-            return ("No name provided", "Cannot create tunnel with an empty name")
-        case .tunnelAlreadyExistsWithThatName:
-            return ("Name already exists", "A tunnel with that name already exists")
-        case .systemErrorOnListingTunnels:
-            return ("Unable to list tunnels", "")
-        case .systemErrorOnAddTunnel:
-            return ("Unable to create tunnel", "")
-        case .systemErrorOnModifyTunnel:
-            return ("Unable to modify tunnel", "")
-        case .systemErrorOnRemoveTunnel:
-            return ("Unable to remove tunnel", "")
-        }
-    }
-}
-
 class TunnelsManager {
     private var tunnels: [TunnelContainer]
     weak var tunnelsListDelegate: TunnelsManagerListDelegate?
@@ -96,7 +37,7 @@ class TunnelsManager {
         NETunnelProviderManager.loadAllFromPreferences { managers, error in
             if let error = error {
                 wg_log(.error, message: "Failed to load tunnel provider managers: \(error)")
-                completionHandler(.failure(TunnelsManagerError.systemErrorOnListingTunnels))
+                completionHandler(.failure(TunnelsManagerError.systemErrorOnListingTunnels(systemError: error)))
                 return
             }
             completionHandler(.success(TunnelsManager(tunnelProviders: managers ?? [])))
@@ -126,7 +67,7 @@ class TunnelsManager {
         tunnelProviderManager.saveToPreferences { [weak self] error in
             guard error == nil else {
                 wg_log(.error, message: "Add: Saving configuration failed: \(error!)")
-                completionHandler(.failure(TunnelsManagerError.systemErrorOnAddTunnel))
+                completionHandler(.failure(TunnelsManagerError.systemErrorOnAddTunnel(systemError: error!)))
                 return
             }
             
@@ -183,7 +124,7 @@ class TunnelsManager {
         tunnelProviderManager.saveToPreferences { [weak self] error in
             guard error == nil else {
                 wg_log(.error, message: "Modify: Saving configuration failed: \(error!)")
-                completionHandler(TunnelsManagerError.systemErrorOnModifyTunnel)
+                completionHandler(TunnelsManagerError.systemErrorOnModifyTunnel(systemError: error!))
                 return
             }
             guard let self = self else { return }
@@ -209,7 +150,7 @@ class TunnelsManager {
                     tunnel.isActivateOnDemandEnabled = tunnelProviderManager.isOnDemandEnabled
                     guard error == nil else {
                         wg_log(.error, message: "Modify: Re-loading after saving configuration failed: \(error!)")
-                        completionHandler(TunnelsManagerError.systemErrorOnModifyTunnel)
+                        completionHandler(TunnelsManagerError.systemErrorOnModifyTunnel(systemError: error!))
                         return
                     }
                     completionHandler(nil)
@@ -226,7 +167,7 @@ class TunnelsManager {
         tunnelProviderManager.removeFromPreferences { [weak self] error in
             guard error == nil else {
                 wg_log(.error, message: "Remove: Saving configuration failed: \(error!)")
-                completionHandler(TunnelsManagerError.systemErrorOnRemoveTunnel)
+                completionHandler(TunnelsManagerError.systemErrorOnRemoveTunnel(systemError: error!))
                 return
             }
             if let self = self {
@@ -415,7 +356,7 @@ class TunnelContainer: NSObject {
     fileprivate func startActivation(recursionCount: UInt = 0, lastError: Error? = nil, activationDelegate: TunnelsManagerActivationDelegate?) {
         if recursionCount >= 8 {
             wg_log(.error, message: "startActivation: Failed after 8 attempts. Giving up with \(lastError!)")
-            activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedBecauseOfTooManyErrors)
+            activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedBecauseOfTooManyErrors(lastSystemError: lastError!))
             return
         }
 
@@ -432,7 +373,7 @@ class TunnelContainer: NSObject {
                 guard let self = self else { return }
                 if error != nil {
                     wg_log(.error, message: "Error saving tunnel after re-enabling: \(error!)")
-                    activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedWhileSaving)
+                    activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedWhileSaving(systemError: error!))
                     return
                 }
                 wg_log(.debug, staticMessage: "startActivation: Tunnel saved after re-enabling")
@@ -456,13 +397,13 @@ class TunnelContainer: NSObject {
             guard let systemError = error as? NEVPNError else {
                 wg_log(.error, message: "Failed to activate tunnel: Error: \(error)")
                 status = .inactive
-                activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedWhileStarting)
+                activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedWhileStarting(systemError: error))
                 return
             }
             guard systemError.code == NEVPNError.configurationInvalid || systemError.code == NEVPNError.configurationStale else {
                 wg_log(.error, message: "Failed to activate tunnel: VPN Error: \(error)")
                 status = .inactive
-                activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedWhileStarting)
+                activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedWhileStarting(systemError: systemError))
                 return
             }
             wg_log(.debug, staticMessage: "startActivation: Will reload tunnel and then try to start it.")
@@ -471,7 +412,7 @@ class TunnelContainer: NSObject {
                 if error != nil {
                     wg_log(.error, message: "startActivation: Error reloading tunnel: \(error!)")
                     self.status = .inactive
-                    activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedWhileLoading)
+                    activationDelegate?.tunnelActivationAttemptFailed(tunnel: self, error: .failedWhileLoading(systemError: systemError))
                     return
                 }
                 wg_log(.debug, staticMessage: "startActivation: Tunnel reloaded")