aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeroen Leenarts <jeroen.leenarts@gmail.com>2018-09-26 11:21:53 +0200
committerJeroen Leenarts <jeroen.leenarts@gmail.com>2018-09-26 11:21:53 +0200
commita55eefcd5d983d7252e0608255a85506ab96b7db (patch)
treeb5a1add2ac990239578b18eb71823213164a18c5
parentNot a gear but dots. (diff)
downloadwireguard-apple-a55eefcd5d983d7252e0608255a85506ab96b7db.tar.xz
wireguard-apple-a55eefcd5d983d7252e0608255a85506ab96b7db.zip
Fixe file/function related warnings.
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r--WireGuard.xcodeproj/project.pbxproj20
-rw-r--r--WireGuard/Coordinators/AppCoordinator+QRScanViewControllerDelegate.swift16
-rw-r--r--WireGuard/Coordinators/AppCoordinator+SettingsTableViewControllerDelegate.swift17
-rw-r--r--WireGuard/Coordinators/AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift11
-rw-r--r--WireGuard/Coordinators/AppCoordinator+TunnelInfoTableViewControllerDelegate.swift19
-rw-r--r--WireGuard/Coordinators/AppCoordinator+TunnelsTableViewControllerDelegate.swift196
-rw-r--r--WireGuard/Coordinators/AppCoordinator.swift227
7 files changed, 282 insertions, 224 deletions
diff --git a/WireGuard.xcodeproj/project.pbxproj b/WireGuard.xcodeproj/project.pbxproj
index 1542ffa..55956de 100644
--- a/WireGuard.xcodeproj/project.pbxproj
+++ b/WireGuard.xcodeproj/project.pbxproj
@@ -34,6 +34,11 @@
4A4BAD2320B6026900F12B28 /* Interface+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A4BAD1F20B6026900F12B28 /* Interface+CoreDataClass.swift */; };
4A61D82E20D98CE2006C7A76 /* WireGuardNetworkExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 4A61D82620D98CE1006C7A76 /* WireGuardNetworkExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4A61D83520D98D25006C7A76 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A61D83420D98D25006C7A76 /* NetworkExtension.framework */; };
+ 4A8A2296215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A2295215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift */; };
+ 4A8A2298215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A2297215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift */; };
+ 4A8A229A215B782E00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A2299215B782D00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift */; };
+ 4A8A229C215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A229B215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift */; };
+ 4A8A229E215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8A229D215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift */; };
4A8AABD820B6A79100B6D8C1 /* UITableView+WireGuard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4A8AABD720B6A79100B6D8C1 /* UITableView+WireGuard.swift */; };
4AADEA2B212616F7008C24FD /* String+Arrays.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5FA1D50F2124D80C00DBA2E6 /* String+Arrays.swift */; };
4ABF718E214D8B0300A1E0BF /* TunnelInfoTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4ABF718D214D8B0300A1E0BF /* TunnelInfoTableViewController.swift */; };
@@ -123,6 +128,11 @@
4A61D82B20D98CE2006C7A76 /* WireGuardNetworkExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WireGuardNetworkExtension.entitlements; sourceTree = "<group>"; };
4A61D83320D98D07006C7A76 /* WireGuard.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WireGuard.entitlements; sourceTree = "<group>"; };
4A61D83420D98D25006C7A76 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; };
+ 4A8A2295215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+QRScanViewControllerDelegate.swift"; sourceTree = "<group>"; };
+ 4A8A2297215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+SettingsTableViewControllerDelegate.swift"; sourceTree = "<group>"; };
+ 4A8A2299215B782D00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift"; sourceTree = "<group>"; };
+ 4A8A229B215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+TunnelsTableViewControllerDelegate.swift"; sourceTree = "<group>"; };
+ 4A8A229D215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppCoordinator+TunnelInfoTableViewControllerDelegate.swift"; sourceTree = "<group>"; };
4A8AABD720B6A79100B6D8C1 /* UITableView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+WireGuard.swift"; sourceTree = "<group>"; };
4ABF718D214D8B0300A1E0BF /* TunnelInfoTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelInfoTableViewController.swift; sourceTree = "<group>"; };
4ABFFE9D212D399F00107136 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; };
@@ -248,6 +258,11 @@
4A4BAD0D20B5F6C300F12B28 /* Coordinator.swift */,
4A4BAD0F20B5F6EC00F12B28 /* RootCoordinator.swift */,
4A4BAD0B20B5F6AA00F12B28 /* AppCoordinator.swift */,
+ 4A8A229D215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift */,
+ 4A8A229B215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift */,
+ 4A8A2295215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift */,
+ 4A8A2297215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift */,
+ 4A8A2299215B782D00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift */,
);
path = Coordinators;
sourceTree = "<group>";
@@ -585,16 +600,21 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 4A8A229A215B782E00736141 /* AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift in Sources */,
4A4BAD0C20B5F6AA00F12B28 /* AppCoordinator.swift in Sources */,
4A4BAD2220B6026900F12B28 /* Interface+CoreDataProperties.swift in Sources */,
+ 4A8A2298215B780600736141 /* AppCoordinator+SettingsTableViewControllerDelegate.swift in Sources */,
4AEAC32B20F14BA9007B67AB /* Log.swift in Sources */,
+ 4A8A229E215B793C00736141 /* AppCoordinator+TunnelInfoTableViewControllerDelegate.swift in Sources */,
4A4BAD1320B5F82400F12B28 /* Identifyable.swift in Sources */,
4A4BAD1720B5F8DE00F12B28 /* WireGuard.xcdatamodeld in Sources */,
5FCC4347212B3E2C009A9C58 /* Attribute.swift in Sources */,
4A4BAD1A20B5F8FF00F12B28 /* Tunnel+CoreDataClass.swift in Sources */,
4A4BACE820B5F1BF00F12B28 /* TunnelsTableViewController.swift in Sources */,
4A4BAD1020B5F6EC00F12B28 /* RootCoordinator.swift in Sources */,
+ 4A8A2296215B77D300736141 /* AppCoordinator+QRScanViewControllerDelegate.swift in Sources */,
4A4351592124956200261999 /* Validators.swift in Sources */,
+ 4A8A229C215B787E00736141 /* AppCoordinator+TunnelsTableViewControllerDelegate.swift in Sources */,
5FA1D4CB21249F7D00DBA2E6 /* Peer+Extension.swift in Sources */,
5FA1D5122124DA6400DBA2E6 /* String+Base64.swift in Sources */,
4AC5462E2116306F00749D21 /* Tunnel+Extension.swift in Sources */,
diff --git a/WireGuard/Coordinators/AppCoordinator+QRScanViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+QRScanViewControllerDelegate.swift
new file mode 100644
index 0000000..4e239d5
--- /dev/null
+++ b/WireGuard/Coordinators/AppCoordinator+QRScanViewControllerDelegate.swift
@@ -0,0 +1,16 @@
+//
+// Copyright © 2018 WireGuard LLC. All rights reserved.
+//
+
+import Foundation
+
+extension AppCoordinator: QRScanViewControllerDelegate {
+ func didSave(tunnel: Tunnel, qrScanViewController: QRScanViewController) {
+ qrScanViewController.navigationController?.popViewController(animated: true)
+ showTunnelInfoViewController(tunnel: tunnel, context: tunnel.managedObjectContext!)
+ }
+
+ func didCancel(qrScanViewController: QRScanViewController) {
+ qrScanViewController.navigationController?.popViewController(animated: true)
+ }
+}
diff --git a/WireGuard/Coordinators/AppCoordinator+SettingsTableViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+SettingsTableViewControllerDelegate.swift
new file mode 100644
index 0000000..0e09386
--- /dev/null
+++ b/WireGuard/Coordinators/AppCoordinator+SettingsTableViewControllerDelegate.swift
@@ -0,0 +1,17 @@
+//
+// Copyright © 2018 WireGuard LLC. All rights reserved.
+//
+
+import UIKit
+import PromiseKit
+import NetworkExtension
+
+enum GoVersionCoordinatorError: Error {
+ case noSession
+}
+
+extension AppCoordinator: SettingsTableViewControllerDelegate {
+ func exportTunnels(settingsTableViewController: SettingsTableViewController, sourceView: UIView) {
+ self.exportConfigs(sourceView: sourceView)
+ }
+}
diff --git a/WireGuard/Coordinators/AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift
new file mode 100644
index 0000000..0b96762
--- /dev/null
+++ b/WireGuard/Coordinators/AppCoordinator+TunnelConfigurationTableViewControllerDelegate.swift
@@ -0,0 +1,11 @@
+//
+// Copyright © 2018 WireGuard LLC. All rights reserved.
+//
+
+import Foundation
+
+extension AppCoordinator: TunnelConfigurationTableViewControllerDelegate {
+ func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) {
+ saveTunnel(tunnel)
+ }
+}
diff --git a/WireGuard/Coordinators/AppCoordinator+TunnelInfoTableViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+TunnelInfoTableViewControllerDelegate.swift
new file mode 100644
index 0000000..651cce5
--- /dev/null
+++ b/WireGuard/Coordinators/AppCoordinator+TunnelInfoTableViewControllerDelegate.swift
@@ -0,0 +1,19 @@
+//
+// Copyright © 2018 WireGuard LLC. All rights reserved.
+//
+
+import Foundation
+
+extension AppCoordinator: TunnelInfoTableViewControllerDelegate {
+ func configure(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) {
+ print("configure tunnel \(tunnel)")
+ let editContext = persistentContainer.newBackgroundContext()
+ var backgroundTunnel: Tunnel?
+ editContext.performAndWait {
+ backgroundTunnel = editContext.object(with: tunnel.objectID) as? Tunnel
+ }
+
+ showTunnelConfigurationViewController(tunnel: backgroundTunnel, context: editContext)
+ }
+
+}
diff --git a/WireGuard/Coordinators/AppCoordinator+TunnelsTableViewControllerDelegate.swift b/WireGuard/Coordinators/AppCoordinator+TunnelsTableViewControllerDelegate.swift
new file mode 100644
index 0000000..5506641
--- /dev/null
+++ b/WireGuard/Coordinators/AppCoordinator+TunnelsTableViewControllerDelegate.swift
@@ -0,0 +1,196 @@
+//
+// Copyright © 2018 WireGuard LLC. All rights reserved.
+//
+
+import UIKit
+import NetworkExtension
+import os.log
+
+import MobileCoreServices
+
+import ZIPFoundation
+import PromiseKit
+
+extension AppCoordinator: TunnelsTableViewControllerDelegate {
+ func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus {
+ let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession
+ return session?.status ?? .invalid
+ }
+
+ func addProvider(tunnelsTableViewController: TunnelsTableViewController) {
+ let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
+ actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from file or archive", comment: ""), style: .default) { [unowned self] _ in
+ self.addProviderFromFile()
+ })
+ actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from QR code", comment: ""), style: .default) { [unowned self] _ in
+ self.addProviderWithQRScan()
+ })
+ actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Create from scratch", comment: ""), style: .default) { [unowned self] _ in
+ self.addProviderManually()
+ })
+ actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel))
+
+ tunnelsTableViewController.present(actionSheet, animated: true, completion: nil)
+ }
+
+ func addProviderFromFile() {
+ let documentPickerController = UIDocumentPickerViewController(documentTypes: [String(kUTTypeZipArchive), "com.wireguard.config.quick"], in: .import)
+ documentPickerController.delegate = documentPickerDelegateObject
+ tunnelsTableViewController.present(documentPickerController, animated: true, completion: nil)
+ }
+
+ func addProviderManually() {
+ let addContext = persistentContainer.newBackgroundContext()
+ showTunnelConfigurationViewController(tunnel: nil, context: addContext)
+ }
+
+ func addProviderWithQRScan() {
+ let addContext = persistentContainer.newBackgroundContext()
+
+ let qrScanViewController = storyboard.instantiateViewController(type: QRScanViewController.self)
+
+ qrScanViewController.configure(context: addContext, delegate: self)
+
+ self.navigationController.pushViewController(qrScanViewController, animated: true)
+ }
+
+ func connect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
+ _ = refreshProviderManagers().then { () -> Promise<Void> in
+ let manager = self.providerManager(for: tunnel)!
+ let block = {
+ switch manager.connection.status {
+ case .invalid, .disconnected:
+ self.connect(tunnel: tunnel)
+ default:
+ break
+ }
+ }
+
+ if manager.connection.status == .invalid {
+ manager.loadFromPreferences { (_) in
+ block()
+ }
+ } else {
+ block()
+ }
+
+ return Promise.value(())
+ }
+ }
+
+ func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
+ _ = refreshProviderManagers().then { () -> Promise<Void> in
+ let manager = self.providerManager(for: tunnel)!
+ let block = {
+ switch manager.connection.status {
+ case .connected, .connecting:
+ self.disconnect(tunnel: tunnel)
+ default:
+ break
+ }
+ }
+
+ if manager.connection.status == .invalid {
+ manager.loadFromPreferences { (_) in
+ block()
+ }
+ } else {
+ block()
+ }
+ return Promise.value(())
+ }
+ }
+
+ private func connect(tunnel: Tunnel) {
+ os_log("connect tunnel: %{public}@", log: Log.general, type: .info, tunnel.description)
+ // Should the manager be enabled?
+
+ let manager = providerManager(for: tunnel)
+ manager?.isEnabled = true
+ manager?.saveToPreferences { (error) in
+ if let error = error {
+ os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
+ return
+ }
+ os_log("saved preferences", log: Log.general, type: .info)
+
+ let session = manager?.connection as! NETunnelProviderSession //swiftlint:disable:this force_cast
+ do {
+ try session.startTunnel()
+ } catch let error {
+ os_log("error starting tunnel: %{public}@", log: Log.general, type: .error, error.localizedDescription)
+ }
+ }
+ }
+
+ func disconnect(tunnel: Tunnel) {
+ let manager = providerManager(for: tunnel)
+ manager?.connection.stopVPNTunnel()
+ }
+
+ func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
+ print("info tunnel \(tunnel)")
+
+ showTunnelInfoViewController(tunnel: tunnel, context: self.persistentContainer.viewContext)
+ }
+
+ func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
+ print("delete tunnel \(tunnel)")
+
+ if let moc = tunnel.managedObjectContext {
+ moc.perform {
+ moc.delete(tunnel)
+ moc.saveContextToStore()
+ }
+ let manager = providerManager(for: tunnel)
+ manager?.removeFromPreferences { (error) in
+ if let error = error {
+ os_log("error removing preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
+ return
+ }
+ self.providerManagers?.removeAll { $0 == manager }
+ os_log("removed preferences", log: Log.general, type: .info)
+ }
+ }
+ }
+
+ private func providerManager(for tunnel: Tunnel) -> NETunnelProviderManager? {
+ return self.providerManagers?.first {
+ guard let prot = $0.protocolConfiguration as? NETunnelProviderProtocol else {
+ return false
+ }
+ guard let tunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else {
+ return false
+ }
+ return tunnelIdentifier == tunnel.tunnelIdentifier
+ }
+ }
+
+ func saveTunnel(_ tunnel: Tunnel) {
+ let manager = providerManager(for: tunnel) ?? NETunnelProviderManager()
+ manager.localizedDescription = tunnel.title
+
+ let protocolConfiguration = NETunnelProviderProtocol()
+ protocolConfiguration.providerBundleIdentifier = VPNBUNDLE
+ protocolConfiguration.serverAddress = (tunnel.peers?.array as? [Peer])?.compactMap { $0.endpoint}.joined(separator: ", ")
+ protocolConfiguration.providerConfiguration = tunnel.generateProviderConfiguration()
+
+ manager.protocolConfiguration = protocolConfiguration
+ let connectRule = NEOnDemandRuleConnect()
+ connectRule.interfaceTypeMatch = .any
+ manager.onDemandRules = [connectRule]
+
+ manager.saveToPreferences { (error) in
+ if let error = error {
+ os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
+ return
+ }
+ os_log("saved preferences", log: Log.general, type: .info)
+ }
+
+ _ = refreshProviderManagers().then { () -> Promise<Void> in
+ self.navigationController.popViewController(animated: true)
+ return Promise.value(())
+ }
+ }
+}
diff --git a/WireGuard/Coordinators/AppCoordinator.swift b/WireGuard/Coordinators/AppCoordinator.swift
index d8cf5db..d94c45e 100644
--- a/WireGuard/Coordinators/AppCoordinator.swift
+++ b/WireGuard/Coordinators/AppCoordinator.swift
@@ -27,7 +27,7 @@ class AppCoordinator: RootViewCoordinator {
let persistentContainer = NSPersistentContainer(name: "WireGuard")
let storyboard = UIStoryboard(name: "Main", bundle: nil)
var providerManagers: [NETunnelProviderManager]?
- private let documentPickerDelegate: AppDocumentPickerDelegate
+ let documentPickerDelegateObject: AppDocumentPickerDelegate
// MARK: - Properties
@@ -54,8 +54,8 @@ class AppCoordinator: RootViewCoordinator {
self.window.rootViewController = self.navigationController
self.window.makeKeyAndVisible()
- documentPickerDelegate = AppDocumentPickerDelegate()
- documentPickerDelegate.appCoordinator = self
+ documentPickerDelegateObject = AppDocumentPickerDelegate()
+ documentPickerDelegateObject.appCoordinator = self
NotificationCenter.default.addObserver(self,
selector: #selector(VPNStatusDidChange(notification:)),
@@ -315,227 +315,6 @@ class AppCoordinator: RootViewCoordinator {
}
}
-extension AppCoordinator: TunnelInfoTableViewControllerDelegate {
- func configure(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) {
- print("configure tunnel \(tunnel)")
- let editContext = persistentContainer.newBackgroundContext()
- var backgroundTunnel: Tunnel?
- editContext.performAndWait {
- backgroundTunnel = editContext.object(with: tunnel.objectID) as? Tunnel
- }
-
- showTunnelConfigurationViewController(tunnel: backgroundTunnel, context: editContext)
- }
-
-}
-
-extension AppCoordinator: TunnelsTableViewControllerDelegate {
- func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus {
- let session = self.providerManager(for: tunnel)?.connection as? NETunnelProviderSession
- return session?.status ?? .invalid
- }
-
- func addProvider(tunnelsTableViewController: TunnelsTableViewController) {
- let actionSheet = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
- actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Add from File", comment: ""), style: .default) { [unowned self] _ in
- self.addProviderFromFile()
- })
- actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Add Manually", comment: ""), style: .default) { [unowned self] _ in
- self.addProviderManually()
- })
- actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Scan QR Code", comment: ""), style: .default) { [unowned self] _ in
- self.addProviderWithQRScan()
- })
- actionSheet.addAction(UIAlertAction(title: NSLocalizedString("Cancel", comment: ""), style: .cancel))
-
- tunnelsTableViewController.present(actionSheet, animated: true, completion: nil)
- }
-
- func addProviderFromFile() {
- let documentPickerController = UIDocumentPickerViewController(documentTypes: [String(kUTTypeZipArchive), "com.wireguard.config.quick"], in: .import)
- documentPickerController.delegate = documentPickerDelegate
- tunnelsTableViewController.present(documentPickerController, animated: true, completion: nil)
- }
-
- func addProviderManually() {
- let addContext = persistentContainer.newBackgroundContext()
- showTunnelConfigurationViewController(tunnel: nil, context: addContext)
- }
-
- func addProviderWithQRScan() {
- let addContext = persistentContainer.newBackgroundContext()
-
- let qrScanViewController = storyboard.instantiateViewController(type: QRScanViewController.self)
-
- qrScanViewController.configure(context: addContext, delegate: self)
-
- self.navigationController.pushViewController(qrScanViewController, animated: true)
- }
-
- func connect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
- _ = refreshProviderManagers().then { () -> Promise<Void> in
- let manager = self.providerManager(for: tunnel)!
- let block = {
- switch manager.connection.status {
- case .invalid, .disconnected:
- self.connect(tunnel: tunnel)
- default:
- break
- }
- }
-
- if manager.connection.status == .invalid {
- manager.loadFromPreferences { (_) in
- block()
- }
- } else {
- block()
- }
-
- return Promise.value(())
- }
- }
-
- func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
- _ = refreshProviderManagers().then { () -> Promise<Void> in
- let manager = self.providerManager(for: tunnel)!
- let block = {
- switch manager.connection.status {
- case .connected, .connecting:
- self.disconnect(tunnel: tunnel)
- default:
- break
- }
- }
-
- if manager.connection.status == .invalid {
- manager.loadFromPreferences { (_) in
- block()
- }
- } else {
- block()
- }
- return Promise.value(())
- }
- }
-
- private func connect(tunnel: Tunnel) {
- os_log("connect tunnel: %{public}@", log: Log.general, type: .info, tunnel.description)
- // Should the manager be enabled?
-
- let manager = providerManager(for: tunnel)
- manager?.isEnabled = true
- manager?.saveToPreferences { (error) in
- if let error = error {
- os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
- return
- }
- os_log("saved preferences", log: Log.general, type: .info)
-
- let session = manager?.connection as! NETunnelProviderSession //swiftlint:disable:this force_cast
- do {
- try session.startTunnel()
- } catch let error {
- os_log("error starting tunnel: %{public}@", log: Log.general, type: .error, error.localizedDescription)
- }
- }
- }
-
- func disconnect(tunnel: Tunnel) {
- let manager = providerManager(for: tunnel)
- manager?.connection.stopVPNTunnel()
- }
-
- func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
- print("info tunnel \(tunnel)")
-
- showTunnelInfoViewController(tunnel: tunnel, context: self.persistentContainer.viewContext)
- }
-
- func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
- print("delete tunnel \(tunnel)")
-
- if let moc = tunnel.managedObjectContext {
- moc.perform {
- moc.delete(tunnel)
- moc.saveContextToStore()
- }
- let manager = providerManager(for: tunnel)
- manager?.removeFromPreferences { (error) in
- if let error = error {
- os_log("error removing preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
- return
- }
- self.providerManagers?.removeAll { $0 == manager }
- os_log("removed preferences", log: Log.general, type: .info)
- }
- }
- }
-
- private func providerManager(for tunnel: Tunnel) -> NETunnelProviderManager? {
- return self.providerManagers?.first {
- guard let prot = $0.protocolConfiguration as? NETunnelProviderProtocol else {
- return false
- }
- guard let tunnelIdentifier = prot.providerConfiguration?[PCKeys.tunnelIdentifier.rawValue] as? String else {
- return false
- }
- return tunnelIdentifier == tunnel.tunnelIdentifier
- }
- }
-
- private func saveTunnel(_ tunnel: Tunnel) {
- let manager = providerManager(for: tunnel) ?? NETunnelProviderManager()
- manager.localizedDescription = tunnel.title
-
- let protocolConfiguration = NETunnelProviderProtocol()
- protocolConfiguration.providerBundleIdentifier = VPNBUNDLE
- protocolConfiguration.serverAddress = (tunnel.peers?.array as? [Peer])?.compactMap { $0.endpoint}.joined(separator: ", ")
- protocolConfiguration.providerConfiguration = tunnel.generateProviderConfiguration()
-
- manager.protocolConfiguration = protocolConfiguration
- let connectRule = NEOnDemandRuleConnect()
- connectRule.interfaceTypeMatch = .any
- manager.onDemandRules = [connectRule]
-
- manager.saveToPreferences { (error) in
- if let error = error {
- os_log("error saving preferences: %{public}@", log: Log.general, type: .error, error.localizedDescription)
- return
- }
- os_log("saved preferences", log: Log.general, type: .info)
- }
-
- _ = refreshProviderManagers().then { () -> Promise<Void> in
- self.navigationController.popViewController(animated: true)
- return Promise.value(())
- }
- }
-}
-
-extension AppCoordinator: TunnelConfigurationTableViewControllerDelegate {
- func didSave(tunnel: Tunnel, tunnelConfigurationTableViewController: TunnelConfigurationTableViewController) {
- saveTunnel(tunnel)
- }
-}
-
-extension AppCoordinator: QRScanViewControllerDelegate {
- func didSave(tunnel: Tunnel, qrScanViewController: QRScanViewController) {
- qrScanViewController.navigationController?.popViewController(animated: true)
- showTunnelInfoViewController(tunnel: tunnel, context: tunnel.managedObjectContext!)
- }
-
- func didCancel(qrScanViewController: QRScanViewController) {
- qrScanViewController.navigationController?.popViewController(animated: true)
- }
-}
-
-extension AppCoordinator: SettingsTableViewControllerDelegate {
- func exportTunnels(settingsTableViewController: SettingsTableViewController, sourceView: UIView) {
- self.exportConfigs(sourceView: sourceView)
- }
-}
-
class AppDocumentPickerDelegate: NSObject, UIDocumentPickerDelegate {
weak var appCoordinator: AppCoordinator?