From de14b76b4d99f74d52b6e404b2ab37394fa5b9dc Mon Sep 17 00:00:00 2001 From: Eric Kuck Date: Wed, 12 Dec 2018 11:40:57 -0600 Subject: Added swiftlint and fixed all errors (and a bunch, but not all, warnings) Signed-off-by: Eric Kuck --- .swiftlint.yml | 12 - README.md | 6 + WireGuard/.swiftlint.yml | 8 + WireGuard/Shared/FileManager+Extension.swift | 4 +- WireGuard/Shared/Model/Configuration.swift | 18 +- WireGuard/Shared/Model/DNSServer.swift | 2 +- WireGuard/Shared/Model/Endpoint.swift | 14 +- WireGuard/Shared/Model/IPAddressRange.swift | 6 +- WireGuard/WireGuard.xcodeproj/project.pbxproj | 38 ++ WireGuard/WireGuard/UI/TunnelViewModel.swift | 22 +- .../WireGuard/UI/iOS/MainViewController.swift | 13 +- .../WireGuard/UI/iOS/QRScanViewController.swift | 11 +- WireGuard/WireGuard/UI/iOS/ScrollableLabel.swift | 2 +- .../UI/iOS/SettingsTableViewController.swift | 7 +- .../UI/iOS/TunnelDetailTableViewController.swift | 26 +- .../UI/iOS/TunnelEditTableViewController.swift | 523 ++++++++++----------- .../UI/iOS/TunnelsListTableViewController.swift | 10 +- WireGuard/WireGuard/VPN/TunnelsManager.swift | 49 +- WireGuard/WireGuard/WireGuardResult.swift | 16 +- WireGuard/WireGuard/ZipArchive/ZipExporter.swift | 2 +- WireGuard/WireGuard/ZipArchive/ZipImporter.swift | 12 +- .../WireGuardNetworkExtension/DNSResolver.swift | 6 +- .../WireGuardNetworkExtension/ErrorNotifier.swift | 2 +- .../PacketTunnelProvider.swift | 16 +- .../PacketTunnelSettingsGenerator.swift | 18 +- 25 files changed, 437 insertions(+), 406 deletions(-) delete mode 100644 .swiftlint.yml create mode 100644 WireGuard/.swiftlint.yml diff --git a/.swiftlint.yml b/.swiftlint.yml deleted file mode 100644 index df5ce7d..0000000 --- a/.swiftlint.yml +++ /dev/null @@ -1,12 +0,0 @@ -disabled_rules: - - line_length - - trailing_comma -excluded: - - Pods -file_length: - warning: 500 -type_name: - min_length: 2 # only warning - max_length: # warning and error - warning: 50 - error: 60 diff --git a/README.md b/README.md index 924b991..921c37c 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,12 @@ $ cp WireGuard/WireGuard/Config/Developer.xcconfig.template WireGuard/WireGuard/ $ vim WireGuard/WireGuard/Config/Developer.xcconfig ``` +- Install swiftlint: + +``` +$ brew install swiftlint +``` + - Open project in XCode: ``` diff --git a/WireGuard/.swiftlint.yml b/WireGuard/.swiftlint.yml new file mode 100644 index 0000000..b16b6b3 --- /dev/null +++ b/WireGuard/.swiftlint.yml @@ -0,0 +1,8 @@ +disabled_rules: + - force_cast + - line_length +file_length: + warning: 500 +cyclomatic_complexity: + warning: 10 + error: 25 diff --git a/WireGuard/Shared/FileManager+Extension.swift b/WireGuard/Shared/FileManager+Extension.swift index d4c2547..535b999 100644 --- a/WireGuard/Shared/FileManager+Extension.swift +++ b/WireGuard/Shared/FileManager+Extension.swift @@ -20,8 +20,8 @@ extension FileManager { static func deleteFile(at url: URL) -> Bool { do { try FileManager.default.removeItem(at: url) - } catch(let e) { - os_log("Failed to delete file '%{public}@': %{public}@", log: OSLog.default, type: .debug, url.absoluteString, e.localizedDescription) + } catch let error { + os_log("Failed to delete file '%{public}@': %{public}@", log: OSLog.default, type: .debug, url.absoluteString, error.localizedDescription) return false } return true diff --git a/WireGuard/Shared/Model/Configuration.swift b/WireGuard/Shared/Model/Configuration.swift index d2680cb..09fdd6b 100644 --- a/WireGuard/Shared/Model/Configuration.swift +++ b/WireGuard/Shared/Model/Configuration.swift @@ -16,7 +16,7 @@ final class TunnelConfiguration: Codable { let peerPublicKeysArray = peers.map { $0.publicKey } let peerPublicKeysSet = Set(peerPublicKeysArray) - if (peerPublicKeysArray.count != peerPublicKeysSet.count) { + if peerPublicKeysArray.count != peerPublicKeysSet.count { fatalError("Two or more peers cannot have the same public key") } } @@ -34,8 +34,12 @@ struct InterfaceConfiguration: Codable { init(name: String, privateKey: Data) { self.name = name self.privateKey = privateKey - if (name.isEmpty) { fatalError("Empty name") } - if (privateKey.count != TunnelConfiguration.keyLength) { fatalError("Invalid private key") } + if name.isEmpty { + fatalError("Empty name") + } + if privateKey.count != TunnelConfiguration.keyLength { + fatalError("Invalid private key") + } } } @@ -45,7 +49,9 @@ struct PeerConfiguration: Codable { var preSharedKey: Data? { didSet(value) { if let value = value { - if (value.count != TunnelConfiguration.keyLength) { fatalError("Invalid preshared key") } + if value.count != TunnelConfiguration.keyLength { + fatalError("Invalid preshared key") + } } } } @@ -55,6 +61,8 @@ struct PeerConfiguration: Codable { init(publicKey: Data) { self.publicKey = publicKey - if (publicKey.count != TunnelConfiguration.keyLength) { fatalError("Invalid public key") } + if publicKey.count != TunnelConfiguration.keyLength { + fatalError("Invalid public key") + } } } diff --git a/WireGuard/Shared/Model/DNSServer.swift b/WireGuard/Shared/Model/DNSServer.swift index 8be1ddd..bb20c02 100644 --- a/WireGuard/Shared/Model/DNSServer.swift +++ b/WireGuard/Shared/Model/DNSServer.swift @@ -40,7 +40,7 @@ extension DNSServer: Codable { let container = try decoder.singleValueContainer() var data = try container.decode(Data.self) let ipAddressFromData: IPAddress? = { - switch (data.count) { + switch data.count { case 4: return IPv4Address(data) case 16: return IPv6Address(data) default: return nil diff --git a/WireGuard/Shared/Model/Endpoint.swift b/WireGuard/Shared/Model/Endpoint.swift index ab357ba..38ffab9 100644 --- a/WireGuard/Shared/Model/Endpoint.swift +++ b/WireGuard/Shared/Model/Endpoint.swift @@ -35,8 +35,8 @@ extension Endpoint { hostString = String(string[string.startIndex ..< endOfHost]) } guard let endpointPort = NWEndpoint.Port(String(string[startOfPort ..< string.endIndex])) else { return nil } - let invalidCharacterIndex = hostString.unicodeScalars.firstIndex { (c) -> Bool in - return !CharacterSet.urlHostAllowed.contains(c) + let invalidCharacterIndex = hostString.unicodeScalars.firstIndex { char in + return !CharacterSet.urlHostAllowed.contains(char) } guard (invalidCharacterIndex == nil) else { return nil } host = NWEndpoint.Host(hostString) @@ -79,11 +79,11 @@ extension Endpoint: Codable { extension Endpoint { func hasHostAsIPAddress() -> Bool { switch (host) { - case .name(_, _): + case .name: return false - case .ipv4(_): + case .ipv4: return true - case .ipv6(_): + case .ipv6: return true } } @@ -92,9 +92,9 @@ extension Endpoint { switch (host) { case .name(let hostname, _): return hostname - case .ipv4(_): + case .ipv4: return nil - case .ipv6(_): + case .ipv6: return nil } } diff --git a/WireGuard/Shared/Model/IPAddressRange.swift b/WireGuard/Shared/Model/IPAddressRange.swift index 2fb4a16..e3c1441 100644 --- a/WireGuard/Shared/Model/IPAddressRange.swift +++ b/WireGuard/Shared/Model/IPAddressRange.swift @@ -27,9 +27,9 @@ extension IPAddressRange { } let maxNetworkPrefixLength: UInt8 = (address is IPv4Address) ? 32 : 128 var networkPrefixLength: UInt8 - if (endOfIPAddress < string.endIndex) { // "/" was located + if endOfIPAddress < string.endIndex { // "/" was located let indexOfNetworkPrefixLength = string.index(after: endOfIPAddress) - guard (indexOfNetworkPrefixLength < string.endIndex) else { return nil } + guard indexOfNetworkPrefixLength < string.endIndex else { return nil } let networkPrefixLengthSubstring = string[indexOfNetworkPrefixLength ..< string.endIndex] guard let npl = UInt8(networkPrefixLengthSubstring) else { return nil } networkPrefixLength = min(npl, maxNetworkPrefixLength) @@ -69,7 +69,7 @@ extension IPAddressRange: Codable { var data = try container.decode(Data.self) networkPrefixLength = data.removeLast() let ipAddressFromData: IPAddress? = { - switch (data.count) { + switch data.count { case 4: return IPv4Address(data) case 16: return IPv6Address(data) default: return nil diff --git a/WireGuard/WireGuard.xcodeproj/project.pbxproj b/WireGuard/WireGuard.xcodeproj/project.pbxproj index dc22757..79d606d 100644 --- a/WireGuard/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard/WireGuard.xcodeproj/project.pbxproj @@ -384,6 +384,7 @@ isa = PBXNativeTarget; buildConfigurationList = 6F5D0C25218352EF000F85AD /* Build configuration list for PBXNativeTarget "WireGuardNetworkExtension" */; buildPhases = ( + 5F45417B21C0906F00994C13 /* Swiftlint */, 6F61F1EC21BA4D4700483816 /* Extract wireguard-go Version */, 6F5D0C16218352EF000F85AD /* Sources */, 6F5D0C17218352EF000F85AD /* Frameworks */, @@ -403,6 +404,7 @@ isa = PBXNativeTarget; buildConfigurationList = 6FF4AC26211EC472002C96EB /* Build configuration list for PBXNativeTarget "WireGuard" */; buildPhases = ( + 5F45417A21C0902400994C13 /* Swiftlint */, 6B87860E2189532500C099FB /* Extract wireguard-go Version */, 6FF4AC10211EC46F002C96EB /* Sources */, 6FF4AC11211EC46F002C96EB /* Frameworks */, @@ -494,6 +496,42 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ + 5F45417A21C0902400994C13 /* Swiftlint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = Swiftlint; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; + 5F45417B21C0906F00994C13 /* Swiftlint */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = Swiftlint; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if which swiftlint >/dev/null; then\n swiftlint\nelse\n echo \"warning: SwiftLint not installed, download from https://github.com/realm/SwiftLint\"\nfi\n"; + }; 6B87860E2189532500C099FB /* Extract wireguard-go Version */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; diff --git a/WireGuard/WireGuard/UI/TunnelViewModel.swift b/WireGuard/WireGuard/UI/TunnelViewModel.swift index 92a1a64..e623eab 100644 --- a/WireGuard/WireGuard/UI/TunnelViewModel.swift +++ b/WireGuard/WireGuard/UI/TunnelViewModel.swift @@ -379,8 +379,8 @@ class TunnelViewModel { var peersData: [PeerData] = [] if let tunnelConfiguration = tunnelConfiguration { interfaceData.validatedConfiguration = tunnelConfiguration.interface - for (i, peerConfiguration) in tunnelConfiguration.peers.enumerated() { - let peerData = PeerData(index: i) + for (index, peerConfiguration) in tunnelConfiguration.peers.enumerated() { + let peerData = PeerData(index: index) peerData.validatedConfiguration = peerConfiguration peersData.append(peerData) } @@ -397,22 +397,22 @@ class TunnelViewModel { func appendEmptyPeer() { let peer = PeerData(index: peersData.count) peersData.append(peer) - for p in peersData { - p.numberOfPeers = peersData.count - p.updateExcludePrivateIPsFieldState() + for peer in peersData { + peer.numberOfPeers = peersData.count + peer.updateExcludePrivateIPsFieldState() } } func deletePeer(peer: PeerData) { let removedPeer = peersData.remove(at: peer.index) assert(removedPeer.index == peer.index) - for p in peersData[peer.index ..< peersData.count] { - assert(p.index > 0) - p.index = p.index - 1 + for peer in peersData[peer.index ..< peersData.count] { + assert(peer.index > 0) + peer.index -= 1 } - for p in peersData { - p.numberOfPeers = peersData.count - p.updateExcludePrivateIPsFieldState() + for peer in peersData { + peer.numberOfPeers = peersData.count + peer.updateExcludePrivateIPsFieldState() } } diff --git a/WireGuard/WireGuard/UI/iOS/MainViewController.swift b/WireGuard/WireGuard/UI/iOS/MainViewController.swift index 69f40d5..c06b5d3 100644 --- a/WireGuard/WireGuard/UI/iOS/MainViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/MainViewController.swift @@ -42,20 +42,21 @@ class MainViewController: UISplitViewController { // Create the tunnels manager, and when it's ready, inform tunnelsListVC TunnelsManager.create { [weak self] result in + guard let self = self else { return } + if let error = result.error { ErrorPresenter.showErrorAlert(error: error, from: self) return } let tunnelsManager: TunnelsManager = result.value! - guard let s = self else { return } - s.tunnelsManager = tunnelsManager - s.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager) + self.tunnelsManager = tunnelsManager + self.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager) - tunnelsManager.activationDelegate = s + tunnelsManager.activationDelegate = self - s.onTunnelsManagerReady?(tunnelsManager) - s.onTunnelsManagerReady = nil + self.onTunnelsManagerReady?(tunnelsManager) + self.onTunnelsManagerReady = nil } } } diff --git a/WireGuard/WireGuard/UI/iOS/QRScanViewController.swift b/WireGuard/WireGuard/UI/iOS/QRScanViewController.swift index 207fc43..3849f70 100644 --- a/WireGuard/WireGuard/UI/iOS/QRScanViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/QRScanViewController.swift @@ -32,7 +32,7 @@ class QRScanViewController: UIViewController { NSLayoutConstraint.activate([ tipLabel.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor), tipLabel.rightAnchor.constraint(equalTo: view.safeAreaLayoutGuide.rightAnchor), - tipLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -32), + tipLabel.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -32) ]) guard let videoCaptureDevice = AVCaptureDevice.default(for: .video), @@ -118,12 +118,11 @@ class QRScanViewController: UIViewController { self?.dismiss(animated: true, completion: nil) })) alert.addAction(UIAlertAction(title: NSLocalizedString("Save", comment: ""), style: .default, handler: { [weak self] _ in - let title = alert.textFields?[0].text?.trimmingCharacters(in: .whitespacesAndNewlines) ?? "" - if (title.isEmpty) { return } + guard let title = alert.textFields?[0].text?.trimmingCharacters(in: .whitespacesAndNewlines), !title.isEmpty else { return } tunnelConfiguration.interface.name = title - if let s = self { - s.delegate?.addScannedQRCode(tunnelConfiguration: tunnelConfiguration, qrScanViewController: s) { - s.dismiss(animated: true, completion: nil) + if let self = self { + self.delegate?.addScannedQRCode(tunnelConfiguration: tunnelConfiguration, qrScanViewController: self) { + self.dismiss(animated: true, completion: nil) } } })) diff --git a/WireGuard/WireGuard/UI/iOS/ScrollableLabel.swift b/WireGuard/WireGuard/UI/iOS/ScrollableLabel.swift index 7abd4de..c0cc86b 100644 --- a/WireGuard/WireGuard/UI/iOS/ScrollableLabel.swift +++ b/WireGuard/WireGuard/UI/iOS/ScrollableLabel.swift @@ -34,7 +34,7 @@ class ScrollableLabel: UIScrollView { label.topAnchor.constraint(equalTo: self.contentLayoutGuide.topAnchor), label.bottomAnchor.constraint(equalTo: self.contentLayoutGuide.bottomAnchor), label.rightAnchor.constraint(equalTo: self.contentLayoutGuide.rightAnchor), - label.heightAnchor.constraint(equalTo: self.heightAnchor), + label.heightAnchor.constraint(equalTo: self.heightAnchor) ]) // If label has less content, it should expand to fit the scrollView, // so that right-alignment works in the label. diff --git a/WireGuard/WireGuard/UI/iOS/SettingsTableViewController.swift b/WireGuard/WireGuard/UI/iOS/SettingsTableViewController.swift index bbe5d25..aade1df 100644 --- a/WireGuard/WireGuard/UI/iOS/SettingsTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/SettingsTableViewController.swift @@ -57,8 +57,8 @@ class SettingsTableViewController: UITableViewController { guard let logo = self.tableView.tableFooterView else { return } let bottomPadding = max(self.tableView.layoutMargins.bottom, CGFloat(10)) let fullHeight = max(self.tableView.contentSize.height, self.tableView.bounds.size.height - self.tableView.layoutMargins.top - bottomPadding) - let e = logo.frame - logo.frame = CGRect(x: e.minX, y: fullHeight - e.height, width: e.width, height: e.height) + let frame = logo.frame + logo.frame = CGRect(x: frame.minX, y: fullHeight - frame.height, width: frame.width, height: frame.height) } @objc func doneTapped() { @@ -116,7 +116,8 @@ class SettingsTableViewController: UITableViewController { do { try FileManager.default.copyItem(at: networkExtensionLogFileURL, to: destinationURL) } catch { - os_log("Failed to copy file: %{public}@ to %{public}@: %{public}@", log: OSLog.default, type: .error, networkExtensionLogFileURL.absoluteString, destinationURL.absoluteString, error.localizedDescription) + os_log("Failed to copy file: %{public}@ to %{public}@: %{public}@", log: OSLog.default, type: .error, + networkExtensionLogFileURL.absoluteString, destinationURL.absoluteString, error.localizedDescription) ErrorPresenter.showErrorAlert(title: "Log export failed", message: "The log could not be copied", from: self) return } diff --git a/WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift index be81f7f..b54efd9 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift @@ -21,10 +21,10 @@ class TunnelDetailTableViewController: UITableViewController { let tunnel: TunnelContainer var tunnelViewModel: TunnelViewModel - init(tunnelsManager tm: TunnelsManager, tunnel t: TunnelContainer) { - tunnelsManager = tm - tunnel = t - tunnelViewModel = TunnelViewModel(tunnelConfiguration: t.tunnelConfiguration()) + init(tunnelsManager: TunnelsManager, tunnel: TunnelContainer) { + self.tunnelsManager = tunnelsManager + self.tunnel = tunnel + tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration()) super.init(style: .grouped) } @@ -152,11 +152,11 @@ extension TunnelDetailTableViewController { let cell = tableView.dequeueReusableCell(withIdentifier: TunnelDetailTableViewStatusCell.id, for: indexPath) as! TunnelDetailTableViewStatusCell cell.tunnel = self.tunnel cell.onSwitchToggled = { [weak self] isOn in - guard let s = self else { return } + guard let self = self else { return } if (isOn) { - s.tunnelsManager.startActivation(of: s.tunnel) { [weak s] error in + self.tunnelsManager.startActivation(of: self.tunnel) { [weak self] error in if let error = error { - ErrorPresenter.showErrorAlert(error: error, from: s, onPresented: { + ErrorPresenter.showErrorAlert(error: error, from: self, onPresented: { DispatchQueue.main.async { cell.statusSwitch.isOn = false } @@ -164,7 +164,7 @@ extension TunnelDetailTableViewController { } } } else { - s.tunnelsManager.startDeactivation(of: s.tunnel) + self.tunnelsManager.startDeactivation(of: self.tunnel) } } return cell @@ -198,16 +198,16 @@ extension TunnelDetailTableViewController { cell.buttonText = "Delete tunnel" cell.hasDestructiveAction = true cell.onTapped = { [weak self] in - guard let s = self else { return } - s.showConfirmationAlert(message: "Delete this tunnel?", buttonTitle: "Delete", from: cell) { [weak s] in - guard let tunnelsManager = s?.tunnelsManager, let tunnel = s?.tunnel else { return } + guard let self = self else { return } + self.showConfirmationAlert(message: "Delete this tunnel?", buttonTitle: "Delete", from: cell) { [weak self] in + guard let tunnelsManager = self?.tunnelsManager, let tunnel = self?.tunnel else { return } tunnelsManager.remove(tunnel: tunnel) { (error) in if (error != nil) { print("Error removing tunnel: \(String(describing: error))") return } } - s?.navigationController?.navigationController?.popToRootViewController(animated: true) + self?.navigationController?.navigationController?.popToRootViewController(animated: true) } } return cell @@ -374,7 +374,7 @@ class TunnelDetailTableViewKeyValueCell: CopyableLabelTableViewCell { constraints = [ contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: keyLabel.bottomAnchor, multiplier: 0.5), valueLabel.leftAnchor.constraint(equalToSystemSpacingAfter: keyLabel.rightAnchor, multiplier: 1), - valueLabel.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 0.5), + valueLabel.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 0.5) ] isStackedHorizontally = true isStackedVertically = false diff --git a/WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift index 3565a42..abe573a 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift @@ -37,19 +37,22 @@ class TunnelEditTableViewController: UITableViewController { let tunnelViewModel: TunnelViewModel var activateOnDemandSetting: ActivateOnDemandSetting - init(tunnelsManager tm: TunnelsManager, tunnel t: TunnelContainer) { + private var interfaceSectionCount: Int { return interfaceFieldsBySection.count } + private var peerSectionCount: Int { return tunnelViewModel.peersData.count } + + init(tunnelsManager: TunnelsManager, tunnel: TunnelContainer) { // Use this initializer to edit an existing tunnel. - tunnelsManager = tm - tunnel = t - tunnelViewModel = TunnelViewModel(tunnelConfiguration: t.tunnelConfiguration()) - activateOnDemandSetting = t.activateOnDemandSetting() + self.tunnelsManager = tunnelsManager + self.tunnel = tunnel + tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnel.tunnelConfiguration()) + activateOnDemandSetting = tunnel.activateOnDemandSetting() super.init(style: .grouped) } - init(tunnelsManager tm: TunnelsManager, tunnelConfiguration: TunnelConfiguration?) { + init(tunnelsManager: TunnelsManager, tunnelConfiguration: TunnelConfiguration?) { // Use this initializer to create a new tunnel. // If tunnelConfiguration is passed, data will be prepopulated from that configuration. - tunnelsManager = tm + self.tunnelsManager = tunnelsManager tunnel = nil tunnelViewModel = TunnelViewModel(tunnelConfiguration: tunnelConfiguration) activateOnDemandSetting = ActivateOnDemandSetting.defaultSetting @@ -62,18 +65,18 @@ class TunnelEditTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() - self.title = (tunnel == nil) ? "New configuration" : "Edit configuration" + self.title = tunnel == nil ? "New configuration" : "Edit configuration" self.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(saveTapped)) self.navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancelTapped)) self.tableView.estimatedRowHeight = 44 self.tableView.rowHeight = UITableView.automaticDimension - self.tableView.register(TunnelEditTableViewKeyValueCell.self, forCellReuseIdentifier: TunnelEditTableViewKeyValueCell.id) - self.tableView.register(TunnelEditTableViewReadOnlyKeyValueCell.self, forCellReuseIdentifier: TunnelEditTableViewReadOnlyKeyValueCell.id) - self.tableView.register(TunnelEditTableViewButtonCell.self, forCellReuseIdentifier: TunnelEditTableViewButtonCell.id) - self.tableView.register(TunnelEditTableViewSwitchCell.self, forCellReuseIdentifier: TunnelEditTableViewSwitchCell.id) - self.tableView.register(TunnelEditTableViewSelectionListCell.self, forCellReuseIdentifier: TunnelEditTableViewSelectionListCell.id) + self.tableView.register(TunnelEditTableViewKeyValueCell.self, forCellReuseIdentifier: TunnelEditTableViewKeyValueCell.reuseIdentifier) + self.tableView.register(TunnelEditTableViewReadOnlyKeyValueCell.self, forCellReuseIdentifier: TunnelEditTableViewReadOnlyKeyValueCell.reuseIdentifier) + self.tableView.register(TunnelEditTableViewButtonCell.self, forCellReuseIdentifier: TunnelEditTableViewButtonCell.reuseIdentifier) + self.tableView.register(TunnelEditTableViewSwitchCell.self, forCellReuseIdentifier: TunnelEditTableViewSwitchCell.reuseIdentifier) + self.tableView.register(TunnelEditTableViewSelectionListCell.self, forCellReuseIdentifier: TunnelEditTableViewSelectionListCell.reuseIdentifier) } @objc func saveTapped() { @@ -123,26 +126,20 @@ class TunnelEditTableViewController: UITableViewController { extension TunnelEditTableViewController { override func numberOfSections(in tableView: UITableView) -> Int { - let numberOfInterfaceSections = interfaceFieldsBySection.count - let numberOfPeerSections = tunnelViewModel.peersData.count - - return numberOfInterfaceSections + numberOfPeerSections + 1 /* Add Peer */ + 1 /* On-Demand */ + return interfaceSectionCount + peerSectionCount + 1 /* Add Peer */ + 1 /* On-Demand */ } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - let numberOfInterfaceSections = interfaceFieldsBySection.count - let numberOfPeerSections = tunnelViewModel.peersData.count - - if (section < numberOfInterfaceSections) { + if (section < interfaceSectionCount) { // Interface return interfaceFieldsBySection[section].count - } else if ((numberOfPeerSections > 0) && (section < (numberOfInterfaceSections + numberOfPeerSections))) { + } else if ((peerSectionCount > 0) && (section < (interfaceSectionCount + peerSectionCount))) { // Peer - let peerIndex = (section - numberOfInterfaceSections) + let peerIndex = (section - interfaceSectionCount) let peerData = tunnelViewModel.peersData[peerIndex] let peerFieldsToShow = peerData.shouldAllowExcludePrivateIPsControl ? peerFields : peerFields.filter { $0 != .excludePrivateIPs } return peerFieldsToShow.count - } else if (section < (numberOfInterfaceSections + numberOfPeerSections + 1)) { + } else if (section < (interfaceSectionCount + peerSectionCount + 1)) { // Add peer return 1 } else { @@ -156,284 +153,279 @@ extension TunnelEditTableViewController { } override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? { - let numberOfInterfaceSections = interfaceFieldsBySection.count - let numberOfPeerSections = tunnelViewModel.peersData.count - - if (section < numberOfInterfaceSections) { + if (section < interfaceSectionCount) { // Interface return (section == 0) ? "Interface" : nil - } else if ((numberOfPeerSections > 0) && (section < (numberOfInterfaceSections + numberOfPeerSections))) { + } else if ((peerSectionCount > 0) && (section < (interfaceSectionCount + peerSectionCount))) { // Peer return "Peer" - } else if (section == (numberOfInterfaceSections + numberOfPeerSections)) { + } else if (section == (interfaceSectionCount + peerSectionCount)) { // Add peer return nil } else { - assert(section == (numberOfInterfaceSections + numberOfPeerSections + 1)) + assert(section == (interfaceSectionCount + peerSectionCount + 1)) return "On-Demand Activation" } } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { - let numberOfInterfaceSections = interfaceFieldsBySection.count - let numberOfPeerSections = tunnelViewModel.peersData.count - - let section = indexPath.section - let row = indexPath.row + if (indexPath.section < interfaceSectionCount) { + return interfaceFieldCell(for: tableView, at: indexPath) + } else if ((peerSectionCount > 0) && (indexPath.section < (interfaceSectionCount + peerSectionCount))) { + return peerCell(for: tableView, at: indexPath) + } else if (indexPath.section == (interfaceSectionCount + peerSectionCount)) { + return addPeerCell(for: tableView, at: indexPath) + } else { + return onDemandCell(for: tableView, at: indexPath) + } + } - if (section < numberOfInterfaceSections) { - // Interface - let interfaceData = tunnelViewModel.interfaceData - let field = interfaceFieldsBySection[section][row] - if (field == .generateKeyPair) { - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewButtonCell.id, for: indexPath) as! TunnelEditTableViewButtonCell - cell.buttonText = field.rawValue - cell.onTapped = { [weak self, weak interfaceData] in - if let interfaceData = interfaceData, let s = self { - interfaceData[.privateKey] = Curve25519.generatePrivateKey().base64EncodedString() - if let privateKeyRow = s.interfaceFieldsBySection[section].firstIndex(of: .privateKey), - let publicKeyRow = s.interfaceFieldsBySection[section].firstIndex(of: .publicKey) { - let privateKeyIndex = IndexPath(row: privateKeyRow, section: section) - let publicKeyIndex = IndexPath(row: publicKeyRow, section: section) - s.tableView.reloadRows(at: [privateKeyIndex, publicKeyIndex], with: .automatic) - } + private func interfaceFieldCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { + let interfaceData = tunnelViewModel.interfaceData + let field = interfaceFieldsBySection[indexPath.section][indexPath.row] + if (field == .generateKeyPair) { + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewButtonCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewButtonCell + cell.buttonText = field.rawValue + cell.onTapped = { [weak self, weak interfaceData] in + if let interfaceData = interfaceData, let self = self { + interfaceData[.privateKey] = Curve25519.generatePrivateKey().base64EncodedString() + if let privateKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .privateKey), + let publicKeyRow = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .publicKey) { + let privateKeyIndex = IndexPath(row: privateKeyRow, section: indexPath.section) + let publicKeyIndex = IndexPath(row: publicKeyRow, section: indexPath.section) + self.tableView.reloadRows(at: [privateKeyIndex, publicKeyIndex], with: .automatic) } } - return cell - } else if (field == .publicKey) { - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewReadOnlyKeyValueCell.id, for: indexPath) as! TunnelEditTableViewReadOnlyKeyValueCell - cell.key = field.rawValue - cell.value = interfaceData[field] - return cell - } else { - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewKeyValueCell.id, for: indexPath) as! TunnelEditTableViewKeyValueCell - // Set key - cell.key = field.rawValue - // Set placeholder text - switch (field) { - case .name: - cell.placeholderText = "Required" - case .privateKey: - cell.placeholderText = "Required" - case .addresses: - cell.placeholderText = "Optional" - case .listenPort: - cell.placeholderText = "Automatic" - case .mtu: - cell.placeholderText = "Automatic" - case .dns: - cell.placeholderText = "Optional" - case .publicKey: break - case .generateKeyPair: break - } - // Set keyboardType - if (field == .mtu || field == .listenPort) { - cell.keyboardType = .numberPad - } else if (field == .addresses || field == .dns) { - cell.keyboardType = .numbersAndPunctuation + } + return cell + } else if field == .publicKey { + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewReadOnlyKeyValueCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewReadOnlyKeyValueCell + cell.key = field.rawValue + cell.value = interfaceData[field] + return cell + } else { + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewKeyValueCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewKeyValueCell + // Set key + cell.key = field.rawValue + // Set placeholder text + switch field { + case .name: + cell.placeholderText = "Required" + case .privateKey: + cell.placeholderText = "Required" + case .addresses: + cell.placeholderText = "Optional" + case .listenPort: + cell.placeholderText = "Automatic" + case .mtu: + cell.placeholderText = "Automatic" + case .dns: + cell.placeholderText = "Optional" + case .publicKey: break + case .generateKeyPair: break + } + // Set keyboardType + if field == .mtu || field == .listenPort { + cell.keyboardType = .numberPad + } else if field == .addresses || field == .dns { + cell.keyboardType = .numbersAndPunctuation + } + // Show erroring fields + cell.isValueValid = (!interfaceData.fieldsWithError.contains(field)) + // Bind values to view model + cell.value = interfaceData[field] + if field == .dns { // While editing DNS, you might directly set exclude private IPs + cell.onValueBeingEdited = { [weak interfaceData] value in + interfaceData?[field] = value } - // Show erroring fields - cell.isValueValid = (!interfaceData.fieldsWithError.contains(field)) - // Bind values to view model - cell.value = interfaceData[field] - if (field == .dns) { // While editing DNS, you might directly set exclude private IPs - cell.onValueBeingEdited = { [weak interfaceData] value in - interfaceData?[field] = value - } - } else { - cell.onValueChanged = { [weak interfaceData] value in - interfaceData?[field] = value - } + } else { + cell.onValueChanged = { [weak interfaceData] value in + interfaceData?[field] = value } - // Compute public key live - if (field == .privateKey) { - cell.onValueBeingEdited = { [weak self, weak interfaceData] value in - if let interfaceData = interfaceData, let s = self { - interfaceData[.privateKey] = value - if let row = s.interfaceFieldsBySection[section].firstIndex(of: .publicKey) { - s.tableView.reloadRows(at: [IndexPath(row: row, section: section)], with: .none) - } + } + // Compute public key live + if field == .privateKey { + cell.onValueBeingEdited = { [weak self, weak interfaceData] value in + if let interfaceData = interfaceData, let self = self { + interfaceData[.privateKey] = value + if let row = self.interfaceFieldsBySection[indexPath.section].firstIndex(of: .publicKey) { + self.tableView.reloadRows(at: [IndexPath(row: row, section: indexPath.section)], with: .none) } } } - return cell } - } else if ((numberOfPeerSections > 0) && (section < (numberOfInterfaceSections + numberOfPeerSections))) { - // Peer - let peerIndex = (section - numberOfInterfaceSections) - let peerData = tunnelViewModel.peersData[peerIndex] - let peerFieldsToShow = peerData.shouldAllowExcludePrivateIPsControl ? peerFields : peerFields.filter { $0 != .excludePrivateIPs } - let field = peerFieldsToShow[row] - if (field == .deletePeer) { - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewButtonCell.id, for: indexPath) as! TunnelEditTableViewButtonCell - cell.buttonText = field.rawValue - cell.hasDestructiveAction = true - cell.onTapped = { [weak self, weak peerData] in - guard let peerData = peerData else { return } - guard let s = self else { return } - s.showConfirmationAlert(message: "Delete this peer?", - buttonTitle: "Delete", from: cell, - onConfirmed: { [weak s] in - guard let s = s else { return } - let removedSectionIndices = s.deletePeer(peer: peerData) - let shouldShowExcludePrivateIPs = (s.tunnelViewModel.peersData.count == 1 && - s.tunnelViewModel.peersData[0].shouldAllowExcludePrivateIPsControl) - tableView.performBatchUpdates({ - s.tableView.deleteSections(removedSectionIndices, with: .automatic) - if (shouldShowExcludePrivateIPs) { - if let row = s.peerFields.firstIndex(of: .excludePrivateIPs) { - let rowIndexPath = IndexPath(row: row, section: numberOfInterfaceSections /* First peer section */) - s.tableView.insertRows(at: [rowIndexPath], with: .automatic) - } - - } - }) + return cell + } + } + + private func peerCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { + let peerIndex = indexPath.section - interfaceFieldsBySection.count + let peerData = tunnelViewModel.peersData[peerIndex] + let peerFieldsToShow = peerData.shouldAllowExcludePrivateIPsControl ? peerFields : peerFields.filter { $0 != .excludePrivateIPs } + let field = peerFieldsToShow[indexPath.row] + if field == .deletePeer { + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewButtonCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewButtonCell + cell.buttonText = field.rawValue + cell.hasDestructiveAction = true + cell.onTapped = { [weak self, weak peerData] in + guard let peerData = peerData else { return } + guard let self = self else { return } + self.showConfirmationAlert(message: "Delete this peer?", buttonTitle: "Delete", from: cell) { [weak self] in + guard let self = self else { return } + let removedSectionIndices = self.deletePeer(peer: peerData) + let shouldShowExcludePrivateIPs = (self.tunnelViewModel.peersData.count == 1 && self.tunnelViewModel.peersData[0].shouldAllowExcludePrivateIPsControl) + tableView.performBatchUpdates({ + self.tableView.deleteSections(removedSectionIndices, with: .automatic) + if shouldShowExcludePrivateIPs { + if let row = self.peerFields.firstIndex(of: .excludePrivateIPs) { + let rowIndexPath = IndexPath(row: row, section: self.interfaceFieldsBySection.count /* First peer section */) + self.tableView.insertRows(at: [rowIndexPath], with: .automatic) + } + + } }) } - return cell - } else if (field == .excludePrivateIPs) { - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewSwitchCell.id, for: indexPath) as! TunnelEditTableViewSwitchCell - cell.message = field.rawValue - cell.isEnabled = peerData.shouldAllowExcludePrivateIPsControl - cell.isOn = peerData.excludePrivateIPsValue - cell.onSwitchToggled = { [weak self] (isOn) in - guard let s = self else { return } - peerData.excludePrivateIPsValueChanged(isOn: isOn, dnsServers: s.tunnelViewModel.interfaceData[.dns]) - if let row = s.peerFields.firstIndex(of: .allowedIPs) { - s.tableView.reloadRows(at: [IndexPath(row: row, section: section)], with: .none) - } - } - return cell - } else { - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewKeyValueCell.id, for: indexPath) as! TunnelEditTableViewKeyValueCell - // Set key - cell.key = field.rawValue - // Set placeholder text - switch (field) { - case .publicKey: - cell.placeholderText = "Required" - case .preSharedKey: - cell.placeholderText = "Optional" - case .endpoint: - cell.placeholderText = "Optional" - case .allowedIPs: - cell.placeholderText = "Optional" - case .persistentKeepAlive: - cell.placeholderText = "Off" - case .excludePrivateIPs: break - case .deletePeer: break - } - // Set keyboardType - if (field == .persistentKeepAlive) { - cell.keyboardType = .numberPad - } else if (field == .allowedIPs) { - cell.keyboardType = .numbersAndPunctuation + } + return cell + } else if field == .excludePrivateIPs { + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewSwitchCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewSwitchCell + cell.message = field.rawValue + cell.isEnabled = peerData.shouldAllowExcludePrivateIPsControl + cell.isOn = peerData.excludePrivateIPsValue + cell.onSwitchToggled = { [weak self] (isOn) in + guard let self = self else { return } + peerData.excludePrivateIPsValueChanged(isOn: isOn, dnsServers: self.tunnelViewModel.interfaceData[.dns]) + if let row = self.peerFields.firstIndex(of: .allowedIPs) { + self.tableView.reloadRows(at: [IndexPath(row: row, section: indexPath.section)], with: .none) } - // Show erroring fields - cell.isValueValid = (!peerData.fieldsWithError.contains(field)) - // Bind values to view model - cell.value = peerData[field] - if (field != .allowedIPs) { - cell.onValueChanged = { [weak peerData] value in - peerData?[field] = value - } + } + return cell + } else { + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewKeyValueCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewKeyValueCell + // Set key + cell.key = field.rawValue + // Set placeholder text + switch field { + case .publicKey: + cell.placeholderText = "Required" + case .preSharedKey: + cell.placeholderText = "Optional" + case .endpoint: + cell.placeholderText = "Optional" + case .allowedIPs: + cell.placeholderText = "Optional" + case .persistentKeepAlive: + cell.placeholderText = "Off" + case .excludePrivateIPs: break + case .deletePeer: break + } + // Set keyboardType + if field == .persistentKeepAlive { + cell.keyboardType = .numberPad + } else if field == .allowedIPs { + cell.keyboardType = .numbersAndPunctuation + } + // Show erroring fields + cell.isValueValid = (!peerData.fieldsWithError.contains(field)) + // Bind values to view model + 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 s = self { - let oldValue = peerData.shouldAllowExcludePrivateIPsControl - peerData[.allowedIPs] = value - if (oldValue != peerData.shouldAllowExcludePrivateIPsControl) { - if let row = s.peerFields.firstIndex(of: .excludePrivateIPs) { - if (peerData.shouldAllowExcludePrivateIPsControl) { - s.tableView.insertRows(at: [IndexPath(row: row, section: section)], with: .automatic) - } else { - s.tableView.deleteRows(at: [IndexPath(row: row, section: section)], with: .automatic) - } + } + // 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: .automatic) + } else { + self.tableView.deleteRows(at: [IndexPath(row: row, section: indexPath.section)], with: .automatic) } } } } } - return cell - } - } else if (section == (numberOfInterfaceSections + numberOfPeerSections)) { - // Add peer - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewButtonCell.id, for: indexPath) as! TunnelEditTableViewButtonCell - cell.buttonText = "Add peer" - cell.onTapped = { [weak self] in - guard let s = self else { return } - let shouldHideExcludePrivateIPs = (s.tunnelViewModel.peersData.count == 1 && - s.tunnelViewModel.peersData[0].shouldAllowExcludePrivateIPsControl) - let addedSectionIndices = s.appendEmptyPeer() - tableView.performBatchUpdates({ - tableView.insertSections(addedSectionIndices, with: .automatic) - if (shouldHideExcludePrivateIPs) { - if let row = s.peerFields.firstIndex(of: .excludePrivateIPs) { - let rowIndexPath = IndexPath(row: row, section: numberOfInterfaceSections /* First peer section */) - s.tableView.deleteRows(at: [rowIndexPath], with: .automatic) - } - } - }, completion: nil) } return cell - } else { - assert(section == (numberOfInterfaceSections + numberOfPeerSections + 1)) - if (row == 0) { - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewSwitchCell.id, for: indexPath) as! TunnelEditTableViewSwitchCell - cell.message = "Activate on demand" - cell.isOn = activateOnDemandSetting.isActivateOnDemandEnabled - cell.onSwitchToggled = { [weak self] (isOn) in - guard let s = self else { return } - let indexPaths: [IndexPath] = (1 ..< 4).map { IndexPath(row: $0, section: section) } - if (isOn) { - s.activateOnDemandSetting.isActivateOnDemandEnabled = true - if (s.activateOnDemandSetting.activateOnDemandOption == .none) { - s.activateOnDemandSetting.activateOnDemandOption = TunnelViewModel.defaultActivateOnDemandOption() - } - s.tableView.insertRows(at: indexPaths, with: .automatic) - } else { - s.activateOnDemandSetting.isActivateOnDemandEnabled = false - s.tableView.deleteRows(at: indexPaths, with: .automatic) + } + } + + private func addPeerCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewButtonCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewButtonCell + cell.buttonText = "Add peer" + cell.onTapped = { [weak self] in + guard let self = self else { return } + let shouldHideExcludePrivateIPs = (self.tunnelViewModel.peersData.count == 1 && self.tunnelViewModel.peersData[0].shouldAllowExcludePrivateIPsControl) + let addedSectionIndices = self.appendEmptyPeer() + tableView.performBatchUpdates({ + tableView.insertSections(addedSectionIndices, with: .automatic) + if shouldHideExcludePrivateIPs { + if let row = self.peerFields.firstIndex(of: .excludePrivateIPs) { + let rowIndexPath = IndexPath(row: row, section: self.interfaceFieldsBySection.count /* First peer section */) + self.tableView.deleteRows(at: [rowIndexPath], with: .automatic) } } - return cell - } else { - assert(row < 4) - let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewSelectionListCell.id, for: indexPath) as! TunnelEditTableViewSelectionListCell - let rowOption = activateOnDemandOptions[row - 1] - let selectedOption = activateOnDemandSetting.activateOnDemandOption - assert(selectedOption != .none) - cell.message = TunnelViewModel.activateOnDemandOptionText(for: rowOption) - cell.isChecked = (selectedOption == rowOption) - return cell + }, completion: nil) + } + return cell + } + + private func onDemandCell(for tableView: UITableView, at indexPath: IndexPath) -> UITableViewCell { + assert(indexPath.section == interfaceSectionCount + peerSectionCount + 1) + if indexPath.row == 0 { + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewSwitchCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewSwitchCell + cell.message = "Activate on demand" + 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) } + if isOn { + self.activateOnDemandSetting.isActivateOnDemandEnabled = true + if self.activateOnDemandSetting.activateOnDemandOption == .none { + self.activateOnDemandSetting.activateOnDemandOption = TunnelViewModel.defaultActivateOnDemandOption() + } + self.tableView.insertRows(at: indexPaths, with: .automatic) + } else { + self.activateOnDemandSetting.isActivateOnDemandEnabled = false + self.tableView.deleteRows(at: indexPaths, with: .automatic) + } } + return cell + } else { + assert(indexPath.row < 4) + let cell = tableView.dequeueReusableCell(withIdentifier: TunnelEditTableViewSelectionListCell.reuseIdentifier, for: indexPath) as! TunnelEditTableViewSelectionListCell + let rowOption = activateOnDemandOptions[indexPath.row - 1] + let selectedOption = activateOnDemandSetting.activateOnDemandOption + assert(selectedOption != .none) + cell.message = TunnelViewModel.activateOnDemandOptionText(for: rowOption) + cell.isChecked = (selectedOption == rowOption) + return cell } } func appendEmptyPeer() -> IndexSet { - let numberOfInterfaceSections = interfaceFieldsBySection.count - tunnelViewModel.appendEmptyPeer() let addedPeerIndex = tunnelViewModel.peersData.count - 1 - let addedSectionIndices = IndexSet(integer: (numberOfInterfaceSections + addedPeerIndex)) + let addedSectionIndices = IndexSet(integer: interfaceSectionCount + addedPeerIndex) return addedSectionIndices } func deletePeer(peer: TunnelViewModel.PeerData) -> IndexSet { - let numberOfInterfaceSections = interfaceFieldsBySection.count - assert(peer.index < tunnelViewModel.peersData.count) tunnelViewModel.deletePeer(peer: peer) - let removedSectionIndices = IndexSet(integer: (numberOfInterfaceSections + peer.index)) + let removedSectionIndices = IndexSet(integer: (interfaceSectionCount + peer.index)) return removedSectionIndices } - func showConfirmationAlert(message: String, buttonTitle: String, from sourceView: UIView, - onConfirmed: @escaping (() -> Void)) { + func showConfirmationAlert(message: String, buttonTitle: String, from sourceView: UIView, onConfirmed: @escaping (() -> Void)) { let destroyAction = UIAlertAction(title: buttonTitle, style: .destructive) { (_) in onConfirmed() } @@ -454,27 +446,18 @@ extension TunnelEditTableViewController { extension TunnelEditTableViewController { override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? { - let numberOfInterfaceSections = interfaceFieldsBySection.count - let numberOfPeerSections = tunnelViewModel.peersData.count - - let section = indexPath.section - let row = indexPath.row - - if (section == (numberOfInterfaceSections + numberOfPeerSections + 1)) { - return (row > 0) ? indexPath : nil + if indexPath.section == (interfaceSectionCount + peerSectionCount + 1) { + return (indexPath.row > 0) ? indexPath : nil } else { return nil } } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { - let numberOfInterfaceSections = interfaceFieldsBySection.count - let numberOfPeerSections = tunnelViewModel.peersData.count - let section = indexPath.section let row = indexPath.row - assert(section == (numberOfInterfaceSections + numberOfPeerSections + 1)) + assert(section == (interfaceSectionCount + peerSectionCount + 1)) assert(row > 0) let option = activateOnDemandOptions[row - 1] @@ -487,7 +470,7 @@ extension TunnelEditTableViewController { } class TunnelEditTableViewKeyValueCell: UITableViewCell { - static let id: String = "TunnelEditTableViewKeyValueCell" + static let reuseIdentifier = "TunnelEditTableViewKeyValueCell" var key: String { get { return keyLabel.text ?? "" } set(value) {keyLabel.text = value } @@ -502,7 +485,7 @@ class TunnelEditTableViewKeyValueCell: UITableViewCell { } var isValueValid: Bool = true { didSet { - if (isValueValid) { + if isValueValid { keyLabel.textColor = UIColor.black } else { keyLabel.textColor = UIColor.red @@ -584,7 +567,7 @@ class TunnelEditTableViewKeyValueCell: UITableViewCell { constraints = [ contentView.layoutMarginsGuide.bottomAnchor.constraint(equalToSystemSpacingBelow: keyLabel.bottomAnchor, multiplier: 0.5), valueTextField.leftAnchor.constraint(equalToSystemSpacingAfter: keyLabel.rightAnchor, multiplier: 1), - valueTextField.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 0.5), + valueTextField.topAnchor.constraint(equalToSystemSpacingBelow: contentView.layoutMarginsGuide.topAnchor, multiplier: 0.5) ] isStackedHorizontally = true isStackedVertically = false @@ -636,7 +619,7 @@ extension TunnelEditTableViewKeyValueCell: UITextFieldDelegate { } class TunnelEditTableViewReadOnlyKeyValueCell: CopyableLabelTableViewCell { - static let id: String = "TunnelEditTableViewReadOnlyKeyValueCell" + static let reuseIdentifier = "TunnelEditTableViewReadOnlyKeyValueCell" var key: String { get { return keyLabel.text ?? "" } set(value) {keyLabel.text = value } @@ -684,7 +667,7 @@ class TunnelEditTableViewReadOnlyKeyValueCell: CopyableLabelTableViewCell { NSLayoutConstraint.activate([ valueLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor), valueLabel.leftAnchor.constraint(equalToSystemSpacingAfter: keyLabel.rightAnchor, multiplier: 1), - valueLabel.rightAnchor.constraint(equalTo: contentView.layoutMarginsGuide.rightAnchor), + valueLabel.rightAnchor.constraint(equalTo: contentView.layoutMarginsGuide.rightAnchor) ]) } @@ -704,7 +687,7 @@ class TunnelEditTableViewReadOnlyKeyValueCell: CopyableLabelTableViewCell { } class TunnelEditTableViewButtonCell: UITableViewCell { - static let id: String = "TunnelEditTableViewButtonCell" + static let reuseIdentifier = "TunnelEditTableViewButtonCell" var buttonText: String { get { return button.title(for: .normal) ?? "" } set(value) { button.setTitle(value, for: .normal) } @@ -751,7 +734,7 @@ class TunnelEditTableViewButtonCell: UITableViewCell { } class TunnelEditTableViewSwitchCell: UITableViewCell { - static let id: String = "TunnelEditTableViewSwitchCell" + static let reuseIdentifier = "TunnelEditTableViewSwitchCell" var message: String { get { return textLabel?.text ?? "" } set(value) { textLabel!.text = value } @@ -796,7 +779,7 @@ class TunnelEditTableViewSwitchCell: UITableViewCell { } class TunnelEditTableViewSelectionListCell: UITableViewCell { - static let id: String = "TunnelEditTableViewSelectionListCell" + static let reuseIdentifier = "TunnelEditTableViewSelectionListCell" var message: String { get { return textLabel?.text ?? "" } set(value) { textLabel!.text = value } diff --git a/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift index 66c4452..07fbee4 100644 --- a/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift +++ b/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift @@ -116,8 +116,8 @@ class TunnelsListTableViewController: UIViewController { alert.addAction(scanQRCodeAction) let createFromScratchAction = UIAlertAction(title: "Create from scratch", style: .default) { [weak self] (_) in - if let s = self, let tunnelsManager = s.tunnelsManager { - s.presentViewControllerForTunnelCreation(tunnelsManager: tunnelsManager, tunnelConfiguration: nil) + if let self = self, let tunnelsManager = self.tunnelsManager { + self.presentViewControllerForTunnelCreation(tunnelsManager: tunnelsManager, tunnelConfiguration: nil) } } alert.addAction(createFromScratchAction) @@ -246,11 +246,11 @@ extension TunnelsListTableViewController: UITableViewDataSource { let tunnel = tunnelsManager.tunnel(at: indexPath.row) cell.tunnel = tunnel cell.onSwitchToggled = { [weak self] isOn in - guard let s = self, let tunnelsManager = s.tunnelsManager else { return } + guard let self = self, let tunnelsManager = self.tunnelsManager else { return } if (isOn) { - tunnelsManager.startActivation(of: tunnel) { [weak s] error in + tunnelsManager.startActivation(of: tunnel) { [weak self] error in if let error = error { - ErrorPresenter.showErrorAlert(error: error, from: s, onPresented: { + ErrorPresenter.showErrorAlert(error: error, from: self, onPresented: { DispatchQueue.main.async { cell.statusSwitch.isOn = false } diff --git a/WireGuard/WireGuard/VPN/TunnelsManager.swift b/WireGuard/WireGuard/VPN/TunnelsManager.swift index 222100d..f8819d4 100644 --- a/WireGuard/WireGuard/VPN/TunnelsManager.swift +++ b/WireGuard/WireGuard/VPN/TunnelsManager.swift @@ -118,11 +118,11 @@ class TunnelsManager { completionHandler(.failure(TunnelsManagerError.vpnSystemErrorOnAddTunnel)) return } - if let s = self { + if let self = self { let tunnel = TunnelContainer(tunnel: tunnelProviderManager) - s.tunnels.append(tunnel) - s.tunnels.sort { $0.name < $1.name } - s.tunnelsListDelegate?.tunnelAdded(at: s.tunnels.firstIndex(of: tunnel)!) + self.tunnels.append(tunnel) + self.tunnels.sort { $0.name < $1.name } + self.tunnelsListDelegate?.tunnelAdded(at: self.tunnels.firstIndex(of: tunnel)!) completionHandler(.success(tunnel)) } } @@ -175,14 +175,14 @@ class TunnelsManager { completionHandler(TunnelsManagerError.vpnSystemErrorOnModifyTunnel) return } - if let s = self { + if let self = self { if (isNameChanged) { - let oldIndex = s.tunnels.firstIndex(of: tunnel)! - s.tunnels.sort { $0.name < $1.name } - let newIndex = s.tunnels.firstIndex(of: tunnel)! - s.tunnelsListDelegate?.tunnelMoved(at: oldIndex, to: newIndex) + let oldIndex = self.tunnels.firstIndex(of: tunnel)! + self.tunnels.sort { $0.name < $1.name } + let newIndex = self.tunnels.firstIndex(of: tunnel)! + self.tunnelsListDelegate?.tunnelMoved(at: oldIndex, to: newIndex) } - s.tunnelsListDelegate?.tunnelModified(at: s.tunnels.firstIndex(of: tunnel)!) + self.tunnelsListDelegate?.tunnelModified(at: self.tunnels.firstIndex(of: tunnel)!) if (tunnel.status == .active || tunnel.status == .activating || tunnel.status == .reasserting) { // Turn off the tunnel, and then turn it back on, so the changes are made effective @@ -219,10 +219,10 @@ class TunnelsManager { completionHandler(TunnelsManagerError.vpnSystemErrorOnRemoveTunnel) return } - if let s = self { - let index = s.tunnels.firstIndex(of: tunnel)! - s.tunnels.remove(at: index) - s.tunnelsListDelegate?.tunnelRemoved(at: index) + if let self = self { + let index = self.tunnels.firstIndex(of: tunnel)! + self.tunnels.remove(at: index) + self.tunnelsListDelegate?.tunnelRemoved(at: index) } completionHandler(nil) } @@ -264,9 +264,7 @@ class TunnelsManager { } func refreshStatuses() { - for t in tunnels { - t.refreshStatus() - } + tunnels.forEach { $0.refreshStatus() } } private func startObservingTunnelStatuses() { @@ -275,24 +273,24 @@ class TunnelsManager { 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 } - guard let s = self 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 == s.tunnelBeingActivated) { + if (tunnel == self.tunnelBeingActivated) { if (session.status == .disconnected) { if (InternetReachability.currentStatus() == .notReachable) { let error = TunnelsManagerError.tunnelActivationFailedNoInternetConnection - s.activationDelegate?.tunnelActivationFailed(tunnel: tunnel, error: error) + self.activationDelegate?.tunnelActivationFailed(tunnel: tunnel, error: error) } - s.tunnelBeingActivated = nil + self.tunnelBeingActivated = nil } else if (session.status == .connected) { - s.tunnelBeingActivated = nil + self.tunnelBeingActivated = nil } } @@ -300,7 +298,7 @@ class TunnelsManager { if ((tunnel.status == .restarting) && (session.status == .disconnected || session.status == .disconnecting)) { // Don't change tunnel.status when disconnecting for a restart if (session.status == .disconnected) { - s.tunnelBeingActivated = tunnel + self.tunnelBeingActivated = tunnel tunnel.startActivation(completionHandler: { _ in }) } return @@ -387,7 +385,8 @@ class TunnelContainer: NSObject { } os_log("startActivation: Tunnel saved after re-enabling", log: OSLog.default, type: .info) os_log("startActivation: Invoking startActivation", log: OSLog.default, type: .debug) - self?.startActivation(recursionCount: recursionCount + 1, lastError: NEVPNError(NEVPNError.configurationUnknown), tunnelConfiguration: tunnelConfiguration, completionHandler: completionHandler) + self?.startActivation(recursionCount: recursionCount + 1, lastError: NEVPNError(NEVPNError.configurationUnknown), + tunnelConfiguration: tunnelConfiguration, completionHandler: completionHandler) } return } diff --git a/WireGuard/WireGuard/WireGuardResult.swift b/WireGuard/WireGuard/WireGuardResult.swift index 93fc4c2..92f73cd 100644 --- a/WireGuard/WireGuard/WireGuardResult.swift +++ b/WireGuard/WireGuard/WireGuardResult.swift @@ -2,27 +2,27 @@ // Copyright © 2018 WireGuard LLC. All Rights Reserved. enum WireGuardResult { - case success(T) - case failure(WireGuardAppError) + case success(_ value: T) + case failure(_ error: WireGuardAppError) var value: T? { switch (self) { - case .success(let v): return v - case .failure(_): return nil + case .success(let value): return value + case .failure: return nil } } var error: WireGuardAppError? { switch (self) { - case .success(_): return nil - case .failure(let e): return e + case .success: return nil + case .failure(let error): return error } } var isSuccess: Bool { switch (self) { - case .success(_): return true - case .failure(_): return false + case .success: return true + case .failure: return false } } } diff --git a/WireGuard/WireGuard/ZipArchive/ZipExporter.swift b/WireGuard/WireGuard/ZipArchive/ZipExporter.swift index 4f57613..f875e1b 100644 --- a/WireGuard/WireGuard/ZipArchive/ZipExporter.swift +++ b/WireGuard/WireGuard/ZipArchive/ZipExporter.swift @@ -16,7 +16,7 @@ enum ZipExporterError: WireGuardAppError { class ZipExporter { static func exportConfigFiles(tunnelConfigurations: [TunnelConfiguration], to url: URL, - completion: @escaping (WireGuardAppError?) -> Void) { + completion: @escaping (WireGuardAppError?) -> Void) { guard (!tunnelConfigurations.isEmpty) else { completion(ZipExporterError.noTunnelsToExport) diff --git a/WireGuard/WireGuard/ZipArchive/ZipImporter.swift b/WireGuard/WireGuard/ZipArchive/ZipImporter.swift index 6c1e3de..194dc0e 100644 --- a/WireGuard/WireGuard/ZipArchive/ZipImporter.swift +++ b/WireGuard/WireGuard/ZipArchive/ZipImporter.swift @@ -20,13 +20,13 @@ class ZipImporter { var unarchivedFiles: [(fileBaseName: String, contents: Data)] do { unarchivedFiles = try ZipArchive.unarchive(url: url, requiredFileExtensions: ["conf"]) - for (i, unarchivedFile) in unarchivedFiles.enumerated().reversed() { + for (index, unarchivedFile) in unarchivedFiles.enumerated().reversed() { let fileBaseName = unarchivedFile.fileBaseName let trimmedName = fileBaseName.trimmingCharacters(in: .whitespacesAndNewlines) if (!trimmedName.isEmpty) { - unarchivedFiles[i].fileBaseName = trimmedName + unarchivedFiles[index].fileBaseName = trimmedName } else { - unarchivedFiles.remove(at: i) + unarchivedFiles.remove(at: index) } } @@ -42,8 +42,8 @@ class ZipImporter { unarchivedFiles.sort { $0.fileBaseName < $1.fileBaseName } var configs = Array(repeating: nil, count: unarchivedFiles.count) - for (i, file) in unarchivedFiles.enumerated() { - if (i > 0 && file == unarchivedFiles[i - 1]) { + for (index, file) in unarchivedFiles.enumerated() { + if (index > 0 && file == unarchivedFiles[index - 1]) { continue } guard let fileContents = String(data: file.contents, encoding: .utf8) else { @@ -52,7 +52,7 @@ class ZipImporter { guard let tunnelConfig = try? WgQuickConfigFileParser.parse(fileContents, name: file.fileBaseName) else { continue } - configs[i] = tunnelConfig + configs[index] = tunnelConfig } DispatchQueue.main.async { completion(.success(configs)) } } diff --git a/WireGuard/WireGuardNetworkExtension/DNSResolver.swift b/WireGuard/WireGuardNetworkExtension/DNSResolver.swift index 0874fd9..8a9873f 100644 --- a/WireGuard/WireGuardNetworkExtension/DNSResolver.swift +++ b/WireGuard/WireGuardNetworkExtension/DNSResolver.swift @@ -28,13 +28,13 @@ class DNSResolver { } var resolvedEndpoints: [Endpoint?] = Array(repeating: nil, count: endpoints.count) - for (i, endpoint) in endpoints.enumerated() { + for (index, endpoint) in endpoints.enumerated() { guard let endpoint = endpoint else { continue } if (endpoint.hasHostAsIPAddress()) { - resolvedEndpoints[i] = endpoint + resolvedEndpoints[index] = endpoint } else { let workItem = DispatchWorkItem { - resolvedEndpoints[i] = DNSResolver.resolveSync(endpoint: endpoint) + resolvedEndpoints[index] = DNSResolver.resolveSync(endpoint: endpoint) } DispatchQueue.global(qos: .userInitiated).async(group: dispatchGroup, execute: workItem) } diff --git a/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift b/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift index 4087fe7..4723e79 100644 --- a/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift +++ b/WireGuard/WireGuardNetworkExtension/ErrorNotifier.swift @@ -8,7 +8,7 @@ class ErrorNotifier { switch (error) { case .savedProtocolConfigurationIsInvalid: return ("Activation failure", "Could not retrieve tunnel information from the saved configuration") - case .dnsResolutionFailure(_): + case .dnsResolutionFailure: return ("DNS resolution failure", "One or more endpoint domains could not be resolved") case .couldNotStartWireGuard: return ("Activation failure", "WireGuard backend could not be started") diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift index f5f0296..81a9520 100644 --- a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift +++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift @@ -21,7 +21,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { // MARK: Properties private var wgHandle: Int32? - + private var networkMonitor: NWPathMonitor? // MARK: NEPacketTunnelProvider @@ -29,7 +29,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { deinit { networkMonitor?.cancel() } - + /// Begin the process of establishing the tunnel. override func startTunnel(options: [String: NSObject]?, completionHandler startTunnelCompletionHandler: @escaping (Error?) -> Void) { @@ -89,9 +89,9 @@ class PacketTunnelProvider: NEPacketTunnelProvider { } let wireguardSettings = packetTunnelSettingsGenerator.uapiConfiguration() - + var handle: Int32 = -1 - + networkMonitor = NWPathMonitor() networkMonitor?.pathUpdateHandler = { path in guard handle >= 0 else { return } @@ -99,18 +99,18 @@ class PacketTunnelProvider: NEPacketTunnelProvider { wg_log(.debug, message: "Network change detected, re-establishing sockets and IPs: \(path.availableInterfaces)") let endpointString = packetTunnelSettingsGenerator.endpointUapiConfiguration(currentListenPort: wgGetListenPort(handle)) let err = endpointString.withCString { - wgSetConfig(handle, gostring_t(p: $0, n: endpointString.utf8.count)) + wgSetConfig(handle, gostring_t(p: $0, n: endpointString.utf8.count)) } if err == -EADDRINUSE { let endpointString = packetTunnelSettingsGenerator.endpointUapiConfiguration(currentListenPort: 0) _ = endpointString.withCString { - wgSetConfig(handle, gostring_t(p: $0, n: endpointString.utf8.count)) + wgSetConfig(handle, gostring_t(p: $0, n: endpointString.utf8.count)) } } } } networkMonitor?.start(queue: DispatchQueue(label: "NetworkMonitor")) - + handle = connect(interfaceName: tunnelConfiguration.interface.name, settings: wireguardSettings, fd: fd) if handle < 0 { @@ -141,7 +141,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider { override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { networkMonitor?.cancel() networkMonitor = nil - + wg_log(.info, staticMessage: "Stopping tunnel") if let handle = wgHandle { wgTurnOff(handle) diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift index 61e161e..f6bcdba 100644 --- a/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift +++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift @@ -18,17 +18,17 @@ class PacketTunnelSettingsGenerator { func endpointUapiConfiguration(currentListenPort: UInt16) -> String { var wgSettings = "listen_port=\(tunnelConfiguration.interface.listenPort ?? currentListenPort)\n" - for (i, peer) in tunnelConfiguration.peers.enumerated() { + for (index, peer) in tunnelConfiguration.peers.enumerated() { wgSettings.append("public_key=\(peer.publicKey.hexEncodedString())\n") - if let endpoint = resolvedEndpoints[i] { + if let endpoint = resolvedEndpoints[index] { if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") } wgSettings.append("endpoint=\(endpoint.stringRepresentation())\n") } } - + return wgSettings } - + func uapiConfiguration() -> String { var wgSettings = "" let privateKey = tunnelConfiguration.interface.privateKey.hexEncodedString() @@ -40,12 +40,12 @@ class PacketTunnelSettingsGenerator { wgSettings.append("replace_peers=true\n") } assert(tunnelConfiguration.peers.count == resolvedEndpoints.count) - for (i, peer) in tunnelConfiguration.peers.enumerated() { + for (index, peer) in tunnelConfiguration.peers.enumerated() { wgSettings.append("public_key=\(peer.publicKey.hexEncodedString())\n") if let preSharedKey = peer.preSharedKey { wgSettings.append("preshared_key=\(preSharedKey.hexEncodedString())\n") } - if let endpoint = resolvedEndpoints[i] { + if let endpoint = resolvedEndpoints[index] { if case .name(_, _) = endpoint.host { assert(false, "Endpoint is not resolved") } wgSettings.append("endpoint=\(endpoint.stringRepresentation())\n") } @@ -200,10 +200,10 @@ class PacketTunnelSettingsGenerator { } static func ipv4SubnetMaskString(of addressRange: IPAddressRange) -> String { - let n: UInt8 = addressRange.networkPrefixLength - assert(n <= 32) + let length: UInt8 = addressRange.networkPrefixLength + assert(length <= 32) var octets: [UInt8] = [0, 0, 0, 0] - let subnetMask: UInt32 = n > 0 ? ~UInt32(0) << (32 - n) : UInt32(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) -- cgit v1.2.3-59-g8ed1b