wireguard-apple/WireGuard/Coordinators/AppCoordinator+TunnelsTable...

119 lines
4.9 KiB
Swift

//
// 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) {
connect(tunnel: tunnel)
}
func disconnect(tunnel: Tunnel, tunnelsTableViewController: TunnelsTableViewController) {
disconnect(tunnel: tunnel)
}
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)
}
}
}
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(())
}
}
}