Move name from interface to tunnel
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
9295895e3a
commit
4ed646973e
|
@ -96,7 +96,7 @@ struct LegacyInterfaceConfiguration: LegacyModel {
|
||||||
let dns: [LegacyDNSServer]
|
let dns: [LegacyDNSServer]
|
||||||
|
|
||||||
var migrated: InterfaceConfiguration {
|
var migrated: InterfaceConfiguration {
|
||||||
var interface = InterfaceConfiguration(name: name, privateKey: privateKey)
|
var interface = InterfaceConfiguration(privateKey: privateKey)
|
||||||
interface.addresses = addresses.migrated
|
interface.addresses = addresses.migrated
|
||||||
interface.listenPort = listenPort
|
interface.listenPort = listenPort
|
||||||
interface.mtu = mtu
|
interface.mtu = mtu
|
||||||
|
@ -167,7 +167,7 @@ final class LegacyTunnelConfiguration: LegacyModel {
|
||||||
let peers: [LegacyPeerConfiguration]
|
let peers: [LegacyPeerConfiguration]
|
||||||
|
|
||||||
var migrated: TunnelConfiguration {
|
var migrated: TunnelConfiguration {
|
||||||
return TunnelConfiguration(interface: interface.migrated, peers: peers.migrated)
|
return TunnelConfiguration(name: interface.name, interface: interface.migrated, peers: peers.migrated)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,18 +4,16 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
struct InterfaceConfiguration {
|
struct InterfaceConfiguration {
|
||||||
var name: String?
|
|
||||||
var privateKey: Data
|
var privateKey: Data
|
||||||
var addresses = [IPAddressRange]()
|
var addresses = [IPAddressRange]()
|
||||||
var listenPort: UInt16?
|
var listenPort: UInt16?
|
||||||
var mtu: UInt16?
|
var mtu: UInt16?
|
||||||
var dns = [DNSServer]()
|
var dns = [DNSServer]()
|
||||||
|
|
||||||
init(name: String?, privateKey: Data) {
|
init(privateKey: Data) {
|
||||||
self.name = name
|
|
||||||
self.privateKey = privateKey
|
|
||||||
if privateKey.count != TunnelConfiguration.keyLength {
|
if privateKey.count != TunnelConfiguration.keyLength {
|
||||||
fatalError("Invalid private key")
|
fatalError("Invalid private key")
|
||||||
}
|
}
|
||||||
|
self.privateKey = privateKey
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,14 +4,16 @@
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class TunnelConfiguration {
|
final class TunnelConfiguration {
|
||||||
|
var name: String?
|
||||||
var interface: InterfaceConfiguration
|
var interface: InterfaceConfiguration
|
||||||
let peers: [PeerConfiguration]
|
let peers: [PeerConfiguration]
|
||||||
|
|
||||||
static let keyLength = 32
|
static let keyLength = 32
|
||||||
|
|
||||||
init(interface: InterfaceConfiguration, peers: [PeerConfiguration]) {
|
init(name: String?, interface: InterfaceConfiguration, peers: [PeerConfiguration]) {
|
||||||
self.interface = interface
|
self.interface = interface
|
||||||
self.peers = peers
|
self.peers = peers
|
||||||
|
self.name = name
|
||||||
|
|
||||||
let peerPublicKeysArray = peers.map { $0.publicKey }
|
let peerPublicKeysArray = peers.map { $0.publicKey }
|
||||||
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
let peerPublicKeysSet = Set<Data>(peerPublicKeysArray)
|
||||||
|
|
|
@ -27,13 +27,14 @@ extension NETunnelProviderProtocol {
|
||||||
serverAddress = "Multiple endpoints"
|
serverAddress = "Multiple endpoints"
|
||||||
}
|
}
|
||||||
|
|
||||||
username = tunnelConfiguration.interface.name
|
//TODO(roopc): Why are we doing this? Just for kicks? Is it useful? Seems needless.
|
||||||
|
username = tunnelConfiguration.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func tunnelConfiguration(name: String?) -> TunnelConfiguration? {
|
func asTunnelConfiguration(called name: String? = nil) -> TunnelConfiguration? {
|
||||||
migrateConfigurationIfNeeded()
|
migrateConfigurationIfNeeded()
|
||||||
guard let serializedConfig = providerConfiguration?[Keys.wgQuickConfig.rawValue] as? String else { return nil }
|
guard let serializedConfig = providerConfiguration?[Keys.wgQuickConfig.rawValue] as? String else { return nil }
|
||||||
return try? TunnelConfiguration(serializedConfig, name: name)
|
return try? TunnelConfiguration(fromWgQuickConfig: serializedConfig, called: name)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,8 +20,8 @@ extension TunnelConfiguration {
|
||||||
case invalidPeer
|
case invalidPeer
|
||||||
}
|
}
|
||||||
|
|
||||||
//swiftlint:disable:next cyclomatic_complexity function_body_length
|
//swiftlint:disable:next function_body_length cyclomatic_complexity
|
||||||
convenience init(_ wgQuickConfig: String, name: String?) throws {
|
convenience init(fromWgQuickConfig wgQuickConfig: String, called name: String? = nil) throws {
|
||||||
var interfaceConfiguration: InterfaceConfiguration?
|
var interfaceConfiguration: InterfaceConfiguration?
|
||||||
var peerConfigurations = [PeerConfiguration]()
|
var peerConfigurations = [PeerConfiguration]()
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ extension TunnelConfiguration {
|
||||||
if isLastLine || lowercasedLine == "[interface]" || lowercasedLine == "[peer]" {
|
if isLastLine || lowercasedLine == "[interface]" || lowercasedLine == "[peer]" {
|
||||||
// Previous section has ended; process the attributes collected so far
|
// Previous section has ended; process the attributes collected so far
|
||||||
if parserState == .inInterfaceSection {
|
if parserState == .inInterfaceSection {
|
||||||
guard let interface = TunnelConfiguration.collate(interfaceAttributes: attributes, name: name) else { throw ParseError.invalidInterface }
|
guard let interface = TunnelConfiguration.collate(interfaceAttributes: attributes) else { throw ParseError.invalidInterface }
|
||||||
guard interfaceConfiguration == nil else { throw ParseError.multipleInterfaces }
|
guard interfaceConfiguration == nil else { throw ParseError.multipleInterfaces }
|
||||||
interfaceConfiguration = interface
|
interfaceConfiguration = interface
|
||||||
} else if parserState == .inPeerSection {
|
} else if parserState == .inPeerSection {
|
||||||
|
@ -87,7 +87,7 @@ extension TunnelConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let interfaceConfiguration = interfaceConfiguration {
|
if let interfaceConfiguration = interfaceConfiguration {
|
||||||
self.init(interface: interfaceConfiguration, peers: peerConfigurations)
|
self.init(name: name, interface: interfaceConfiguration, peers: peerConfigurations)
|
||||||
} else {
|
} else {
|
||||||
throw ParseError.noInterface
|
throw ParseError.noInterface
|
||||||
}
|
}
|
||||||
|
@ -133,11 +133,11 @@ extension TunnelConfiguration {
|
||||||
}
|
}
|
||||||
|
|
||||||
//swiftlint:disable:next cyclomatic_complexity
|
//swiftlint:disable:next cyclomatic_complexity
|
||||||
private static func collate(interfaceAttributes attributes: [String: String], name: String?) -> InterfaceConfiguration? {
|
private static func collate(interfaceAttributes attributes: [String: String]) -> InterfaceConfiguration? {
|
||||||
// required wg fields
|
// required wg fields
|
||||||
guard let privateKeyString = attributes["privatekey"] else { return nil }
|
guard let privateKeyString = attributes["privatekey"] else { return nil }
|
||||||
guard let privateKey = Data(base64Encoded: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else { return nil }
|
guard let privateKey = Data(base64Encoded: privateKeyString), privateKey.count == TunnelConfiguration.keyLength else { return nil }
|
||||||
var interface = InterfaceConfiguration(name: name, privateKey: privateKey)
|
var interface = InterfaceConfiguration(privateKey: privateKey)
|
||||||
// other wg fields
|
// other wg fields
|
||||||
if let listenPortString = attributes["listenport"] {
|
if let listenPortString = attributes["listenport"] {
|
||||||
guard let listenPort = UInt16(listenPortString) else { return nil }
|
guard let listenPort = UInt16(listenPortString) else { return nil }
|
||||||
|
|
|
@ -54,7 +54,7 @@ class TunnelsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(tunnelConfiguration: TunnelConfiguration, activateOnDemandSetting: ActivateOnDemandSetting = ActivateOnDemandSetting.defaultSetting, completionHandler: @escaping (WireGuardResult<TunnelContainer>) -> Void) {
|
func add(tunnelConfiguration: TunnelConfiguration, activateOnDemandSetting: ActivateOnDemandSetting = ActivateOnDemandSetting.defaultSetting, completionHandler: @escaping (WireGuardResult<TunnelContainer>) -> Void) {
|
||||||
let tunnelName = tunnelConfiguration.interface.name ?? ""
|
let tunnelName = tunnelConfiguration.name ?? ""
|
||||||
if tunnelName.isEmpty {
|
if tunnelName.isEmpty {
|
||||||
completionHandler(.failure(TunnelsManagerError.tunnelNameEmpty))
|
completionHandler(.failure(TunnelsManagerError.tunnelNameEmpty))
|
||||||
return
|
return
|
||||||
|
@ -67,7 +67,7 @@ class TunnelsManager {
|
||||||
|
|
||||||
let tunnelProviderManager = NETunnelProviderManager()
|
let tunnelProviderManager = NETunnelProviderManager()
|
||||||
tunnelProviderManager.protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration)
|
tunnelProviderManager.protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration)
|
||||||
tunnelProviderManager.localizedDescription = tunnelConfiguration.interface.name
|
tunnelProviderManager.localizedDescription = tunnelConfiguration.name
|
||||||
tunnelProviderManager.isEnabled = true
|
tunnelProviderManager.isEnabled = true
|
||||||
|
|
||||||
activateOnDemandSetting.apply(on: tunnelProviderManager)
|
activateOnDemandSetting.apply(on: tunnelProviderManager)
|
||||||
|
@ -107,7 +107,7 @@ class TunnelsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
func modify(tunnel: TunnelContainer, tunnelConfiguration: TunnelConfiguration, activateOnDemandSetting: ActivateOnDemandSetting, completionHandler: @escaping (TunnelsManagerError?) -> Void) {
|
func modify(tunnel: TunnelContainer, tunnelConfiguration: TunnelConfiguration, activateOnDemandSetting: ActivateOnDemandSetting, completionHandler: @escaping (TunnelsManagerError?) -> Void) {
|
||||||
let tunnelName = tunnelConfiguration.interface.name ?? ""
|
let tunnelName = tunnelConfiguration.name ?? ""
|
||||||
if tunnelName.isEmpty {
|
if tunnelName.isEmpty {
|
||||||
completionHandler(TunnelsManagerError.tunnelNameEmpty)
|
completionHandler(TunnelsManagerError.tunnelNameEmpty)
|
||||||
return
|
return
|
||||||
|
@ -124,7 +124,7 @@ class TunnelsManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
tunnelProviderManager.protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration)
|
tunnelProviderManager.protocolConfiguration = NETunnelProviderProtocol(tunnelConfiguration: tunnelConfiguration)
|
||||||
tunnelProviderManager.localizedDescription = tunnelConfiguration.interface.name
|
tunnelProviderManager.localizedDescription = tunnelConfiguration.name
|
||||||
tunnelProviderManager.isEnabled = true
|
tunnelProviderManager.isEnabled = true
|
||||||
|
|
||||||
let isActivatingOnDemand = !tunnelProviderManager.isOnDemandEnabled && activateOnDemandSetting.isActivateOnDemandEnabled
|
let isActivatingOnDemand = !tunnelProviderManager.isOnDemandEnabled && activateOnDemandSetting.isActivateOnDemandEnabled
|
||||||
|
@ -349,7 +349,7 @@ class TunnelContainer: NSObject {
|
||||||
private var lastTunnelConnectionStatus: NEVPNStatus?
|
private var lastTunnelConnectionStatus: NEVPNStatus?
|
||||||
|
|
||||||
var tunnelConfiguration: TunnelConfiguration? {
|
var tunnelConfiguration: TunnelConfiguration? {
|
||||||
return (tunnelProvider.protocolConfiguration as? NETunnelProviderProtocol)?.tunnelConfiguration(name: tunnelProvider.localizedDescription)
|
return (tunnelProvider.protocolConfiguration as? NETunnelProviderProtocol)?.asTunnelConfiguration(called: tunnelProvider.localizedDescription)
|
||||||
}
|
}
|
||||||
|
|
||||||
var activateOnDemandSetting: ActivateOnDemandSetting {
|
var activateOnDemandSetting: ActivateOnDemandSetting {
|
||||||
|
|
|
@ -66,6 +66,7 @@ class TunnelViewModel {
|
||||||
var scratchpad = [InterfaceField: String]()
|
var scratchpad = [InterfaceField: String]()
|
||||||
var fieldsWithError = Set<InterfaceField>()
|
var fieldsWithError = Set<InterfaceField>()
|
||||||
var validatedConfiguration: InterfaceConfiguration?
|
var validatedConfiguration: InterfaceConfiguration?
|
||||||
|
var validatedName: String?
|
||||||
|
|
||||||
subscript(field: InterfaceField) -> String {
|
subscript(field: InterfaceField) -> String {
|
||||||
get {
|
get {
|
||||||
|
@ -83,6 +84,7 @@ class TunnelViewModel {
|
||||||
populateScratchpad()
|
populateScratchpad()
|
||||||
}
|
}
|
||||||
validatedConfiguration = nil
|
validatedConfiguration = nil
|
||||||
|
validatedName = nil
|
||||||
if stringValue.isEmpty {
|
if stringValue.isEmpty {
|
||||||
scratchpad.removeValue(forKey: field)
|
scratchpad.removeValue(forKey: field)
|
||||||
} else {
|
} else {
|
||||||
|
@ -102,7 +104,8 @@ class TunnelViewModel {
|
||||||
func populateScratchpad() {
|
func populateScratchpad() {
|
||||||
// Populate the scratchpad from the configuration object
|
// Populate the scratchpad from the configuration object
|
||||||
guard let config = validatedConfiguration else { return }
|
guard let config = validatedConfiguration else { return }
|
||||||
scratchpad[.name] = config.name
|
guard let name = validatedName else { return }
|
||||||
|
scratchpad[.name] = name
|
||||||
scratchpad[.privateKey] = config.privateKey.base64EncodedString()
|
scratchpad[.privateKey] = config.privateKey.base64EncodedString()
|
||||||
scratchpad[.publicKey] = config.publicKey.base64EncodedString()
|
scratchpad[.publicKey] = config.publicKey.base64EncodedString()
|
||||||
if !config.addresses.isEmpty {
|
if !config.addresses.isEmpty {
|
||||||
|
@ -120,10 +123,10 @@ class TunnelViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
//swiftlint:disable:next cyclomatic_complexity function_body_length
|
//swiftlint:disable:next cyclomatic_complexity function_body_length
|
||||||
func save() -> SaveResult<InterfaceConfiguration> {
|
func save() -> SaveResult<(String, InterfaceConfiguration)> {
|
||||||
if let validatedConfiguration = validatedConfiguration {
|
if let config = validatedConfiguration, let name = validatedName {
|
||||||
// It's already validated and saved
|
// It's already validated and saved
|
||||||
return .saved(validatedConfiguration)
|
return .saved((name, config))
|
||||||
}
|
}
|
||||||
fieldsWithError.removeAll()
|
fieldsWithError.removeAll()
|
||||||
guard let name = scratchpad[.name]?.trimmingCharacters(in: .whitespacesAndNewlines), (!name.isEmpty) else {
|
guard let name = scratchpad[.name]?.trimmingCharacters(in: .whitespacesAndNewlines), (!name.isEmpty) else {
|
||||||
|
@ -138,7 +141,7 @@ class TunnelViewModel {
|
||||||
fieldsWithError.insert(.privateKey)
|
fieldsWithError.insert(.privateKey)
|
||||||
return .error(tr("alertInvalidInterfaceMessagePrivateKeyInvalid"))
|
return .error(tr("alertInvalidInterfaceMessagePrivateKeyInvalid"))
|
||||||
}
|
}
|
||||||
var config = InterfaceConfiguration(name: name, privateKey: privateKey)
|
var config = InterfaceConfiguration(privateKey: privateKey)
|
||||||
var errorMessages = [String]()
|
var errorMessages = [String]()
|
||||||
if let addressesString = scratchpad[.addresses] {
|
if let addressesString = scratchpad[.addresses] {
|
||||||
var addresses = [IPAddressRange]()
|
var addresses = [IPAddressRange]()
|
||||||
|
@ -184,7 +187,8 @@ class TunnelViewModel {
|
||||||
guard errorMessages.isEmpty else { return .error(errorMessages.first!) }
|
guard errorMessages.isEmpty else { return .error(errorMessages.first!) }
|
||||||
|
|
||||||
validatedConfiguration = config
|
validatedConfiguration = config
|
||||||
return .saved(config)
|
validatedName = name
|
||||||
|
return .saved((name, config))
|
||||||
}
|
}
|
||||||
|
|
||||||
func filterFieldsWithValueOrControl(interfaceFields: [InterfaceField]) -> [InterfaceField] {
|
func filterFieldsWithValueOrControl(interfaceFields: [InterfaceField]) -> [InterfaceField] {
|
||||||
|
@ -390,6 +394,7 @@ class TunnelViewModel {
|
||||||
var peersData = [PeerData]()
|
var peersData = [PeerData]()
|
||||||
if let tunnelConfiguration = tunnelConfiguration {
|
if let tunnelConfiguration = tunnelConfiguration {
|
||||||
interfaceData.validatedConfiguration = tunnelConfiguration.interface
|
interfaceData.validatedConfiguration = tunnelConfiguration.interface
|
||||||
|
interfaceData.validatedName = tunnelConfiguration.name
|
||||||
for (index, peerConfiguration) in tunnelConfiguration.peers.enumerated() {
|
for (index, peerConfiguration) in tunnelConfiguration.peers.enumerated() {
|
||||||
let peerData = PeerData(index: index)
|
let peerData = PeerData(index: index)
|
||||||
peerData.validatedConfiguration = peerConfiguration
|
peerData.validatedConfiguration = peerConfiguration
|
||||||
|
@ -453,7 +458,7 @@ class TunnelViewModel {
|
||||||
return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated"))
|
return .error(tr("alertInvalidPeerMessagePublicKeyDuplicated"))
|
||||||
}
|
}
|
||||||
|
|
||||||
let tunnelConfiguration = TunnelConfiguration(interface: interfaceConfiguration, peers: peerConfigurations)
|
let tunnelConfiguration = TunnelConfiguration(name: interfaceConfiguration.0, interface: interfaceConfiguration.1, peers: peerConfigurations)
|
||||||
return .saved(tunnelConfiguration)
|
return .saved(tunnelConfiguration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,7 @@ class QRScanViewController: UIViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
func scanDidComplete(withCode code: String) {
|
func scanDidComplete(withCode code: String) {
|
||||||
let scannedTunnelConfiguration = try? TunnelConfiguration(code, name: "Scanned")
|
let scannedTunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: code, called: "Scanned")
|
||||||
guard let tunnelConfiguration = scannedTunnelConfiguration else {
|
guard let tunnelConfiguration = scannedTunnelConfiguration else {
|
||||||
scanDidEncounterError(title: tr("alertScanQRCodeInvalidQRCodeTitle"), message: tr("alertScanQRCodeInvalidQRCodeMessage"))
|
scanDidEncounterError(title: tr("alertScanQRCodeInvalidQRCodeTitle"), message: tr("alertScanQRCodeInvalidQRCodeMessage"))
|
||||||
return
|
return
|
||||||
|
@ -114,7 +114,7 @@ class QRScanViewController: UIViewController {
|
||||||
})
|
})
|
||||||
alert.addAction(UIAlertAction(title: tr("actionSave"), style: .default) { [weak self] _ in
|
alert.addAction(UIAlertAction(title: tr("actionSave"), style: .default) { [weak self] _ in
|
||||||
guard let title = alert.textFields?[0].text?.trimmingCharacters(in: .whitespacesAndNewlines), !title.isEmpty else { return }
|
guard let title = alert.textFields?[0].text?.trimmingCharacters(in: .whitespacesAndNewlines), !title.isEmpty else { return }
|
||||||
tunnelConfiguration.interface.name = title
|
tunnelConfiguration.name = title
|
||||||
if let self = self {
|
if let self = self {
|
||||||
self.delegate?.addScannedQRCode(tunnelConfiguration: tunnelConfiguration, qrScanViewController: self) {
|
self.delegate?.addScannedQRCode(tunnelConfiguration: tunnelConfiguration, qrScanViewController: self) {
|
||||||
self.dismiss(animated: true, completion: nil)
|
self.dismiss(animated: true, completion: nil)
|
||||||
|
|
|
@ -98,7 +98,7 @@ class TunnelEditTableViewController: UITableViewController {
|
||||||
let tunnelSaveResult = tunnelViewModel.save()
|
let tunnelSaveResult = tunnelViewModel.save()
|
||||||
switch tunnelSaveResult {
|
switch tunnelSaveResult {
|
||||||
case .error(let errorMessage):
|
case .error(let errorMessage):
|
||||||
let alertTitle = (tunnelViewModel.interfaceData.validatedConfiguration == nil) ?
|
let alertTitle = (tunnelViewModel.interfaceData.validatedConfiguration == nil || tunnelViewModel.interfaceData.validatedName == nil) ?
|
||||||
tr("alertInvalidInterfaceTitle") : tr("alertInvalidPeerTitle")
|
tr("alertInvalidInterfaceTitle") : tr("alertInvalidPeerTitle")
|
||||||
ErrorPresenter.showErrorAlert(title: alertTitle, message: errorMessage, from: self)
|
ErrorPresenter.showErrorAlert(title: alertTitle, message: errorMessage, from: self)
|
||||||
tableView.reloadData() // Highlight erroring fields
|
tableView.reloadData() // Highlight erroring fields
|
||||||
|
|
|
@ -180,7 +180,7 @@ class TunnelsListTableViewController: UIViewController {
|
||||||
} else /* if (url.pathExtension == "conf") -- we assume everything else is a conf */ {
|
} else /* if (url.pathExtension == "conf") -- we assume everything else is a conf */ {
|
||||||
let fileBaseName = url.deletingPathExtension().lastPathComponent.trimmingCharacters(in: .whitespacesAndNewlines)
|
let fileBaseName = url.deletingPathExtension().lastPathComponent.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
if let fileContents = try? String(contentsOf: url),
|
if let fileContents = try? String(contentsOf: url),
|
||||||
let tunnelConfiguration = try? TunnelConfiguration(fileContents, name: fileBaseName) {
|
let tunnelConfiguration = try? TunnelConfiguration(fromWgQuickConfig: fileContents, called: fileBaseName) {
|
||||||
tunnelsManager.add(tunnelConfiguration: tunnelConfiguration) { [weak self] result in
|
tunnelsManager.add(tunnelConfiguration: tunnelConfiguration) { [weak self] result in
|
||||||
if let error = result.error {
|
if let error = result.error {
|
||||||
ErrorPresenter.showErrorAlert(error: error, from: self, onPresented: completionHandler)
|
ErrorPresenter.showErrorAlert(error: error, from: self, onPresented: completionHandler)
|
||||||
|
|
|
@ -23,7 +23,7 @@ class ZipExporter {
|
||||||
var lastTunnelName: String = ""
|
var lastTunnelName: String = ""
|
||||||
for tunnelConfiguration in tunnelConfigurations {
|
for tunnelConfiguration in tunnelConfigurations {
|
||||||
if let contents = tunnelConfiguration.asWgQuickConfig().data(using: .utf8) {
|
if let contents = tunnelConfiguration.asWgQuickConfig().data(using: .utf8) {
|
||||||
let name = tunnelConfiguration.interface.name ?? ""
|
let name = tunnelConfiguration.name ?? "untitled"
|
||||||
if name.isEmpty || name == lastTunnelName { continue }
|
if name.isEmpty || name == lastTunnelName { continue }
|
||||||
inputsToArchiver.append((fileName: "\(name).conf", contents: contents))
|
inputsToArchiver.append((fileName: "\(name).conf", contents: contents))
|
||||||
lastTunnelName = name
|
lastTunnelName = name
|
||||||
|
|
|
@ -44,7 +44,7 @@ class ZipImporter {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
guard let fileContents = String(data: file.contents, encoding: .utf8) else { continue }
|
guard let fileContents = String(data: file.contents, encoding: .utf8) else { continue }
|
||||||
guard let tunnelConfig = try? TunnelConfiguration(fileContents, name: file.fileBaseName) else { continue }
|
guard let tunnelConfig = try? TunnelConfiguration(fromWgQuickConfig: fileContents, called: file.fileBaseName) else { continue }
|
||||||
configs[index] = tunnelConfig
|
configs[index] = tunnelConfig
|
||||||
}
|
}
|
||||||
DispatchQueue.main.async { completion(.success(configs)) }
|
DispatchQueue.main.async { completion(.success(configs)) }
|
||||||
|
|
|
@ -29,7 +29,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
let errorNotifier = ErrorNotifier(activationAttemptId: activationAttemptId, tunnelProvider: self)
|
let errorNotifier = ErrorNotifier(activationAttemptId: activationAttemptId, tunnelProvider: self)
|
||||||
|
|
||||||
guard let tunnelProviderProtocol = protocolConfiguration as? NETunnelProviderProtocol,
|
guard let tunnelProviderProtocol = protocolConfiguration as? NETunnelProviderProtocol,
|
||||||
let tunnelConfiguration = tunnelProviderProtocol.tunnelConfiguration(name: nil) else {
|
let tunnelConfiguration = tunnelProviderProtocol.asTunnelConfiguration() else {
|
||||||
errorNotifier.notify(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
|
errorNotifier.notify(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
|
||||||
startTunnelCompletionHandler(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
|
startTunnelCompletionHandler(PacketTunnelProviderError.savedProtocolConfigurationIsInvalid)
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue