]> git.ipfire.org Git - thirdparty/wireguard-apple.git/commitdiff
More formatting nits and cyclomatic complexity fixes
authorEric Kuck <eric@bluelinelabs.com>
Thu, 13 Dec 2018 03:09:52 +0000 (21:09 -0600)
committerEric Kuck <eric@bluelinelabs.com>
Thu, 13 Dec 2018 03:09:52 +0000 (21:09 -0600)
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
17 files changed:
WireGuard/.swiftlint.yml
WireGuard/Shared/Model/Configuration.swift
WireGuard/Shared/Model/IPAddressRange.swift
WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift
WireGuard/WireGuard/UI/TunnelViewModel.swift
WireGuard/WireGuard/UI/iOS/ErrorPresenter.swift
WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift
WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift
WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift
WireGuard/WireGuard/VPN/TunnelsManager.swift
WireGuard/WireGuard/WireGuardAppError.swift
WireGuard/WireGuard/ZipArchive/ZipArchive.swift
WireGuard/WireGuard/ZipArchive/ZipExporter.swift
WireGuard/WireGuard/ZipArchive/ZipImporter.swift
WireGuard/WireGuardNetworkExtension/DNSResolver.swift
WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift
WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift

index df6266a36648083a10882b5daab954622791d7c4..2c414b60fa85461a4dbc084e655c8bc9339a95b6 100644 (file)
@@ -1,6 +1,7 @@
 disabled_rules:
  - line_length
  - trailing_whitespace
+ - todo
 opt_in_rules:
  - unneeded_parentheses_in_closure_argument
 # - trailing_closure
index 09fdd6b86823cc79c7e11af364b0329b23eb1cfc..77dfe9747d9c5f5a43f9773e370485b2b6ee2c0a 100644 (file)
@@ -26,10 +26,10 @@ final class TunnelConfiguration: Codable {
 struct InterfaceConfiguration: Codable {
     var name: String
     var privateKey: Data
-    var addresses: [IPAddressRange] = []
+    var addresses = [IPAddressRange]()
     var listenPort: UInt16?
     var mtu: UInt16?
-    var dns: [DNSServer] = []
+    var dns = [DNSServer]()
 
     init(name: String, privateKey: Data) {
         self.name = name
@@ -55,7 +55,7 @@ struct PeerConfiguration: Codable {
             }
         }
     }
-    var allowedIPs: [IPAddressRange] = []
+    var allowedIPs = [IPAddressRange]()
     var endpoint: Endpoint?
     var persistentKeepAlive: UInt16?
 
index e3c14414885abb35d9f660f65703ae594ae8a62a..468e3aa531c7a3ef9469e31941e7796816ee8a1a 100644 (file)
@@ -75,9 +75,7 @@ extension IPAddressRange: Codable {
             default: return nil
             }
         }()
-        guard let ipAddress = ipAddressFromData else {
-            throw DecodingError.invalidData
-        }
+        guard let ipAddress = ipAddressFromData else { throw DecodingError.invalidData }
         address = ipAddress
     }
     enum DecodingError: Error {
index 138ca620820eeeedf1017a46a035d5d5766ee431..14a6dfb571fd5be56ca818d1e163b5f9c6b78512 100644 (file)
@@ -54,13 +54,11 @@ class WgQuickConfigFileParser {
                 } else {
                     attributes[key] = value
                 }
-            } else {
-                if lowercasedLine != "[interface]" && lowercasedLine != "[peer]" {
-                    throw ParseError.invalidLine(line)
-                }
+            } else if lowercasedLine != "[interface]" && lowercasedLine != "[peer]" {
+                throw ParseError.invalidLine(line)
             }
 
