diff --git a/WireGuard.xcodeproj/project.pbxproj b/WireGuard.xcodeproj/project.pbxproj index e7ae5e2..989aba5 100644 --- a/WireGuard.xcodeproj/project.pbxproj +++ b/WireGuard.xcodeproj/project.pbxproj @@ -35,6 +35,7 @@ 4A61D83520D98D25006C7A76 /* NetworkExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4A61D83420D98D25006C7A76 /* NetworkExtension.framework */; }; 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 */; }; 4ABFFEA0212D39A000107136 /* x25519.c in Sources */ = {isa = PBXBuildFile; fileRef = 4ABFFE9F212D39A000107136 /* x25519.c */; }; 4ABFFEA3212D3C8300107136 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4ABFFEA2212D3C8300107136 /* Security.framework */; }; 4AC086832120B9F900CEE5ED /* ProviderConfigurationKeys.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4AC086822120B9F900CEE5ED /* ProviderConfigurationKeys.swift */; }; @@ -121,6 +122,7 @@ 4A61D83320D98D07006C7A76 /* WireGuard.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = WireGuard.entitlements; sourceTree = ""; }; 4A61D83420D98D25006C7A76 /* NetworkExtension.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = NetworkExtension.framework; path = System/Library/Frameworks/NetworkExtension.framework; sourceTree = SDKROOT; }; 4A8AABD720B6A79100B6D8C1 /* UITableView+WireGuard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UITableView+WireGuard.swift"; sourceTree = ""; }; + 4ABF718D214D8B0300A1E0BF /* TunnelInfoTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelInfoTableViewController.swift; sourceTree = ""; }; 4ABFFE9D212D399F00107136 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = ""; }; 4ABFFE9E212D39A000107136 /* x25519.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = x25519.h; sourceTree = ""; }; 4ABFFE9F212D39A000107136 /* x25519.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = x25519.c; sourceTree = ""; }; @@ -252,6 +254,7 @@ 4A4BAD1220B5F82400F12B28 /* Identifyable.swift */, 4A8AABD720B6A79100B6D8C1 /* UITableView+WireGuard.swift */, 4A4BACE720B5F1BF00F12B28 /* TunnelsTableViewController.swift */, + 4ABF718D214D8B0300A1E0BF /* TunnelInfoTableViewController.swift */, 4A4BA6D720B73CBA00223AB8 /* TunnelConfigurationTableViewController.swift */, 5FCC4342212B3092009A9C58 /* QRScanViewController.swift */, ); @@ -591,6 +594,7 @@ 5FA1D5122124DA6400DBA2E6 /* String+Base64.swift in Sources */, 4AC5462E2116306F00749D21 /* Tunnel+Extension.swift in Sources */, 5FCC4343212B3092009A9C58 /* QRScanViewController.swift in Sources */, + 4ABF718E214D8B0300A1E0BF /* TunnelInfoTableViewController.swift in Sources */, 4A4BAD0E20B5F6C300F12B28 /* Coordinator.swift in Sources */, 4ABFFEA0212D39A000107136 /* x25519.c in Sources */, 4A4BA6D820B73CBA00223AB8 /* TunnelConfigurationTableViewController.swift in Sources */, diff --git a/WireGuard/Base.lproj/Main.storyboard b/WireGuard/Base.lproj/Main.storyboard index 5d68a22..cceab80 100644 --- a/WireGuard/Base.lproj/Main.storyboard +++ b/WireGuard/Base.lproj/Main.storyboard @@ -514,7 +514,311 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WireGuard/Coordinators/AppCoordinator.swift b/WireGuard/Coordinators/AppCoordinator.swift index 0de4271..b73c07c 100644 --- a/WireGuard/Coordinators/AppCoordinator.swift +++ b/WireGuard/Coordinators/AppCoordinator.swift @@ -261,6 +261,22 @@ class AppCoordinator: RootViewCoordinator { }) } + func showTunnelInfoViewController(tunnel: Tunnel, context: NSManagedObjectContext) { + let tunnelInfoViewController = storyboard.instantiateViewController(type: TunnelInfoTableViewController.self) + + tunnelInfoViewController.configure(context: context, delegate: self, tunnel: tunnel) + + self.navigationController.pushViewController(tunnelInfoViewController, animated: true) + } + + func showTunnelConfigurationViewController(tunnel: Tunnel?, context: NSManagedObjectContext) { + let tunnelConfigurationViewController = storyboard.instantiateViewController(type: TunnelConfigurationTableViewController.self) + + tunnelConfigurationViewController.configure(context: context, delegate: self, tunnel: tunnel) + + self.navigationController.pushViewController(tunnelConfigurationViewController, animated: true) + } + public func showError(_ error: Error) { showAlert(title: NSLocalizedString("Error", comment: "Error alert title"), message: error.localizedDescription) } @@ -289,6 +305,20 @@ 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 exportTunnels(tunnelsTableViewController: TunnelsTableViewController, barButtonItem: UIBarButtonItem) { self.exportConfigs(barButtonItem: barButtonItem) @@ -401,23 +431,10 @@ extension AppCoordinator: TunnelsTableViewControllerDelegate { manager?.connection.stopVPNTunnel() } - func configure(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) { - print("configure tunnel \(tunnel)") - let editContext = persistentContainer.newBackgroundContext() - var backgroundTunnel: Tunnel? - editContext.performAndWait { - backgroundTunnel = editContext.object(with: tunnel.objectID) as? Tunnel - } + func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) { + print("info tunnel \(tunnel)") - showTunnelConfigurationViewController(tunnel: backgroundTunnel, context: editContext) - } - - func showTunnelConfigurationViewController(tunnel: Tunnel?, context: NSManagedObjectContext) { - let tunnelConfigurationViewController = storyboard.instantiateViewController(type: TunnelConfigurationTableViewController.self) - - tunnelConfigurationViewController.configure(context: context, delegate: self, tunnel: tunnel) - - self.navigationController.pushViewController(tunnelConfigurationViewController, animated: true) + showTunnelInfoViewController(tunnel: tunnel, context: self.persistentContainer.viewContext) } func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) { @@ -476,7 +493,7 @@ extension AppCoordinator: TunnelsTableViewControllerDelegate { } _ = refreshProviderManagers().then { () -> Promise in - self.navigationController.popToRootViewController(animated: true) + self.navigationController.popViewController(animated: true) return Promise.value(()) } } diff --git a/WireGuard/ViewControllers/TunnelInfoTableViewController.swift b/WireGuard/ViewControllers/TunnelInfoTableViewController.swift new file mode 100644 index 0000000..0b4b038 --- /dev/null +++ b/WireGuard/ViewControllers/TunnelInfoTableViewController.swift @@ -0,0 +1,115 @@ +// +// TunnelInfoTableViewController.swift +// WireGuard +// +// Created by Jeroen Leenarts on 15-09-18. +// Copyright © 2018 WireGuard LLC. All rights reserved. +// + +import UIKit +import CoreData +import BNRCoreDataStack +import PromiseKit + +protocol TunnelInfoTableViewControllerDelegate: class { + func configure(tunnel: Tunnel, tunnelInfoTableViewController: TunnelInfoTableViewController) +} + +class TunnelInfoTableViewController: UITableViewController { + + @IBOutlet weak var editButton: UIBarButtonItem! + + private var viewContext: NSManagedObjectContext! + private weak var delegate: TunnelInfoTableViewControllerDelegate? + private var tunnel: Tunnel! + + func configure(context: NSManagedObjectContext, delegate: TunnelInfoTableViewControllerDelegate? = nil, tunnel: Tunnel) { + viewContext = context + self.delegate = delegate + self.tunnel = tunnel + } + + override func viewWillAppear(_ animated: Bool) { + super .viewWillAppear(animated) + + self.tableView.reloadData() + } + + override func numberOfSections(in tableView: UITableView) -> Int { + return 3 + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch section { + case 1: + return tunnel?.peers?.count ?? 1 + default: + return 1 + } + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + switch indexPath.section { + case 0: + let cell = tableView.dequeueReusableCell(type: InterfaceInfoTableViewCell.self, for: indexPath) + cell.model = tunnel.interface + return cell + default: + let cell = tableView.dequeueReusableCell(type: PeerInfoTableViewCell.self, for: indexPath) + if let peer = tunnel.peers?.object(at: indexPath.row) as? Peer { + cell.peer = peer + } else { + let peer = Peer(context: tunnel.managedObjectContext!) + tunnel.addToPeers(peer) + cell.peer = peer + } + return cell + } + } + + @IBAction func editTunnelConfiguration(_ sender: Any) { + delegate?.configure(tunnel: self.tunnel, tunnelInfoTableViewController: self) + } +} + +class InterfaceInfoTableViewCell: UITableViewCell { + var model: Interface! { + didSet { + nameField.text = model.tunnel?.title + addressesField.text = model.addresses + privateKeyField.text = model.privateKey + listenPortField.text = String(model.listenPort) + dnsField.text = model.dns + mtuField.text = String(model.mtu) + } + } + + @IBOutlet weak var nameField: UILabel! + @IBOutlet weak var addressesField: UILabel! + @IBOutlet weak var privateKeyField: UILabel! + @IBOutlet weak var listenPortField: UILabel! + @IBOutlet weak var dnsField: UILabel! + @IBOutlet weak var mtuField: UILabel! +} + +class PeerInfoTableViewCell: UITableViewCell { + var peer: Peer! { + didSet { + publicKeyField.text = peer.publicKey + preSharedKeyField.text = peer.presharedKey + allowedIpsField.text = peer.allowedIPs + endpointField.text = peer.endpoint + persistentKeepaliveField.text = String(peer.persistentKeepalive) + } + } + + @IBOutlet weak var publicKeyField: UILabel! + @IBOutlet weak var preSharedKeyField: UILabel! + @IBOutlet weak var allowedIpsField: UILabel! + @IBOutlet weak var endpointField: UILabel! + @IBOutlet weak var persistentKeepaliveField: UILabel! +} + +extension TunnelInfoTableViewController: Identifyable {} +extension InterfaceInfoTableViewCell: Identifyable {} +extension PeerInfoTableViewCell: Identifyable {} diff --git a/WireGuard/ViewControllers/TunnelsTableViewController.swift b/WireGuard/ViewControllers/TunnelsTableViewController.swift index 5f7f15f..385000c 100644 --- a/WireGuard/ViewControllers/TunnelsTableViewController.swift +++ b/WireGuard/ViewControllers/TunnelsTableViewController.swift @@ -7,8 +7,9 @@ // import UIKit - +import os.log import CoreData + import BNRCoreDataStack import NetworkExtension @@ -17,7 +18,7 @@ protocol TunnelsTableViewControllerDelegate: class { func addProvider(tunnelsTableViewController: TunnelsTableViewController) func connect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) - func configure(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) + func info(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) func delete(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) func status(for tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) -> NEVPNStatus } @@ -39,11 +40,16 @@ class TunnelsTableViewController: UITableViewController { public func updateStatus(for tunnelIdentifier: String) { viewContext.perform { - let tunnel = try? Tunnel.findFirstInContext(self.viewContext, predicate: NSPredicate(format: "tunnelIdentifier == %@", tunnelIdentifier)) - if let tunnel = tunnel { - if let indexPath = self.fetchedResultsController.indexPathForObject(tunnel!) { - self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none) + do { + let tunnel = try Tunnel.findFirstInContext(self.viewContext, predicate: NSPredicate(format: "tunnelIdentifier == %@", tunnelIdentifier)) + if let tunnel = tunnel { + if let indexPath = self.fetchedResultsController.indexPathForObject(tunnel) { + self.tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none) + } } + } catch { + os_log("Unable to load tunnel for tunnel identifier: %{public}@", log: Log.general, type: .error, error.localizedDescription) + } } } @@ -104,7 +110,7 @@ class TunnelsTableViewController: UITableViewController { let section = sections[indexPath.section] let tunnel = section.objects[indexPath.row] - delegate?.configure(tunnel: tunnel, tunnelsTableViewController: self) + delegate?.info(tunnel: tunnel, tunnelsTableViewController: self) tableView.deselectRow(at: indexPath, animated: true) } @@ -117,7 +123,7 @@ class TunnelsTableViewController: UITableViewController { let section = sections[indexPath.section] let tunnel = section.objects[indexPath.row] - delegate?.configure(tunnel: tunnel, tunnelsTableViewController: self) + delegate?.info(tunnel: tunnel, tunnelsTableViewController: self) }