aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Kuck <eric@bluelinelabs.com>2018-12-12 21:09:52 -0600
committerEric Kuck <eric@bluelinelabs.com>2018-12-12 21:09:52 -0600
commit8a916beb389f84e21ed1aaf0d246801cd6acd73c (patch)
tree59ad4609e551e3259a802591eba9346b16408873
parentMore linter warnings fixed, enabled more swiftlint rules, project cleanup (diff)
downloadwireguard-apple-8a916beb389f84e21ed1aaf0d246801cd6acd73c.tar.xz
wireguard-apple-8a916beb389f84e21ed1aaf0d246801cd6acd73c.zip
More formatting nits and cyclomatic complexity fixes
Signed-off-by: Eric Kuck <eric@bluelinelabs.com>
-rw-r--r--WireGuard/.swiftlint.yml1
-rw-r--r--WireGuard/Shared/Model/Configuration.swift6
-rw-r--r--WireGuard/Shared/Model/IPAddressRange.swift4
-rw-r--r--WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift14
-rw-r--r--WireGuard/WireGuard/UI/TunnelViewModel.swift34
-rw-r--r--WireGuard/WireGuard/UI/iOS/ErrorPresenter.swift10
-rw-r--r--WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift8
-rw-r--r--WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift59
-rw-r--r--WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift2
-rw-r--r--WireGuard/WireGuard/VPN/TunnelsManager.swift71
-rw-r--r--WireGuard/WireGuard/WireGuardAppError.swift3
-rw-r--r--WireGuard/WireGuard/ZipArchive/ZipArchive.swift4
-rw-r--r--WireGuard/WireGuard/ZipArchive/ZipExporter.swift5
-rw-r--r--WireGuard/WireGuard/ZipArchive/ZipImporter.swift2
-rw-r--r--WireGuard/WireGuardNetworkExtension/DNSResolver.swift2
-rw-r--r--WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift5
-rw-r--r--WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift153
17 files changed, 166 insertions, 217 deletions
diff --git a/WireGuard/.swiftlint.yml b/WireGuard/.swiftlint.yml
index df6266a..2c414b6 100644
--- a/WireGuard/.swiftlint.yml
+++ b/WireGuard/.swiftlint.yml
@@ -1,6 +1,7 @@
disabled_rules:
- line_length
- trailing_whitespace
+ - todo
opt_in_rules:
- unneeded_parentheses_in_closure_argument
# - trailing_closure
diff --git a/WireGuard/Shared/Model/Configuration.swift b/WireGuard/Shared/Model/Configuration.swift
index 09fdd6b..77dfe97 100644
--- a/WireGuard/Shared/Model/Configuration.swift
+++ b/WireGuard/Shared/Model/Configuration.swift
@@ -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?
diff --git a/WireGuard/Shared/Model/IPAddressRange.swift b/WireGuard/Shared/Model/IPAddressRange.swift
index e3c1441..468e3aa 100644
--- a/WireGuard/Shared/Model/IPAddressRange.swift
+++ b/WireGuard/Shared/Model/IPAddressRange.swift
@@ -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 {
diff --git a/WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift b/WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift
index 138ca62..14a6dfb 100644
--- a/WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift
+++ b/WireGuard/WireGuard/ConfigFile/WgQuickConfigFileParser.swift
@@ -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 }
diff --git a/WireGuard/WireGuard/UI/TunnelViewModel.swift b/WireGuard/WireGuard/UI/TunnelViewModel.swift
index af7ff4c..80a6092 100644
--- a/WireGuard/WireGuard/UI/TunnelViewModel.swift
+++ b/WireGuard/WireGuard/UI/TunnelViewModel.swift
@@ -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 {
diff --git a/WireGuard/WireGuard/UI/iOS/ErrorPresenter.swift b/WireGuard/WireGuard/UI/iOS/ErrorPresenter.swift
index 7c28495..2889694 100644
--- a/WireGuard/WireGuard/UI/iOS/ErrorPresenter.swift
+++ b/WireGuard/WireGuard/UI/iOS/ErrorPresenter.swift
@@ -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?()
}
diff --git a/WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift
index e6ad024..c5816e8 100644
--- a/WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift
+++ b/WireGuard/WireGuard/UI/iOS/TunnelDetailTableViewController.swift
@@ -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 {
diff --git a/WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift
index b26992d..7cd96a2 100644
--- a/WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift
+++ b/WireGuard/WireGuard/UI/iOS/TunnelEditTableViewController.swift
@@ -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 {
diff --git a/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift b/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift
index e5d5af1..f24b452 100644
--- a/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift
+++ b/WireGuard/WireGuard/UI/iOS/TunnelsListTableViewController.swift
@@ -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?()
diff --git a/WireGuard/WireGuard/VPN/TunnelsManager.swift b/WireGuard/WireGuard/VPN/TunnelsManager.swift
index 9716eaf..9d48cdb 100644
--- a/WireGuard/WireGuard/VPN/TunnelsManager.swift
+++ b/WireGuard/WireGuard/VPN/TunnelsManager.swift
@@ -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()
}
}
diff --git a/WireGuard/WireGuard/WireGuardAppError.swift b/WireGuard/WireGuard/WireGuardAppError.swift
index 3e4707d..ba83ac5 100644
--- a/WireGuard/WireGuard/WireGuardAppError.swift
+++ b/WireGuard/WireGuard/WireGuardAppError.swift
@@ -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
}
diff --git a/WireGuard/WireGuard/ZipArchive/ZipArchive.swift b/WireGuard/WireGuard/ZipArchive/ZipArchive.swift
index 12cfb69..ad74d0e 100644
--- a/WireGuard/WireGuard/ZipArchive/ZipArchive.swift
+++ b/WireGuard/WireGuard/ZipArchive/ZipArchive.swift
@@ -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
diff --git a/WireGuard/WireGuard/ZipArchive/ZipExporter.swift b/WireGuard/WireGuard/ZipArchive/ZipExporter.swift
index b0e6b15..cdc9ac9 100644
--- a/WireGuard/WireGuard/ZipArchive/ZipExporter.swift
+++ b/WireGuard/WireGuard/ZipArchive/ZipExporter.swift
@@ -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)
diff --git a/WireGuard/WireGuard/ZipArchive/ZipImporter.swift b/WireGuard/WireGuard/ZipArchive/ZipImporter.swift
index e2767f2..523614b 100644
--- a/WireGuard/WireGuard/ZipArchive/ZipImporter.swift
+++ b/WireGuard/WireGuard/ZipArchive/ZipImporter.swift
@@ -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.")
diff --git a/WireGuard/WireGuardNetworkExtension/DNSResolver.swift b/WireGuard/WireGuardNetworkExtension/DNSResolver.swift
index 57093c8..9f85743 100644
--- a/WireGuard/WireGuardNetworkExtension/DNSResolver.swift
+++ b/WireGuard/WireGuardNetworkExtension/DNSResolver.swift
@@ -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
diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift
index b1571d5..5cac333 100644
--- a/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift
+++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelProvider.swift
@@ -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) {
diff --git a/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift b/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift
index 1e5ae8e..d97699d 100644
--- a/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift
+++ b/WireGuard/WireGuardNetworkExtension/PacketTunnelSettingsGenerator.swift
@@ -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 {