-            let isLastLine = (lineIndex == lines.count - 1)
+            let isLastLine = lineIndex == lines.count - 1
 
             if isLastLine || lowercasedLine == "[interface]" || lowercasedLine == "[peer]" {
                 // Previous section has ended; process the attributes collected so far
@@ -109,7 +107,7 @@ class WgQuickConfigFileParser {
         }
         // wg-quick fields
         if let addressesString = attributes["address"] {
-            var addresses: [IPAddressRange] = []
+            var addresses = [IPAddressRange]()
             for addressString in addressesString.split(separator: ",") {
                 let trimmedString = addressString.trimmingCharacters(in: .whitespaces)
                 guard let address = IPAddressRange(from: trimmedString) else { return nil }
@@ -118,7 +116,7 @@ class WgQuickConfigFileParser {
             interface.addresses = addresses
         }
         if let dnsString = attributes["dns"] {
-            var dnsServers: [DNSServer] = []
+            var dnsServers = [DNSServer]()
             for dnsServerString in dnsString.split(separator: ",") {
                 let trimmedString = dnsServerString.trimmingCharacters(in: .whitespaces)
                 guard let dnsServer = DNSServer(from: trimmedString) else { return nil }
@@ -144,7 +142,7 @@ class WgQuickConfigFileParser {
             peer.preSharedKey = preSharedKey
         }
         if let allowedIPsString = attributes["allowedips"] {
-            var allowedIPs: [IPAddressRange] = []
+            var allowedIPs = [IPAddressRange]()
             for allowedIPString in allowedIPsString.split(separator: ",") {
                 let trimmedString = allowedIPString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
                 guard let allowedIP = IPAddressRange(from: trimmedString) else { return nil }
index af7ff4c1eca78c5a5743af342ff79e6af44e0bc9..80a6092b23d0d34d97fb115eb486de52508692f4 100644 (file)
@@ -37,8 +37,8 @@ class TunnelViewModel {
     static let keyLengthInBase64 = 44
 
     class InterfaceData {
-        var scratchpad: [InterfaceField: String] = [:]
-        var fieldsWithError: Set<InterfaceField> = []
+        var scratchpad = [InterfaceField: String]()
+        var fieldsWithError = Set<InterfaceField>()
         var validatedConfiguration: InterfaceConfiguration?
 
         subscript(field: InterfaceField) -> String {
@@ -114,9 +114,9 @@ class TunnelViewModel {
                 return .error("Interface's private key must be a 32-byte key in base64 encoding")
             }
             var config = InterfaceConfiguration(name: name, privateKey: privateKey)
-            var errorMessages: [String] = []
+            var errorMessages = [String]()
             if let addressesString = scratchpad[.addresses] {
-                var addresses: [IPAddressRange] = []
+                var addresses = [IPAddressRange]()
                 for addressString in addressesString.split(separator: ",") {
                     let trimmedString = addressString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
                     if let address = IPAddressRange(from: trimmedString) {
@@ -145,7 +145,7 @@ class TunnelViewModel {
                 }
             }
             if let dnsString = scratchpad[.dns] {
-                var dnsServers: [DNSServer] = []
+                var dnsServers = [DNSServer]()
                 for dnsServerString in dnsString.split(separator: ",") {
                     let trimmedString = dnsServerString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
                     if let dnsServer = DNSServer(from: trimmedString) {
@@ -177,14 +177,14 @@ class TunnelViewModel {
 
     class PeerData {
         var index: Int
-        var scratchpad: [PeerField: String] = [:]
-        var fieldsWithError: Set<PeerField> = []
+        var scratchpad = [PeerField: String]()
+        var fieldsWithError = Set<PeerField>()
         var validatedConfiguration: PeerConfiguration?
 
         // For exclude private IPs
-        var shouldAllowExcludePrivateIPsControl: Bool = false /* Read-only from the VC's point of view */
-        var excludePrivateIPsValue: Bool = false /* Read-only from the VC's point of view */
-        fileprivate var numberOfPeers: Int = 0
+        private(set) var shouldAllowExcludePrivateIPsControl = false
+        private(set) var excludePrivateIPsValue = false
+        fileprivate var numberOfPeers = 0
 
         init(index: Int) {
             self.index = index
@@ -251,7 +251,7 @@ class TunnelViewModel {
                 return .error("Peer's public key must be a 32-byte key in base64 encoding")
             }
             var config = PeerConfiguration(publicKey: publicKey)
-            var errorMessages: [String] = []
+            var errorMessages = [String]()
             if let preSharedKeyString = scratchpad[.preSharedKey] {
                 if let preSharedKey = Data(base64Encoded: preSharedKeyString), preSharedKey.count == TunnelConfiguration.keyLength {
                     config.preSharedKey = preSharedKey
@@ -261,7 +261,7 @@ class TunnelViewModel {
                 }
             }
             if let allowedIPsString = scratchpad[.allowedIPs] {
-                var allowedIPs: [IPAddressRange] = []
+                var allowedIPs = [IPAddressRange]()
                 for allowedIPString in allowedIPsString.split(separator: ",") {
                     let trimmedString = allowedIPString.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
                     if let allowedIP = IPAddressRange(from: trimmedString) {
@@ -352,11 +352,9 @@ class TunnelViewModel {
             let ipv6Addresses = allowedIPStrings.filter { $0.contains(":") }
             let modifiedAllowedIPStrings: [String]
             if isOn {
-                modifiedAllowedIPStrings = ipv6Addresses +
-                    TunnelViewModel.PeerData.ipv4DefaultRouteModRFC1918String + dnsServerStrings
+                modifiedAllowedIPStrings = ipv6Addresses + TunnelViewModel.PeerData.ipv4DefaultRouteModRFC1918String + dnsServerStrings
             } else {
-                modifiedAllowedIPStrings = ipv6Addresses +
-                    [TunnelViewModel.PeerData.ipv4DefaultRouteString]
+                modifiedAllowedIPStrings = ipv6Addresses + [TunnelViewModel.PeerData.ipv4DefaultRouteString]
             }
             scratchpad[.allowedIPs] = modifiedAllowedIPStrings.joined(separator: ", ")
             validatedConfiguration = nil // The configuration has been modified, and needs to be saved
@@ -374,7 +372,7 @@ class TunnelViewModel {
 
     init(tunnelConfiguration: TunnelConfiguration?) {
         let interfaceData: InterfaceData = InterfaceData()
-        var peersData: [PeerData] = []
+        var peersData = [PeerData]()
         if let tunnelConfiguration = tunnelConfiguration {
             interfaceData.validatedConfiguration = tunnelConfiguration.interface
             for (index, peerConfiguration) in tunnelConfiguration.peers.enumerated() {
@@ -423,7 +421,7 @@ class TunnelViewModel {
         case .error(let errorMessage):
             return .error(errorMessage)
         case .saved(let interfaceConfiguration):
-            var peerConfigurations: [PeerConfiguration] = []
+            var peerConfigurations = [PeerConfiguration]()
             peerConfigurations.reserveCapacity(peerSaveResults.count)
             for peerSaveResult in peerSaveResults {
                 switch peerSaveResult {
index 7c28495b15635a73009e2659c40344a2e509192b..2889694cfa239f61853bcf5c9762160ae02aeebb 100644 (file)
@@ -5,10 +5,10 @@ import UIKit
 import os.log
 
 class ErrorPresenter {
-    static func showErrorAlert(error: WireGuardAppError, from sourceVC: UIViewController?,
-                               onPresented: (() -> Void)? = nil, onDismissal: (() -> Void)? = nil) {
+    static func showErrorAlert(error: WireGuardAppError, from sourceVC: UIViewController?, onPresented: (() -> Void)? = nil, onDismissal: (() -> Void)? = nil) {
         guard let sourceVC = sourceVC else { return }
-        guard let (title, message) = error.alertText() else { return }
+        
+        let (title, message) = error.alertText()
         let okAction = UIAlertAction(title: "OK", style: .default) { _ in
             onDismissal?()
         }
@@ -18,9 +18,9 @@ class ErrorPresenter {
         sourceVC.present(alert, animated: true, completion: onPresented)
     }
 
-    static func showErrorAlert(title: String, message: String, from sourceVC: UIViewController?,
-                               onPresented: (() -> Void)? = nil, onDismissal: (() -> Void)? = nil) {
+    static func showErrorAlert(title: String, message: String, from sourceVC: UIViewController?, onPresented: (() -> Void)? = nil, onDismissal: (() -> Void)? = nil) {
         guard let sourceVC = sourceVC else { return }
+        
         let okAction = UIAlertAction(title: "OK", style: .default) { _ in
             onDismissal?()
         }
index e6ad02402733e4214541ebb47b8e676c00818475..c5816e82c567971d1fb66ec2cef9e120e6106b14 100644 (file)
@@ -322,9 +322,9 @@ private class KeyValueCell: CopyableLabelTableViewCell {
     let keyLabel: UILabel
     let valueLabel: ScrollableLabel
 
-    var isStackedHorizontally: Bool = false
-    var isStackedVertically: Bool = false
-    var contentSizeBasedConstraints: [NSLayoutConstraint] = []
+    var isStackedHorizontally = false
+    var isStackedVertically = false
+    var contentSizeBasedConstraints = [NSLayoutConstraint]()
 
     override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
         keyLabel = UILabel()
@@ -364,7 +364,7 @@ private class KeyValueCell: CopyableLabelTableViewCell {
     }
 
     func configureForContentSize() {
-        var constraints: [NSLayoutConstraint] = []
+        var constraints = [NSLayoutConstraint]()
         if self.traitCollection.preferredContentSizeCategory.isAccessibilityCategory {
             // Stack vertically
             if !isStackedVertically {
index b26992d39f2938d6de18e42b3a851313ce120abe..7cd96a2e7a15f119d75b58d2a6e2154a8a7487c1 100644 (file)
@@ -334,52 +334,45 @@ extension TunnelEditTableViewController {
         switch field {
         case .publicKey:
             cell.placeholderText = "Required"
-        case .preSharedKey, .endpoint, .allowedIPs:
+            cell.keyboardType = .default
+        case .preSharedKey, .endpoint:
+            cell.placeholderText = "Optional"
+            cell.keyboardType = .default
+        case .allowedIPs:
             cell.placeholderText = "Optional"
+            cell.keyboardType = .numbersAndPunctuation
         case .persistentKeepAlive:
             cell.placeholderText = "Off"
-        case .excludePrivateIPs, .deletePeer:
-            break
-        }
-        
-        switch field {
-        case .persistentKeepAlive:
             cell.keyboardType = .numberPad
-        case .allowedIPs:
-            cell.keyboardType = .numbersAndPunctuation
-        default:
+        case .excludePrivateIPs, .deletePeer:
             cell.keyboardType = .default
         }
 
-        // Show erroring fields
-        cell.isValueValid = (!peerData.fieldsWithError.contains(field))
-        // Bind values to view model
+        cell.isValueValid = !peerData.fieldsWithError.contains(field)
         cell.value = peerData[field]
-        if field != .allowedIPs {
-            cell.onValueChanged = { [weak peerData] value in
-                peerData?[field] = value
-            }
-        }
-        // Compute state of exclude private IPs live
+        
         if field == .allowedIPs {
             cell.onValueBeingEdited = { [weak self, weak peerData] value in
-                if let peerData = peerData, let self = self {
-                    let oldValue = peerData.shouldAllowExcludePrivateIPsControl
-                    peerData[.allowedIPs] = value
-                    if oldValue != peerData.shouldAllowExcludePrivateIPsControl {
-                        if let row = self.peerFields.firstIndex(of: .excludePrivateIPs) {
-                            if peerData.shouldAllowExcludePrivateIPsControl {
-                                self.tableView.insertRows(at: [IndexPath(row: row, section: indexPath.section)], with: .fade)
-                            } else {
-                                self.tableView.deleteRows(at: [IndexPath(row: row, section: indexPath.section)], with: .fade)
-                            }
+                guard let self = self, let peerData = peerData else { return }
+                
+                let oldValue = peerData.shouldAllowExcludePrivateIPsControl
+                peerData[.allowedIPs] = value
+                if oldValue != peerData.shouldAllowExcludePrivateIPsControl {
+                    if let row = self.peerFields.firstIndex(of: .excludePrivateIPs) {
+                        if peerData.shouldAllowExcludePrivateIPsControl {
+                            self.tableView.insertRows(at: [IndexPath(row: row, section: indexPath.section)], with: .fade)
+                        } else {
+                            self.tableView.deleteRows(at: [IndexPath(row: row, section: indexPath.section)], with: .fade)
                         }
                     }
                 }
             }
         } else {
-            cell.onValueBeingEdited = nil
+            cell.onValueChanged = { [weak peerData] value in
+                peerData?[field] = value
+            }
         }
+        
         return cell
     }
 
@@ -410,7 +403,7 @@ extension TunnelEditTableViewController {
             cell.isOn = activateOnDemandSetting.isActivateOnDemandEnabled
             cell.onSwitchToggled = { [weak self] isOn in
                 guard let self = self else { return }
-                let indexPaths: [IndexPath] = (1 ..< 4).map { IndexPath(row: $0, section: indexPath.section) }
+                let indexPaths = (1 ..< 4).map { IndexPath(row: $0, section: indexPath.section) }
                 if isOn {
                     self.activateOnDemandSetting.isActivateOnDemandEnabled = true
                     if self.activateOnDemandSetting.activateOnDemandOption == .none {
@@ -529,7 +522,7 @@ private class KeyValueCell: UITableViewCell {
 
     var isStackedHorizontally: Bool = false
     var isStackedVertically: Bool = false
-    var contentSizeBasedConstraints: [NSLayoutConstraint] = []
+    var contentSizeBasedConstraints = [NSLayoutConstraint]()
 
     private var textFieldValueOnBeginEditing: String = ""
 
@@ -573,7 +566,7 @@ private class KeyValueCell: UITableViewCell {
     }
 
     func configureForContentSize() {
-        var constraints: [NSLayoutConstraint] = []
+        var constraints = [NSLayoutConstraint]()
         if self.traitCollection.preferredContentSizeCategory.isAccessibilityCategory {
             // Stack vertically
             if !isStackedVertically {
index e5d5af13671cc4035953eaa82332a7a33a7a5bd6..f24b452df66d861727a014ea5dbba7639d17317c 100644 (file)
@@ -173,7 +173,7 @@ class TunnelsListTableViewController: UIViewController {
                     ErrorPresenter.showErrorAlert(error: error, from: self)
                     return
                 }
-                let configs: [TunnelConfiguration?] = result.value!
+                let configs = result.value!
                 tunnelsManager.addMultiple(tunnelConfigurations: configs.compactMap { $0 }) { [weak self] numberSuccessful in
                     if numberSuccessful == configs.count {
                         completionHandler?()
index 9716eafda1033b7d159e9686b4d268175508452d..9d48cdb399c62d985ddc00110278c208cd06a288 100644 (file)
@@ -32,7 +32,8 @@ enum TunnelsManagerError: WireGuardAppError {
     case tunnelActivationFailedInternalError // startTunnel() succeeded, but activation failed
     case tunnelActivationFailedNoInternetConnection // startTunnel() succeeded, but activation failed since no internet
 
-    func alertText() -> (String, String)? {
+    //swiftlint:disable:next cyclomatic_complexity
+    func alertText() -> AlertText {
         switch self {
         case .tunnelNameEmpty:
             return ("No name provided", "Can't create tunnel with an empty name")
@@ -46,7 +47,6 @@ enum TunnelsManagerError: WireGuardAppError {
             return ("Unable to modify tunnel", "Internal error")
         case .vpnSystemErrorOnRemoveTunnel:
             return ("Unable to remove tunnel", "Internal error")
-
         case .attemptingActivationWhenTunnelIsNotInactive:
             return ("Activation failure", "The tunnel is already active or in the process of being activated")
         case .attemptingActivationWhenAnotherTunnelIsOperational(let otherTunnelName):
@@ -267,44 +267,41 @@ class TunnelsManager {
     }
 
     private func startObservingTunnelStatuses() {
-        if statusObservationToken != nil { return }
-        statusObservationToken = NotificationCenter.default.addObserver(
-            forName: .NEVPNStatusDidChange,
-            object: nil,
-            queue: OperationQueue.main) { [weak self] statusChangeNotification in
-                guard let self = self else { return }
-                guard let session = statusChangeNotification.object as? NETunnelProviderSession else { return }
-                guard let tunnelProvider = session.manager as? NETunnelProviderManager else { return }
-                guard let tunnel = self.tunnels.first(where: { $0.tunnelProvider == tunnelProvider }) else { return }
-
-                os_log("Tunnel '%{public}@' connection status changed to '%{public}@'",
-                       log: OSLog.default, type: .debug, tunnel.name, "\(tunnel.tunnelProvider.connection.status)")
-
-                // In case our attempt to start the tunnel, didn't succeed
-                if tunnel == self.tunnelBeingActivated {
-                    if session.status == .disconnected {
-                        if InternetReachability.currentStatus() == .notReachable {
-                            let error = TunnelsManagerError.tunnelActivationFailedNoInternetConnection
-                            self.activationDelegate?.tunnelActivationFailed(tunnel: tunnel, error: error)
-                        }
-                        self.tunnelBeingActivated = nil
-                    } else if session.status == .connected {
-                        self.tunnelBeingActivated = nil
+        guard statusObservationToken == nil else { return }
+        
+        statusObservationToken = NotificationCenter.default.addObserver(forName: .NEVPNStatusDidChange, object: nil, queue: OperationQueue.main) { [weak self] statusChangeNotification in
+            guard let self = self else { return }
+            guard let session = statusChangeNotification.object as? NETunnelProviderSession else { return }
+            guard let tunnelProvider = session.manager as? NETunnelProviderManager else { return }
+            guard let tunnel = self.tunnels.first(where: { $0.tunnelProvider == tunnelProvider }) else { return }
+            
+            os_log("Tunnel '%{public}@' connection status changed to '%{public}@'",
+                   log: OSLog.default, type: .debug, tunnel.name, "\(tunnel.tunnelProvider.connection.status)")
+            
+            // In case our attempt to start the tunnel, didn't succeed
+            if tunnel == self.tunnelBeingActivated {
+                if session.status == .disconnected {
+                    if InternetReachability.currentStatus() == .notReachable {
+                        let error = TunnelsManagerError.tunnelActivationFailedNoInternetConnection
+                        self.activationDelegate?.tunnelActivationFailed(tunnel: tunnel, error: error)
                     }
+                    self.tunnelBeingActivated = nil
+                } else if session.status == .connected {
+                    self.tunnelBeingActivated = nil
                 }
-
-                // In case we're restarting the tunnel
-                if (tunnel.status == .restarting) && (session.status == .disconnected || session.status == .disconnecting) {
-                    // Don't change tunnel.status when disconnecting for a restart
-                    if session.status == .disconnected {
-                        self.tunnelBeingActivated = tunnel
-                        tunnel.startActivation { _ in }
-                    }
-                    return
+            }
+            
+            // In case we're restarting the tunnel
+            if (tunnel.status == .restarting) && (session.status == .disconnected || session.status == .disconnecting) {
+                // Don't change tunnel.status when disconnecting for a restart
+                if session.status == .disconnected {
+                    self.tunnelBeingActivated = tunnel
+                    tunnel.startActivation { _ in }
                 }
-
-                // Update tunnel status
-                tunnel.refreshStatus()
+                return
+            }
+            
+            tunnel.refreshStatus()
         }
     }
 
index 3e4707d6b42135cf96d61bc9442adfbf2956a415..ba83ac5d9df589f2f46078f3744462e4a8b4fc94 100644 (file)
@@ -2,5 +2,6 @@
 // Copyright © 2018 WireGuard LLC. All Rights Reserved.
 
 protocol WireGuardAppError: Error {
-    func alertText() -> (/* title */ String, /* message */ String)?
+    typealias AlertText = (title: String, message: String)
+    func alertText() -> AlertText
 }
index 12cfb698ffb79f5b717fbd1ed4eb9033193195b2..ad74d0e1eb10a182b57cf3612739a819a46214e4 100644 (file)
@@ -8,7 +8,7 @@ enum ZipArchiveError: WireGuardAppError {
     case cantOpenOutputZipFileForWriting
     case badArchive
 
-    func alertText() -> (String, String)? {
+    func alertText() -> AlertText {
         switch self {
         case .cantOpenInputZipFile:
             return ("Unable to read zip archive", "The zip archive could not be read.")
@@ -41,7 +41,7 @@ class ZipArchive {
 
     static func unarchive(url: URL, requiredFileExtensions: [String]) throws -> [(fileBaseName: String, contents: Data)] {
 
-        var results: [(fileBaseName: String, contents: Data)] = []
+        var results = [(fileBaseName: String, contents: Data)]()
 
         guard let zipFile = unzOpen64(url.path) else {
             throw ZipArchiveError.cantOpenInputZipFile
index b0e6b15d30f5c5a336f4c11492db58b98b1c3f14..cdc9ac983b351c59265c317913d2bef5234776d9 100644 (file)
@@ -6,7 +6,7 @@ import UIKit
 enum ZipExporterError: WireGuardAppError {
     case noTunnelsToExport
 
-    func alertText() -> (String, String)? {
+    func alertText() -> AlertText {
         switch self {
         case .noTunnelsToExport:
             return ("Nothing to export", "There are no tunnels to export")
@@ -15,8 +15,7 @@ enum ZipExporterError: WireGuardAppError {
 }
 
 class ZipExporter {
-    static func exportConfigFiles(tunnelConfigurations: [TunnelConfiguration], to url: URL,
-                                  completion: @escaping (WireGuardAppError?) -> Void) {
+    static func exportConfigFiles(tunnelConfigurations: [TunnelConfiguration], to url: URL, completion: @escaping (WireGuardAppError?) -> Void) {
 
         guard !tunnelConfigurations.isEmpty else {
             completion(ZipExporterError.noTunnelsToExport)
index e2767f2ef21144e7a45f153c1362a9ce56a8359c..523614b99bb908428cb43586727253baf2985c33 100644 (file)
@@ -6,7 +6,7 @@ import UIKit
 enum ZipImporterError: WireGuardAppError {
     case noTunnelsInZipArchive
 
-    func alertText() -> (String, String)? {
+    func alertText() -> AlertText {
         switch self {
         case .noTunnelsInZipArchive:
             return ("No tunnels in zip archive", "No .conf tunnel files were found inside the zip archive.")
index 57093c820b10ac73079b2510f9382f7e7b258bcc..9f85743dfcff130a8982ce42a2b2c9fdb17234c3 100644 (file)
@@ -42,7 +42,7 @@ class DNSResolver {
 
         dispatchGroup.wait() // TODO: Timeout?
 
-        var hostnamesWithDnsResolutionFailure: [String] = []
+        var hostnamesWithDnsResolutionFailure = [String]()
         assert(endpoints.count == resolvedEndpoints.count)
         for tuple in zip(endpoints, resolvedEndpoints) {
             let endpoint = tuple.0
index b1571d5278c3b2604d51e38aca284547aa9a7391..5cac33312b8fc00457ce1d065e0f0eaa4e5e7ef7 100644 (file)
@@ -31,8 +31,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
     }
 
     /// Begin the process of establishing the tunnel.
-    override func startTunnel(options: [String: NSObject]?,
-                              completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) {
+    override func startTunnel(options: [String: NSObject]?, completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) {
 
         guard let tunnelProviderProtocol = self.protocolConfiguration as? NETunnelProviderProtocol,
             let tunnelConfiguration = tunnelProviderProtocol.tunnelConfiguration() else {
@@ -58,7 +57,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
         // Resolve endpoint domains
 
         let endpoints = tunnelConfiguration.peers.map { $0.endpoint }
-        var resolvedEndpoints: [Endpoint?] = []
+        var resolvedEndpoints = [Endpoint?]()
         do {
             resolvedEndpoints = try DNSResolver.resolveSync(endpoints: endpoints)
         } catch DNSResolverError.dnsResolutionFailed(let hostnames) {
index 1e5ae8e9008326943571bab9570fe0d1b7717e8b..d97699da0373b5280003faa3a975e151e98c08ed 100644 (file)
@@ -60,16 +60,13 @@ class PacketTunnelSettingsGenerator {
     }
 
     func generateNetworkSettings() -> NEPacketTunnelNetworkSettings {
-
-        // Remote address
-
         /* iOS requires a tunnel endpoint, whereas in WireGuard it's valid for
          * a tunnel to have no endpoint, or for there to be many endpoints, in
          * which case, displaying a single one in settings doesn't really
          * make sense. So, we fill it in with this placeholder, which is not
          * a valid IP address that will actually route over the Internet.
          */
-        var remoteAddress: String = "0.0.0.0"
+        var remoteAddress = "0.0.0.0"
         let endpointsCompact = resolvedEndpoints.compactMap { $0 }
         if endpointsCompact.count == 1 {
             switch endpointsCompact.first!.host {
@@ -83,16 +80,12 @@ class PacketTunnelSettingsGenerator {
         }
 
         let networkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: remoteAddress)
-
-        // DNS
-
+        
         let dnsServerStrings = tunnelConfiguration.interface.dns.map { $0.stringRepresentation() }
         let dnsSettings = NEDNSSettings(servers: dnsServerStrings)
         dnsSettings.matchDomains = [""] // All DNS queries must first go through the VPN's DNS
         networkSettings.dnsSettings = dnsSettings
-
-        // MTU
-
+        
         let mtu = tunnelConfiguration.interface.mtu ?? 0
         if mtu == 0 {
             // 0 imples automatic MTU, where we set overhead as 80 bytes, which is the worst case for WireGuard
@@ -100,114 +93,86 @@ class PacketTunnelSettingsGenerator {
         } else {
             networkSettings.mtu = NSNumber(value: mtu)
         }
+        
+        let (ipv4Routes, ipv6Routes) = routes()
+        let (ipv4IncludedRoutes, ipv6IncludedRoutes) = includedRoutes()
+        let (ipv4ExcludedRoutes, ipv6ExcludedRoutes) = excludedRoutes()
+        
+        let ipv4Settings = NEIPv4Settings(addresses: ipv4Routes.map { $0.destinationAddress }, subnetMasks: ipv4Routes.map { $0.destinationSubnetMask })
+        ipv4Settings.includedRoutes = ipv4IncludedRoutes
+        ipv4Settings.excludedRoutes = ipv4ExcludedRoutes
+        networkSettings.ipv4Settings = ipv4Settings
+        
+        let ipv6Settings = NEIPv6Settings(addresses: ipv6Routes.map { $0.destinationAddress }, networkPrefixLengths: ipv6Routes.map { $0.destinationNetworkPrefixLength })
+        ipv6Settings.includedRoutes = ipv6IncludedRoutes
+        ipv6Settings.excludedRoutes = ipv6ExcludedRoutes
+        networkSettings.ipv6Settings = ipv6Settings
 
-        // Addresses from interface addresses
-
-        var ipv4Addresses: [String] = []
-        var ipv4SubnetMasks: [String] = []
-
-        var ipv6Addresses: [String] = []
-        var ipv6NetworkPrefixLengths: [NSNumber] = []
+        return networkSettings
+    }
 
+    private func ipv4SubnetMaskString(of addressRange: IPAddressRange) -> String {
+        let length: UInt8 = addressRange.networkPrefixLength
+        assert(length <= 32)
+        var octets: [UInt8] = [0, 0, 0, 0]
+        let subnetMask: UInt32 = length > 0 ? ~UInt32(0) << (32 - length) : UInt32(0)
+        octets[0] = UInt8(truncatingIfNeeded: subnetMask >> 24)
+        octets[1] = UInt8(truncatingIfNeeded: subnetMask >> 16)
+        octets[2] = UInt8(truncatingIfNeeded: subnetMask >> 8)
+        octets[3] = UInt8(truncatingIfNeeded: subnetMask)
+        return octets.map { String($0) }.joined(separator: ".")
+    }
+    
+    private func routes() -> ([NEIPv4Route], [NEIPv6Route]) {
+        var ipv4Routes = [NEIPv4Route]()
+        var ipv6Routes = [NEIPv6Route]()
         for addressRange in tunnelConfiguration.interface.addresses {
             if addressRange.address is IPv4Address {
-                ipv4Addresses.append("\(addressRange.address)")
-                ipv4SubnetMasks.append(PacketTunnelSettingsGenerator.ipv4SubnetMaskString(of: addressRange))
+                ipv4Routes.append(NEIPv4Route(destinationAddress: "\(addressRange.address)", subnetMask: ipv4SubnetMaskString(of: addressRange)))
             } else if addressRange.address is IPv6Address {
-                ipv6Addresses.append("\(addressRange.address)")
-                ipv6NetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength))
+                /* Big fat ugly hack for broken iOS networking stack: the smallest prefix that will have
+                 * any effect on iOS is a /120, so we clamp everything above to /120. This is potentially
+                 * very bad, if various network parameters were actually relying on that subnet being
+                 * intentionally small. TODO: talk about this with upstream iOS devs.
+                 */
+                ipv6Routes.append(NEIPv6Route(destinationAddress: "\(addressRange.address)", networkPrefixLength: NSNumber(value: min(120, addressRange.networkPrefixLength))))
             }
         }
-
-        // Included routes from AllowedIPs
-
-        var ipv4IncludedRouteAddresses: [String] = []
-        var ipv4IncludedRouteSubnetMasks: [String] = []
-
-        var ipv6IncludedRouteAddresses: [String] = []
-        var ipv6IncludedRouteNetworkPrefixLengths: [NSNumber] = []
-
+        return (ipv4Routes, ipv6Routes)
+    }
+    
+    private func includedRoutes() -> ([NEIPv4Route], [NEIPv6Route]) {
+        var ipv4IncludedRoutes = [NEIPv4Route]()
+        var ipv6IncludedRoutes = [NEIPv6Route]()
         for peer in tunnelConfiguration.peers {
             for addressRange in peer.allowedIPs {
                 if addressRange.address is IPv4Address {
-                    ipv4IncludedRouteAddresses.append("\(addressRange.address)")
-                    ipv4IncludedRouteSubnetMasks.append(PacketTunnelSettingsGenerator.ipv4SubnetMaskString(of: addressRange))
+                    ipv4IncludedRoutes.append(NEIPv4Route(destinationAddress: "\(addressRange.address)", subnetMask: ipv4SubnetMaskString(of: addressRange)))
                 } else if addressRange.address is IPv6Address {
-                    ipv6IncludedRouteAddresses.append("\(addressRange.address)")
-                    ipv6IncludedRouteNetworkPrefixLengths.append(NSNumber(value: addressRange.networkPrefixLength))
+                    ipv6IncludedRoutes.append(NEIPv6Route(destinationAddress: "\(addressRange.address)", networkPrefixLength: NSNumber(value: addressRange.networkPrefixLength)))
                 }
             }
         }
-
-        // Excluded routes from endpoints
-
-        var ipv4ExcludedRouteAddresses: [String] = []
-        var ipv4ExcludedRouteSubnetMasks: [String] = []
-
-        var ipv6ExcludedRouteAddresses: [String] = []
-        var ipv6ExcludedRouteNetworkPrefixLengths: [NSNumber] = []
-
+        return (ipv4IncludedRoutes, ipv6IncludedRoutes)
+    }
+    
+    private func excludedRoutes() -> ([NEIPv4Route], [NEIPv6Route]) {
+        var ipv4ExcludedRoutes = [NEIPv4Route]()
+        var ipv6ExcludedRoutes = [NEIPv6Route]()
         for endpoint in resolvedEndpoints {
             guard let endpoint = endpoint else { continue }
             switch endpoint.host {
             case .ipv4(let address):
-                ipv4ExcludedRouteAddresses.append("\(address)")
-                ipv4ExcludedRouteSubnetMasks.append("255.255.255.255") // A single IPv4 address
+                ipv4ExcludedRoutes.append(NEIPv4Route(destinationAddress: "\(address)", subnetMask: "255.255.255.255"))
             case .ipv6(let address):
-                ipv6ExcludedRouteAddresses.append("\(address)")
-                ipv6ExcludedRouteNetworkPrefixLengths.append(NSNumber(value: UInt8(128))) // A single IPv6 address
+                ipv6ExcludedRoutes.append(NEIPv6Route(destinationAddress: "\(address)", networkPrefixLength: NSNumber(value: UInt8(128))))
             default:
                 fatalError()
             }
         }
-
-        // Apply IPv4 settings
-
-        let ipv4Settings = NEIPv4Settings(addresses: ipv4Addresses, subnetMasks: ipv4SubnetMasks)
-        assert(ipv4IncludedRouteAddresses.count == ipv4IncludedRouteSubnetMasks.count)
-        ipv4Settings.includedRoutes = zip(ipv4IncludedRouteAddresses, ipv4IncludedRouteSubnetMasks).map {
-            NEIPv4Route(destinationAddress: $0.0, subnetMask: $0.1)
-        }
-        assert(ipv4ExcludedRouteAddresses.count == ipv4ExcludedRouteSubnetMasks.count)
-        ipv4Settings.excludedRoutes = zip(ipv4ExcludedRouteAddresses, ipv4ExcludedRouteSubnetMasks).map {
-            NEIPv4Route(destinationAddress: $0.0, subnetMask: $0.1)
-        }
-        networkSettings.ipv4Settings = ipv4Settings
-
-        // Apply IPv6 settings
-
-        /* Big fat ugly hack for broken iOS networking stack: the smallest prefix that will have
-         * any effect on iOS is a /120, so we clamp everything above to /120. This is potentially
-         * very bad, if various network parameters were actually relying on that subnet being
-         * intentionally small. TODO: talk about this with upstream iOS devs.
-         */
-        let ipv6Settings = NEIPv6Settings(addresses: ipv6Addresses, networkPrefixLengths: ipv6NetworkPrefixLengths.map { NSNumber(value: min(120, $0.intValue)) })
-        assert(ipv6IncludedRouteAddresses.count == ipv6IncludedRouteNetworkPrefixLengths.count)
-        ipv6Settings.includedRoutes = zip(ipv6IncludedRouteAddresses, ipv6IncludedRouteNetworkPrefixLengths).map {
-            NEIPv6Route(destinationAddress: $0.0, networkPrefixLength: $0.1)
-        }
-        assert(ipv6ExcludedRouteAddresses.count == ipv6ExcludedRouteNetworkPrefixLengths.count)
-        ipv6Settings.excludedRoutes = zip(ipv6ExcludedRouteAddresses, ipv6ExcludedRouteNetworkPrefixLengths).map {
-            NEIPv6Route(destinationAddress: $0.0, networkPrefixLength: $0.1)
-        }
-        networkSettings.ipv6Settings = ipv6Settings
-
-        // Done
-
-        return networkSettings
-    }
-
-    static func ipv4SubnetMaskString(of addressRange: IPAddressRange) -> String {
-        let length: UInt8 = addressRange.networkPrefixLength
-        assert(length <= 32)
-        var octets: [UInt8] = [0, 0, 0, 0]
-        let subnetMask: UInt32 = length > 0 ? ~UInt32(0) << (32 - length) : UInt32(0)
-        octets[0] = UInt8(truncatingIfNeeded: subnetMask >> 24)
-        octets[1] = UInt8(truncatingIfNeeded: subnetMask >> 16)
-        octets[2] = UInt8(truncatingIfNeeded: subnetMask >> 8)
-        octets[3] = UInt8(truncatingIfNeeded: subnetMask)
-        return octets.map { String($0) }.joined(separator: ".")
+        return (ipv4ExcludedRoutes, ipv6ExcludedRoutes)
     }
+    
 }
 
 private extension Data {