Compare commits

..

2 Commits

Author SHA1 Message Date
Andrej Mihajlov 2909fdf41e Switch NSCondition to DispatchGroup
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2023-03-06 12:51:05 +01:00
Andrej Mihajlov 3149c50299 Kit: replace path monitor with KVO observer on defaultPath
Signed-off-by: Andrej Mihajlov <and@mullvad.net>
2023-03-06 12:50:44 +01:00
12 changed files with 112 additions and 474 deletions
@@ -206,7 +206,6 @@ class TunnelsManager {
} }
} }
@available(*, renamed: "modify(tunnel:tunnelConfiguration:onDemandOption:shouldEnsureOnDemandEnabled:)")
func modify(tunnel: TunnelContainer, tunnelConfiguration: TunnelConfiguration, func modify(tunnel: TunnelContainer, tunnelConfiguration: TunnelConfiguration,
onDemandOption: ActivateOnDemandOption, onDemandOption: ActivateOnDemandOption,
shouldEnsureOnDemandEnabled: Bool = false, shouldEnsureOnDemandEnabled: Bool = false,
@@ -300,22 +299,6 @@ class TunnelsManager {
} }
} }
@available(iOS 13.0, macOS 10.15.0, *)
func modify(tunnel: TunnelContainer, tunnelConfiguration: TunnelConfiguration,
onDemandOption: ActivateOnDemandOption,
shouldEnsureOnDemandEnabled: Bool = false) async throws {
return try await withCheckedThrowingContinuation { continuation in
modify(tunnel: tunnel, tunnelConfiguration: tunnelConfiguration, onDemandOption: onDemandOption, shouldEnsureOnDemandEnabled: shouldEnsureOnDemandEnabled) { error in
if let error = error {
continuation.resume(throwing: error)
return
}
continuation.resume(returning: ())
}
}
}
func remove(tunnel: TunnelContainer, completionHandler: @escaping (TunnelsManagerError?) -> Void) { func remove(tunnel: TunnelContainer, completionHandler: @escaping (TunnelsManagerError?) -> Void) {
let tunnelProviderManager = tunnel.tunnelProvider let tunnelProviderManager = tunnel.tunnelProvider
#if os(macOS) #if os(macOS)
@@ -3,7 +3,6 @@
import UIKit import UIKit
import os.log import os.log
import AppIntents
@UIApplicationMain @UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate { class AppDelegate: UIResponder, UIApplicationDelegate {
@@ -12,10 +11,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
var mainVC: MainViewController? var mainVC: MainViewController?
var isLaunchedForSpecificAction = false var isLaunchedForSpecificAction = false
var tunnelsManager: TunnelsManager?
static let tunnelsManagerReadyNotificationName: Notification.Name = Notification.Name(rawValue: "com.wireguard.ios.tunnelsManagerReadyNotification")
func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { func application(_ application: UIApplication, willFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
Logger.configureGlobal(tagged: "APP", withFilePath: FileManager.logFileURL?.path) Logger.configureGlobal(tagged: "APP", withFilePath: FileManager.logFileURL?.path)
@@ -34,29 +29,6 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
self.mainVC = mainVC self.mainVC = mainVC
// Create the tunnels manager, and when it's ready, inform tunnelsListVC
TunnelsManager.create { [weak self] result in
guard let self = self else { return }
switch result {
case .failure(let error):
ErrorPresenter.showErrorAlert(error: error, from: self.mainVC)
case .success(let tunnelsManager):
self.tunnelsManager = tunnelsManager
self.mainVC?.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager)
tunnelsManager.activationDelegate = self.mainVC
if #available(iOS 16.0, *) {
AppDependencyManager.shared.add(dependency: tunnelsManager)
}
NotificationCenter.default.post(name: AppDelegate.tunnelsManagerReadyNotificationName,
object: self,
userInfo: nil)
}
}
return true return true
} }
+8 -9
View File
@@ -2,10 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string> <string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleDisplayName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleDocumentTypes</key> <key>CFBundleDocumentTypes</key>
<array> <array>
<dict> <dict>
@@ -64,6 +64,8 @@
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string> <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>CFBundleDisplayName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string> <string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
@@ -72,22 +74,17 @@
<string>$(VERSION_NAME)</string> <string>$(VERSION_NAME)</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>$(VERSION_ID)</string> <string>$(VERSION_ID)</string>
<key>ITSAppUsesNonExemptEncryption</key>
<false/>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>LSSupportsOpeningDocumentsInPlace</key> <key>LSSupportsOpeningDocumentsInPlace</key>
<false/> <false/>
<key>NSCameraUsageDescription</key> <key>NSCameraUsageDescription</key>
<string>Localized</string> <string>Localized</string>
<key>NSFaceIDUsageDescription</key>
<string>Localized</string>
<key>NSUserActivityTypes</key>
<array/>
<key>UILaunchStoryboardName</key> <key>UILaunchStoryboardName</key>
<string>LaunchScreen</string> <string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key> <key>UIRequiredDeviceCapabilities</key>
<array/> <array>
</array>
<key>UISupportedInterfaceOrientations</key> <key>UISupportedInterfaceOrientations</key>
<array> <array>
<string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortrait</string>
@@ -126,6 +123,8 @@
</dict> </dict>
</dict> </dict>
</array> </array>
<key>NSFaceIDUsageDescription</key>
<string>Localized</string>
<key>com.wireguard.ios.app_group_id</key> <key>com.wireguard.ios.app_group_id</key>
<string>group.$(APP_ID_IOS)</string> <string>group.$(APP_ID_IOS)</string>
</dict> </dict>
@@ -5,9 +5,7 @@ import UIKit
class MainViewController: UISplitViewController { class MainViewController: UISplitViewController {
var tunnelsManager: TunnelsManager? { var tunnelsManager: TunnelsManager?
return (UIApplication.shared.delegate as? AppDelegate)?.tunnelsManager
}
var onTunnelsManagerReady: ((TunnelsManager) -> Void)? var onTunnelsManagerReady: ((TunnelsManager) -> Void)?
var tunnelsListVC: TunnelsListTableViewController? var tunnelsListVC: TunnelsListTableViewController?
@@ -40,24 +38,29 @@ class MainViewController: UISplitViewController {
// On iPad, always show both masterVC and detailVC, even in portrait mode, like the Settings app // On iPad, always show both masterVC and detailVC, even in portrait mode, like the Settings app
preferredDisplayMode = .allVisible preferredDisplayMode = .allVisible
NotificationCenter.default.addObserver(self, selector: #selector(handleTunnelsManagerReady(_:)), // Create the tunnels manager, and when it's ready, inform tunnelsListVC
name: AppDelegate.tunnelsManagerReadyNotificationName, object: nil) TunnelsManager.create { [weak self] result in
guard let self = self else { return }
switch result {
case .failure(let error):
ErrorPresenter.showErrorAlert(error: error, from: self)
case .success(let tunnelsManager):
self.tunnelsManager = tunnelsManager
self.tunnelsListVC?.setTunnelsManager(tunnelsManager: tunnelsManager)
tunnelsManager.activationDelegate = self
self.onTunnelsManagerReady?(tunnelsManager)
self.onTunnelsManagerReady = nil
}
}
} }
func allTunnelNames() -> [String]? { func allTunnelNames() -> [String]? {
guard let tunnelsManager = self.tunnelsManager else { return nil } guard let tunnelsManager = self.tunnelsManager else { return nil }
return tunnelsManager.mapTunnels { $0.name } return tunnelsManager.mapTunnels { $0.name }
} }
@objc
func handleTunnelsManagerReady(_ notification: Notification) {
guard let tunnelsManager = self.tunnelsManager else { return }
self.onTunnelsManagerReady?(tunnelsManager)
self.onTunnelsManagerReady = nil
NotificationCenter.default.removeObserver(self, name: AppDelegate.tunnelsManagerReadyNotificationName, object: nil)
}
} }
extension MainViewController: TunnelsManagerActivationDelegate { extension MainViewController: TunnelsManagerActivationDelegate {
@@ -3,7 +3,6 @@
import Cocoa import Cocoa
import ServiceManagement import ServiceManagement
import AppIntents
@NSApplicationMain @NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate { class AppDelegate: NSObject, NSApplicationDelegate {
@@ -59,10 +58,6 @@ class AppDelegate: NSObject, NSApplicationDelegate {
self.tunnelsTracker = tunnelsTracker self.tunnelsTracker = tunnelsTracker
self.statusItemController = statusItemController self.statusItemController = statusItemController
if #available(macOS 13.0, *) {
AppDependencyManager.shared.add(dependency: tunnelsManager)
}
if !isLaunchedAtLogin { if !isLaunchedAtLogin {
self.showManageTunnelsWindow(completion: nil) self.showManageTunnelsWindow(completion: nil)
} }
+66 -30
View File
@@ -47,6 +47,12 @@ public class WireGuardAdapter {
/// Packet tunnel provider. /// Packet tunnel provider.
private weak var packetTunnelProvider: NEPacketTunnelProvider? private weak var packetTunnelProvider: NEPacketTunnelProvider?
/// KVO observer for `NEProvider.defaultPath`.
private var defaultPathObserver: NSKeyValueObservation?
/// Last known default path.
private var currentDefaultPath: NetworkExtension.NWPath?
/// Log handler closure. /// Log handler closure.
private let logHandler: LogHandler private let logHandler: LogHandler
@@ -181,11 +187,7 @@ public class WireGuardAdapter {
return return
} }
let networkMonitor = NWPathMonitor() self.addDefaultPathObserver()
networkMonitor.pathUpdateHandler = { [weak self] path in
self?.didReceivePathUpdate(path: path)
}
networkMonitor.start(queue: self.workQueue)
do { do {
let settingsGenerator = try self.makeSettingsGenerator(with: tunnelConfiguration) let settingsGenerator = try self.makeSettingsGenerator(with: tunnelConfiguration)
@@ -198,10 +200,10 @@ public class WireGuardAdapter {
try self.startWireGuardBackend(wgConfig: wgConfig), try self.startWireGuardBackend(wgConfig: wgConfig),
settingsGenerator settingsGenerator
) )
self.networkMonitor = networkMonitor
completionHandler(nil) completionHandler(nil)
} catch let error as WireGuardAdapterError { } catch let error as WireGuardAdapterError {
networkMonitor.cancel() self.removeDefaultPathObserver()
completionHandler(error) completionHandler(error)
} catch { } catch {
fatalError() fatalError()
@@ -225,8 +227,7 @@ public class WireGuardAdapter {
return return
} }
self.networkMonitor?.cancel() self.removeDefaultPathObserver()
self.networkMonitor = nil
self.state = .stopped self.state = .stopped
@@ -313,26 +314,29 @@ public class WireGuardAdapter {
/// - Returns: `PacketTunnelSettingsGenerator`. /// - Returns: `PacketTunnelSettingsGenerator`.
private func setNetworkSettings(_ networkSettings: NEPacketTunnelNetworkSettings) throws { private func setNetworkSettings(_ networkSettings: NEPacketTunnelNetworkSettings) throws {
var systemError: Error? var systemError: Error?
let condition = NSCondition()
// Activate the condition let dispatchGroup = DispatchGroup()
condition.lock()
defer { condition.unlock() } dispatchGroup.enter()
self.packetTunnelProvider?.setTunnelNetworkSettings(networkSettings) { error in self.packetTunnelProvider?.setTunnelNetworkSettings(networkSettings) { error in
systemError = error systemError = error
condition.signal() dispatchGroup.leave()
} }
// Packet tunnel's `setTunnelNetworkSettings` times out in certain // Packet tunnel's `setTunnelNetworkSettings` times out in certain
// scenarios & never calls the given callback. // scenarios & never calls the given callback.
let setTunnelNetworkSettingsTimeout: TimeInterval = 5 // seconds let setTunnelNetworkSettingsTimeout: Int = 5 // seconds
if condition.wait(until: Date().addingTimeInterval(setTunnelNetworkSettingsTimeout)) { let waitResult = dispatchGroup.wait(wallTimeout: .now() + .seconds(setTunnelNetworkSettingsTimeout))
switch waitResult {
case .success:
if let systemError = systemError { if let systemError = systemError {
throw WireGuardAdapterError.setNetworkSettings(systemError) throw WireGuardAdapterError.setNetworkSettings(systemError)
} }
} else {
case .timedOut:
self.logHandler(.error, "setTunnelNetworkSettings timed out after 5 seconds; proceeding anyway") self.logHandler(.error, "setTunnelNetworkSettings timed out after 5 seconds; proceeding anyway")
} }
} }
@@ -411,19 +415,48 @@ public class WireGuardAdapter {
} }
} }
/// Helper method used by network path monitor. private func addDefaultPathObserver() {
guard let packetTunnelProvider = packetTunnelProvider else { return }
defaultPathObserver?.invalidate()
defaultPathObserver = packetTunnelProvider.observe(\.defaultPath, options: [.new]) { [weak self] _, change in
guard let self = self, let defaultPath = change.newValue?.flatMap({ $0 }) else { return }
self.workQueue.async {
self.didReceivePathUpdate(path: defaultPath)
}
}
currentDefaultPath = packetTunnelProvider.defaultPath
}
private func removeDefaultPathObserver() {
defaultPathObserver?.invalidate()
defaultPathObserver = nil
currentDefaultPath = nil
}
/// Method invoked by KVO observer when new network path is received.
/// - Parameter path: new network path /// - Parameter path: new network path
private func didReceivePathUpdate(path: Network.NWPath) { private func didReceivePathUpdate(path: NetworkExtension.NWPath) {
self.logHandler(.verbose, "Network change detected with \(path.status) route and interface order \(path.availableInterfaces)") let isSamePath = currentDefaultPath?.isEqual(to: path) ?? false
currentDefaultPath = path
self.logHandler(.verbose, "Network change detected with \(path.status)")
#if os(macOS) #if os(macOS)
if case .started(let handle, _) = self.state { if case .started(let handle, _) = self.state, !isSamePath {
wgBumpSockets(handle) wgBumpSockets(handle)
} }
#elseif os(iOS) #elseif os(iOS)
let isSatisfiable = path.status == .satisfied || path.status == .satisfiable
switch self.state { switch self.state {
case .started(let handle, let settingsGenerator): case .started(let handle, let settingsGenerator):
if path.status.isSatisfiable { if isSatisfiable {
guard !isSamePath else { return }
let (wgConfig, resolutionResults) = settingsGenerator.endpointUapiConfiguration() let (wgConfig, resolutionResults) = settingsGenerator.endpointUapiConfiguration()
self.logEndpointResolutionResults(resolutionResults) self.logEndpointResolutionResults(resolutionResults)
@@ -438,7 +471,7 @@ public class WireGuardAdapter {
} }
case .temporaryShutdown(let settingsGenerator): case .temporaryShutdown(let settingsGenerator):
guard path.status.isSatisfiable else { return } guard isSatisfiable else { return }
self.logHandler(.verbose, "Connectivity online, resuming backend.") self.logHandler(.verbose, "Connectivity online, resuming backend.")
@@ -472,16 +505,19 @@ public enum WireGuardLogLevel: Int32 {
case error = 1 case error = 1
} }
private extension Network.NWPath.Status { extension NetworkExtension.NWPathStatus: CustomDebugStringConvertible {
/// Returns `true` if the path is potentially satisfiable. public var debugDescription: String {
var isSatisfiable: Bool {
switch self { switch self {
case .requiresConnection, .satisfied:
return true
case .unsatisfied: case .unsatisfied:
return false return "unsatisfied"
case .satisfied:
return "satisfied"
case .satisfiable:
return "satisfiable"
case .invalid:
return "invalid"
@unknown default: @unknown default:
return true return "unknown (rawValue = \(rawValue))"
} }
} }
} }
@@ -1,35 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved.
// App Intents Common
"wireguardAppIntentsWrongTunnelError %@" = "Cannot find a tunnel with the name \"%1$@\"";
"wireguardAppIntentsMissingConfigurationError" = "The selected tunnel has no configuration.";
// Get peers Intent
"getPeersIntentName" = "Get Peers";
"getPeersIntentDescription" = "Get list of public keys of peers in the selected configuration";
"getPeersIntentTunnelParameterTitle" = "Tunnel";
"getPeersIntentSummary ${tunnelName}" = "Get peers of ${tunnelName}";
// Tunnel Configuration Update
"updateTunnelConfigurationIntentName" = "Update Tunnel Configuration";
"updateTunnelConfigurationDescription" = "Update peers configuration of the selected tunnel.";
"updateTunnelConfigurationIntentTunnelParameterTitle" = "Tunnel";
"updateTunnelConfigurationIntentPeersParameterTitle" = "Peers";
"updateTunnelConfigurationIntentMergeParameterTitle" = "Merge configuration";
"updateTunnelConfigurationIntentSummary ${tunnelName}" = "Update ${tunnelName} configuration";
"updateTunnelConfigurationIntentPeerOptionsUnavailableError" = "Use the output of \"Build Peer Configuration\" action to update tunnel configuration. To update multiple peers at once, you can use the \"Add to Variable\" action and pass the resulting Variable in this field.";
"updateTunnelConfigurationIntentMalformedPublicKeyError %@" = "The key \"%1$@\" is not a valid Public Key encoded in Base64 format.";
// Build Peer Configuration
"buildPeerConfigurationUpdateIntentName" = "Build Peer Configuration";
"buildPeerConfigurationUpdateIntentDescription" = "Build an item that contains the informations needed to update an peer's configuration.";
"buildPeerConfigurationUpdateIntentSummary ${publicKey}" = "Build configuration for peer ${publicKey}";
"buildPeerConfigurationUpdateIntentPublicKeyParameterTitle" = "Peer Public Key";
"buildPeerConfigurationUpdateIntentEndpointParameterTitle" = "Endpoint";
// Peer Configuration Update Entity
"peerConfigurationUpdateEntityName" = "Configuration Update - Peer";
"peerConfigurationUpdateEntityPropertyPublicKeyTitle" = "Public Key";
"peerConfigurationUpdateEntityPropertyEndpointTitle" = "Endpoint";
@@ -1,77 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved.
import AppIntents
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
struct BuildPeerConfigurationUpdate: AppIntent {
static var title = LocalizedStringResource("buildPeerConfigurationUpdateIntentName", table: "AppIntents")
static var description = IntentDescription(
LocalizedStringResource("buildPeerConfigurationUpdateIntentDescription", table: "AppIntents")
)
@Parameter(
title: LocalizedStringResource("buildPeerConfigurationUpdateIntentPublicKeyParameterTitle", table: "AppIntents")
)
var publicKey: String
@Parameter(
title: LocalizedStringResource("buildPeerConfigurationUpdateIntentEndpointParameterTitle", table: "AppIntents")
)
var endpoint: String
func perform() async throws -> some IntentResult & ReturnsValue<AppIntentsPeer> {
let peerConfigurationUpdate = AppIntentsPeer()
peerConfigurationUpdate.publicKey = publicKey
peerConfigurationUpdate.endpoint = endpoint
return .result(value: peerConfigurationUpdate)
}
static var parameterSummary: some ParameterSummary {
Summary("buildPeerConfigurationUpdateIntentSummary \(\.$publicKey)", table: "AppIntents") {
\.$endpoint
}
}
}
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
struct AppIntentsPeer: TransientAppEntity {
static let kEndpointConfigUpdateDictionaryKey = "Endpoint"
static var typeDisplayRepresentation = TypeDisplayRepresentation(
name: LocalizedStringResource("peerConfigurationUpdateEntityName", table: "AppIntents")
)
@Property(
title: LocalizedStringResource("peerConfigurationUpdateEntityPropertyPublicKeyTitle", table: "AppIntents")
)
var publicKey: String
@Property(
title: LocalizedStringResource("peerConfigurationUpdateEntityPropertyEndpointTitle", table: "AppIntents")
)
var endpoint: String?
var displayRepresentation: DisplayRepresentation {
var dictionary: [String: [String: String]] = [:]
dictionary[publicKey] = [:]
if let endpoint {
dictionary[publicKey]?.updateValue(endpoint, forKey: Self.kEndpointConfigUpdateDictionaryKey)
}
let jsonData: Data
do {
jsonData = try JSONSerialization.data(withJSONObject: dictionary)
} catch {
return DisplayRepresentation(stringLiteral: error.localizedDescription)
}
let jsonString = String(data: jsonData, encoding: .utf8)!
return DisplayRepresentation(stringLiteral: jsonString)
}
}
@@ -1,55 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved.
import Foundation
import AppIntents
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
struct GetPeers: AppIntent {
static var title = LocalizedStringResource("getPeersIntentName", table: "AppIntents")
static var description = IntentDescription(
LocalizedStringResource("getPeersIntentDescription", table: "AppIntents")
)
@Parameter(
title: LocalizedStringResource("getPeersIntentTunnelParameterTitle", table: "AppIntents"),
optionsProvider: TunnelsOptionsProvider()
)
var tunnelName: String
@Dependency
var tunnelsManager: TunnelsManager
func perform() async throws -> some IntentResult & ReturnsValue<[String]> {
guard let tunnelContainer = tunnelsManager.tunnel(named: tunnelName) else {
throw GetPeersIntentError.wrongTunnel(name: tunnelName)
}
guard let tunnelConfiguration = tunnelContainer.tunnelConfiguration else {
throw GetPeersIntentError.missingConfiguration
}
let publicKeys = tunnelConfiguration.peers.map { $0.publicKey.base64Key }
return .result(value: publicKeys)
}
static var parameterSummary: some ParameterSummary {
Summary("getPeersIntentSummary \(\.$tunnelName)", table: "AppIntents")
}
}
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
enum GetPeersIntentError: Swift.Error, CustomLocalizedStringResourceConvertible {
case wrongTunnel(name: String)
case missingConfiguration
var localizedStringResource: LocalizedStringResource {
switch self {
case .wrongTunnel(let name):
return LocalizedStringResource("wireguardAppIntentsWrongTunnelError \(name)", table: "AppIntents")
case .missingConfiguration:
return LocalizedStringResource("wireguardAppIntentsMissingConfigurationError", table: "AppIntents")
}
}
}
@@ -1,15 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved.
import AppIntents
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
struct TunnelsOptionsProvider: DynamicOptionsProvider {
@Dependency
var tunnelsManager: TunnelsManager
func results() async throws -> [String] {
let tunnelsNames = tunnelsManager.mapTunnels { $0.name }
return tunnelsNames
}
}
@@ -1,131 +0,0 @@
// SPDX-License-Identifier: MIT
// Copyright © 2018-2021 WireGuard LLC. All Rights Reserved.
import AppIntents
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
struct UpdateTunnelConfiguration: AppIntent {
static var title = LocalizedStringResource("updateTunnelConfigurationIntentName", table: "AppIntents")
static var description = IntentDescription(
LocalizedStringResource("updateTunnelConfigurationDescription", table: "AppIntents")
)
@Parameter(
title: LocalizedStringResource("updateTunnelConfigurationIntentTunnelParameterTitle", table: "AppIntents"),
optionsProvider: TunnelsOptionsProvider()
)
var tunnelName: String
@Parameter(
title: LocalizedStringResource("updateTunnelConfigurationIntentPeersParameterTitle", table: "AppIntents"),
optionsProvider: AppIntentsPeerOptionsProvider()
)
var peers: [AppIntentsPeer]?
@Parameter(
title: LocalizedStringResource("updateTunnelConfigurationIntentMergeParameterTitle", table: "AppIntents"),
default: true
)
var mergeConfiguration: Bool
@Dependency
var tunnelsManager: TunnelsManager
func perform() async throws -> some IntentResult {
let peers = peers ?? []
guard let tunnelContainer = tunnelsManager.tunnel(named: tunnelName) else {
throw AppIntentConfigurationUpdateError.wrongTunnel(name: tunnelName)
}
guard let tunnelConfiguration = tunnelContainer.tunnelConfiguration else {
throw AppIntentConfigurationUpdateError.missingConfiguration
}
let newConfiguration = try buildNewConfiguration(from: tunnelConfiguration, peersUpdates: peers, mergeChanges: mergeConfiguration)
do {
try await tunnelsManager.modify(tunnel: tunnelContainer, tunnelConfiguration: newConfiguration, onDemandOption: tunnelContainer.onDemandOption)
} catch {
wg_log(.error, message: error.localizedDescription)
throw error
}
wg_log(.debug, message: "Updated configuration of tunnel \(tunnelName)")
return .result()
}
static var parameterSummary: some ParameterSummary {
Summary("updateTunnelConfigurationIntentSummary \(\.$tunnelName)", table: "AppIntents") {
\.$peers
\.$mergeConfiguration
}
}
private func buildNewConfiguration(from oldConfiguration: TunnelConfiguration, peersUpdates: [AppIntentsPeer], mergeChanges: Bool) throws -> TunnelConfiguration {
var peers = oldConfiguration.peers
for peerUpdate in peersUpdates {
let peerIndex: Array<PeerConfiguration>.Index
if let foundIndex = peers.firstIndex(where: { $0.publicKey.base64Key == peerUpdate.publicKey }) {
peerIndex = foundIndex
if mergeChanges == false {
peers[peerIndex] = PeerConfiguration(publicKey: peers[peerIndex].publicKey)
}
} else {
wg_log(.debug, message: "Failed to find peer \(peerUpdate.publicKey) in tunnel with name \(tunnelName). Adding it.")
guard let pubKeyEncoded = PublicKey(base64Key: peerUpdate.publicKey) else {
throw AppIntentConfigurationUpdateError.malformedPublicKey(key: peerUpdate.publicKey)
}
let newPeerConfig = PeerConfiguration(publicKey: pubKeyEncoded)
peerIndex = peers.endIndex
peers.append(newPeerConfig)
}
if let endpointString = peerUpdate.endpoint {
if let newEntpoint = Endpoint(from: endpointString) {
peers[peerIndex].endpoint = newEntpoint
} else {
wg_log(.debug, message: "Failed to convert \(endpointString) to Endpoint")
}
}
}
let newConfiguration = TunnelConfiguration(name: oldConfiguration.name, interface: oldConfiguration.interface, peers: peers)
return newConfiguration
}
}
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
struct AppIntentsPeerOptionsProvider: DynamicOptionsProvider {
func results() async throws -> ItemCollection<AppIntentsPeer> {
// The error thrown here is not displayed correctly to the user. A Feedback
// has been opened (FB12098463).
throw AppIntentConfigurationUpdateError.peerOptionsUnavailable
}
}
@available(iOS 16.0, macOS 13.0, watchOS 9.0, tvOS 16.0, *)
enum AppIntentConfigurationUpdateError: Swift.Error, CustomLocalizedStringResourceConvertible {
case wrongTunnel(name: String)
case missingConfiguration
case peerOptionsUnavailable
case malformedPublicKey(key: String)
var localizedStringResource: LocalizedStringResource {
switch self {
case .wrongTunnel(let name):
return LocalizedStringResource("wireguardAppIntentsWrongTunnelError \(name)", table: "AppIntents")
case .missingConfiguration:
return LocalizedStringResource("wireguardAppIntentsMissingConfigurationError", table: "AppIntents")
case .peerOptionsUnavailable:
return LocalizedStringResource("updateTunnelConfigurationIntentPeerOptionsUnavailableError", table: "AppIntents")
case .malformedPublicKey(let malformedKey):
return LocalizedStringResource("updateTunnelConfigurationIntentMalformedPublicKeyError \(malformedKey)", table: "AppIntents")
}
}
}
+20 -57
View File
@@ -205,16 +205,6 @@
6FFA5DA021958ECC0001E2F7 /* ErrorNotifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5D9F21958ECC0001E2F7 /* ErrorNotifier.swift */; }; 6FFA5DA021958ECC0001E2F7 /* ErrorNotifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5D9F21958ECC0001E2F7 /* ErrorNotifier.swift */; };
6FFA5DA42197085D0001E2F7 /* ActivateOnDemandOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5DA32197085D0001E2F7 /* ActivateOnDemandOption.swift */; }; 6FFA5DA42197085D0001E2F7 /* ActivateOnDemandOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFA5DA32197085D0001E2F7 /* ActivateOnDemandOption.swift */; };
6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFACD1E21E4D89600E9A2A5 /* ParseError+WireGuardAppError.swift */; }; 6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6FFACD1E21E4D89600E9A2A5 /* ParseError+WireGuardAppError.swift */; };
A25DF37029E60E870094E89B /* BuildPeerConfigurationUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E361FB29D9AEEA00FFF234 /* BuildPeerConfigurationUpdate.swift */; };
A25DF37129E60E8C0094E89B /* UpdateTunnelConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E361F929D9821100FFF234 /* UpdateTunnelConfiguration.swift */; };
A25DF37229E60E8F0094E89B /* GetPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A625F05029C4C627005EF23D /* GetPeers.swift */; };
A25DF37329E60E930094E89B /* AppIntents.strings in Resources */ = {isa = PBXBuildFile; fileRef = A6E361F729D8758500FFF234 /* AppIntents.strings */; };
A25DF37429E60E960094E89B /* TunnelsOptionsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E361FD29D9B18C00FFF234 /* TunnelsOptionsProvider.swift */; };
A625F05529C4C627005EF23D /* GetPeers.swift in Sources */ = {isa = PBXBuildFile; fileRef = A625F05029C4C627005EF23D /* GetPeers.swift */; };
A6E361F829D8758500FFF234 /* AppIntents.strings in Resources */ = {isa = PBXBuildFile; fileRef = A6E361F729D8758500FFF234 /* AppIntents.strings */; };
A6E361FA29D9821200FFF234 /* UpdateTunnelConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E361F929D9821100FFF234 /* UpdateTunnelConfiguration.swift */; };
A6E361FC29D9AEEA00FFF234 /* BuildPeerConfigurationUpdate.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E361FB29D9AEEA00FFF234 /* BuildPeerConfigurationUpdate.swift */; };
A6E361FE29D9B18C00FFF234 /* TunnelsOptionsProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = A6E361FD29D9B18C00FFF234 /* TunnelsOptionsProvider.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
@@ -357,6 +347,8 @@
6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchedAtLoginDetector.swift; sourceTree = "<group>"; }; 6F6483E6229293300075BA15 /* LaunchedAtLoginDetector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LaunchedAtLoginDetector.swift; sourceTree = "<group>"; };
6F689999218043390012E523 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; }; 6F689999218043390012E523 /* WireGuard-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WireGuard-Bridging-Header.h"; sourceTree = "<group>"; };
6F70E20D221058DF008BDFB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Sources/WireGuardApp/Base.lproj/InfoPlist.strings; sourceTree = "<group>"; }; 6F70E20D221058DF008BDFB4 /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Sources/WireGuardApp/Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
6F70E20D221058DF008BDFBA /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "Sources/WireGuardApp/zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
6F70E20D221058DF008BDFC6 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "Sources/WireGuardApp/zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; };
6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WireGuardLoginItemHelper.app; sourceTree = BUILT_PRODUCTS_DIR; }; 6F70E22922106A2D008BDFB4 /* WireGuardLoginItemHelper.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = WireGuardLoginItemHelper.app; sourceTree = BUILT_PRODUCTS_DIR; };
6F70E23222106A31008BDFB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; 6F70E23222106A31008BDFB4 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
6F70E23922109BEF008BDFB4 /* LoginItemHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LoginItemHelper.entitlements; sourceTree = "<group>"; }; 6F70E23922109BEF008BDFB4 /* LoginItemHelper.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = LoginItemHelper.entitlements; sourceTree = "<group>"; };
@@ -412,24 +404,24 @@
6FDEF801218646B900D8FBF6 /* ZipArchive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipArchive.swift; sourceTree = "<group>"; }; 6FDEF801218646B900D8FBF6 /* ZipArchive.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ZipArchive.swift; sourceTree = "<group>"; };
6FDEF805218725D200D8FBF6 /* SettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsTableViewController.swift; sourceTree = "<group>"; }; 6FDEF805218725D200D8FBF6 /* SettingsTableViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsTableViewController.swift; sourceTree = "<group>"; };
6FE1765521C90BBE002690EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Sources/WireGuardApp/Base.lproj/Localizable.strings; sourceTree = "<group>"; }; 6FE1765521C90BBE002690EA /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Sources/WireGuardApp/Base.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EB /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = Sources/WireGuardApp/fr.lproj/Localizable.strings; sourceTree = "<group>"; }; 6FE1765521C90BBE002690FC /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh-Hant; path = Sources/WireGuardApp/zh-Hant.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EC /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = Sources/WireGuardApp/pl.lproj/Localizable.strings; sourceTree = "<group>"; }; 6FE1765521C90BBE002690F0 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh-Hans; path = Sources/WireGuardApp/zh-Hans.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690ED /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Sources/WireGuardApp/es.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EE /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = Sources/WireGuardApp/ca.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EF /* pa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pa; path = Sources/WireGuardApp/pa.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F0 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "Sources/WireGuardApp/zh-Hans.lproj/Localizable.strings"; sourceTree = "<group>"; };
6FE1765521C90BBE002690F1 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Sources/WireGuardApp/ja.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F2 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = Sources/WireGuardApp/it.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F3 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = Sources/WireGuardApp/ro.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F4 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = Sources/WireGuardApp/fa.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F5 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = Sources/WireGuardApp/fi.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F6 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = Sources/WireGuardApp/ru.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F7 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = Sources/WireGuardApp/ko.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F8 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = Sources/WireGuardApp/tr.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F9 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Sources/WireGuardApp/de.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690FA /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = Sources/WireGuardApp/sl.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690FB /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = Sources/WireGuardApp/id.lproj/Localizable.strings; sourceTree = "<group>"; }; 6FE1765521C90BBE002690FB /* id */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = id; path = Sources/WireGuardApp/id.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690FC /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "Sources/WireGuardApp/zh-Hant.lproj/Localizable.strings"; sourceTree = "<group>"; }; 6FE1765521C90BBE002690F2 /* it */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = it; path = Sources/WireGuardApp/it.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F9 /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = Sources/WireGuardApp/de.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EB /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = Sources/WireGuardApp/fr.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F5 /* fi */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fi; path = Sources/WireGuardApp/fi.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F4 /* fa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fa; path = Sources/WireGuardApp/fa.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690FA /* sl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sl; path = Sources/WireGuardApp/sl.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EC /* pl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pl; path = Sources/WireGuardApp/pl.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EF /* pa */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = pa; path = Sources/WireGuardApp/pa.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F7 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = Sources/WireGuardApp/ko.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690EE /* ca */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ca; path = Sources/WireGuardApp/ca.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F6 /* ru */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ru; path = Sources/WireGuardApp/ru.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F3 /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = Sources/WireGuardApp/ro.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F8 /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = Sources/WireGuardApp/tr.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690F1 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = Sources/WireGuardApp/ja.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765521C90BBE002690ED /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = Sources/WireGuardApp/es.lproj/Localizable.strings; sourceTree = "<group>"; };
6FE1765921C90E87002690EA /* LocalizationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationHelper.swift; sourceTree = "<group>"; }; 6FE1765921C90E87002690EA /* LocalizationHelper.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizationHelper.swift; sourceTree = "<group>"; };
6FE254FA219C10800028284D /* ZipImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZipImporter.swift; sourceTree = "<group>"; }; 6FE254FA219C10800028284D /* ZipImporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZipImporter.swift; sourceTree = "<group>"; };
6FE254FE219C60290028284D /* ZipExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZipExporter.swift; sourceTree = "<group>"; }; 6FE254FE219C60290028284D /* ZipExporter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ZipExporter.swift; sourceTree = "<group>"; };
@@ -448,11 +440,6 @@
6FFA5D9F21958ECC0001E2F7 /* ErrorNotifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorNotifier.swift; sourceTree = "<group>"; }; 6FFA5D9F21958ECC0001E2F7 /* ErrorNotifier.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ErrorNotifier.swift; sourceTree = "<group>"; };
6FFA5DA32197085D0001E2F7 /* ActivateOnDemandOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivateOnDemandOption.swift; sourceTree = "<group>"; }; 6FFA5DA32197085D0001E2F7 /* ActivateOnDemandOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ActivateOnDemandOption.swift; sourceTree = "<group>"; };
6FFACD1E21E4D89600E9A2A5 /* ParseError+WireGuardAppError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseError+WireGuardAppError.swift"; sourceTree = "<group>"; }; 6FFACD1E21E4D89600E9A2A5 /* ParseError+WireGuardAppError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ParseError+WireGuardAppError.swift"; sourceTree = "<group>"; };
A625F05029C4C627005EF23D /* GetPeers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GetPeers.swift; sourceTree = "<group>"; };
A6E361F729D8758500FFF234 /* AppIntents.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = AppIntents.strings; sourceTree = "<group>"; };
A6E361F929D9821100FFF234 /* UpdateTunnelConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UpdateTunnelConfiguration.swift; sourceTree = "<group>"; };
A6E361FB29D9AEEA00FFF234 /* BuildPeerConfigurationUpdate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BuildPeerConfigurationUpdate.swift; sourceTree = "<group>"; };
A6E361FD29D9B18C00FFF234 /* TunnelsOptionsProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TunnelsOptionsProvider.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
@@ -775,7 +762,6 @@
6FF4AC0B211EC46F002C96EB = { 6FF4AC0B211EC46F002C96EB = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
A625F04C29C4C627005EF23D /* WireguardAppIntents */,
6F70E20C221058DF008BDFB4 /* InfoPlist.strings */, 6F70E20C221058DF008BDFB4 /* InfoPlist.strings */,
6FE1765421C90BBE002690EA /* Localizable.strings */, 6FE1765421C90BBE002690EA /* Localizable.strings */,
6F5D0C432183B4A4000F85AD /* Shared */, 6F5D0C432183B4A4000F85AD /* Shared */,
@@ -827,19 +813,6 @@
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
A625F04C29C4C627005EF23D /* WireguardAppIntents */ = {
isa = PBXGroup;
children = (
A6E361F929D9821100FFF234 /* UpdateTunnelConfiguration.swift */,
A6E361FB29D9AEEA00FFF234 /* BuildPeerConfigurationUpdate.swift */,
A625F05029C4C627005EF23D /* GetPeers.swift */,
A6E361F729D8758500FFF234 /* AppIntents.strings */,
A6E361FD29D9B18C00FFF234 /* TunnelsOptionsProvider.swift */,
);
name = WireguardAppIntents;
path = Sources/WireguardAppIntents;
sourceTree = "<group>";
};
/* End PBXGroup section */ /* End PBXGroup section */
/* Begin PBXLegacyTarget section */ /* Begin PBXLegacyTarget section */
@@ -987,7 +960,7 @@
6FF4AC0C211EC46F002C96EB /* Project object */ = { 6FF4AC0C211EC46F002C96EB /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastSwiftUpdateCheck = 1320; LastSwiftUpdateCheck = 1010;
LastUpgradeCheck = 1010; LastUpgradeCheck = 1010;
ORGANIZATIONNAME = "WireGuard LLC"; ORGANIZATIONNAME = "WireGuard LLC";
TargetAttributes = { TargetAttributes = {
@@ -1105,7 +1078,6 @@
files = ( files = (
6FB1BD6221D2607E00A991BF /* Assets.xcassets in Resources */, 6FB1BD6221D2607E00A991BF /* Assets.xcassets in Resources */,
6F70E20F221058E1008BDFB4 /* InfoPlist.strings in Resources */, 6F70E20F221058E1008BDFB4 /* InfoPlist.strings in Resources */,
A25DF37329E60E930094E89B /* AppIntents.strings in Resources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@@ -1125,7 +1097,6 @@
6FE1765621C90BBE002690EA /* Localizable.strings in Resources */, 6FE1765621C90BBE002690EA /* Localizable.strings in Resources */,
6FF4AC22211EC472002C96EB /* LaunchScreen.storyboard in Resources */, 6FF4AC22211EC472002C96EB /* LaunchScreen.storyboard in Resources */,
6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */, 6F919EDA218C65C50023B400 /* wireguard_doc_logo_44x58.png in Resources */,
A6E361F829D8758500FFF234 /* AppIntents.strings in Resources */,
6FF4AC1F211EC472002C96EB /* Assets.xcassets in Resources */, 6FF4AC1F211EC472002C96EB /* Assets.xcassets in Resources */,
6F919EDB218C65C50023B400 /* wireguard_doc_logo_64x64.png in Resources */, 6F919EDB218C65C50023B400 /* wireguard_doc_logo_64x64.png in Resources */,
6F919EDC218C65C50023B400 /* wireguard_doc_logo_320x320.png in Resources */, 6F919EDC218C65C50023B400 /* wireguard_doc_logo_320x320.png in Resources */,
@@ -1334,7 +1305,6 @@
6FB1BDD121D50F5300A991BF /* ZipImporter.swift in Sources */, 6FB1BDD121D50F5300A991BF /* ZipImporter.swift in Sources */,
6FB1BDD221D50F5300A991BF /* ZipExporter.swift in Sources */, 6FB1BDD221D50F5300A991BF /* ZipExporter.swift in Sources */,
585B10642577E294004F691E /* DNSServer.swift in Sources */, 585B10642577E294004F691E /* DNSServer.swift in Sources */,
A25DF37129E60E8C0094E89B /* UpdateTunnelConfiguration.swift in Sources */,
585B108C2577E294004F691E /* Endpoint.swift in Sources */, 585B108C2577E294004F691E /* Endpoint.swift in Sources */,
6FBA104621D7EBFA0051C35F /* TunnelsListTableViewController.swift in Sources */, 6FBA104621D7EBFA0051C35F /* TunnelsListTableViewController.swift in Sources */,
6FB1BDD321D50F5300A991BF /* ZipArchive.swift in Sources */, 6FB1BDD321D50F5300A991BF /* ZipArchive.swift in Sources */,
@@ -1372,13 +1342,11 @@
6FE3661D21F64F6B00F78C7D /* ConfTextColorTheme.swift in Sources */, 6FE3661D21F64F6B00F78C7D /* ConfTextColorTheme.swift in Sources */,
6F3E02E9228000F6001FE7E3 /* MainMenu.swift in Sources */, 6F3E02E9228000F6001FE7E3 /* MainMenu.swift in Sources */,
5F52D0BF21E3788900283CEA /* NSColor+Hex.swift in Sources */, 5F52D0BF21E3788900283CEA /* NSColor+Hex.swift in Sources */,
A25DF37229E60E8F0094E89B /* GetPeers.swift in Sources */,
6FB1BDBE21D50F0200A991BF /* Logger.swift in Sources */, 6FB1BDBE21D50F0200A991BF /* Logger.swift in Sources */,
6F6483E7229293300075BA15 /* LaunchedAtLoginDetector.swift in Sources */, 6F6483E7229293300075BA15 /* LaunchedAtLoginDetector.swift in Sources */,
6FB1BDBF21D50F0200A991BF /* TunnelConfiguration+WgQuickConfig.swift in Sources */, 6FB1BDBF21D50F0200A991BF /* TunnelConfiguration+WgQuickConfig.swift in Sources */,
6FADE96C2254B8C300B838A4 /* UnusableTunnelDetailViewController.swift in Sources */, 6FADE96C2254B8C300B838A4 /* UnusableTunnelDetailViewController.swift in Sources */,
6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */, 6FFACD2021E4D8D500E9A2A5 /* ParseError+WireGuardAppError.swift in Sources */,
A25DF37029E60E870094E89B /* BuildPeerConfigurationUpdate.swift in Sources */,
6FB1BDC021D50F0200A991BF /* NETunnelProviderProtocol+Extension.swift in Sources */, 6FB1BDC021D50F0200A991BF /* NETunnelProviderProtocol+Extension.swift in Sources */,
6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */, 6F1075642258AE9800D78929 /* DeleteTunnelsConfirmationAlert.swift in Sources */,
6FBA101821D656000051C35F /* StatusMenu.swift in Sources */, 6FBA101821D656000051C35F /* StatusMenu.swift in Sources */,
@@ -1389,7 +1357,6 @@
6FBA104021D6B7040051C35F /* ErrorPresenterProtocol.swift in Sources */, 6FBA104021D6B7040051C35F /* ErrorPresenterProtocol.swift in Sources */,
6FCD99AA21E0E14700BA4C82 /* ButtonedDetailViewController.swift in Sources */, 6FCD99AA21E0E14700BA4C82 /* ButtonedDetailViewController.swift in Sources */,
6FBA104321D6BC250051C35F /* ErrorPresenter.swift in Sources */, 6FBA104321D6BC250051C35F /* ErrorPresenter.swift in Sources */,
A25DF37429E60E960094E89B /* TunnelsOptionsProvider.swift in Sources */,
6F2449E8226587B90047B9E9 /* MacAppStoreUpdateDetector.swift in Sources */, 6F2449E8226587B90047B9E9 /* MacAppStoreUpdateDetector.swift in Sources */,
585B105C2577E293004F691E /* InterfaceConfiguration.swift in Sources */, 585B105C2577E293004F691E /* InterfaceConfiguration.swift in Sources */,
6F907C9D224663A2003CED21 /* LogViewHelper.swift in Sources */, 6F907C9D224663A2003CED21 /* LogViewHelper.swift in Sources */,
@@ -1440,7 +1407,6 @@
6FF3527221C2616C0008484E /* ringlogger.c in Sources */, 6FF3527221C2616C0008484E /* ringlogger.c in Sources */,
6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */, 6F0F44CB222D55FD00B0FF04 /* EditableTextCell.swift in Sources */,
585B105E2577E293004F691E /* PeerConfiguration.swift in Sources */, 585B105E2577E293004F691E /* PeerConfiguration.swift in Sources */,
A6E361FA29D9821200FFF234 /* UpdateTunnelConfiguration.swift in Sources */,
6FF3527321C2616C0008484E /* Logger.swift in Sources */, 6FF3527321C2616C0008484E /* Logger.swift in Sources */,
6F7774E421718281006A79B3 /* TunnelsListTableViewController.swift in Sources */, 6F7774E421718281006A79B3 /* TunnelsListTableViewController.swift in Sources */,
585B108E2577E294004F691E /* x25519.c in Sources */, 585B108E2577E294004F691E /* x25519.c in Sources */,
@@ -1455,10 +1421,8 @@
6FDB6D18224CC05A00EE4BC3 /* LogViewController.swift in Sources */, 6FDB6D18224CC05A00EE4BC3 /* LogViewController.swift in Sources */,
6FFA5D952194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift in Sources */, 6FFA5D952194454A0001E2F7 /* NETunnelProviderProtocol+Extension.swift in Sources */,
5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */, 5F4541A921C451D100994C13 /* TunnelStatus.swift in Sources */,
A625F05529C4C627005EF23D /* GetPeers.swift in Sources */,
6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */, 6F8F0D7422267AD2000E8335 /* ChevronCell.swift in Sources */,
6F61F1E921B932F700483816 /* WireGuardAppError.swift in Sources */, 6F61F1E921B932F700483816 /* WireGuardAppError.swift in Sources */,
A6E361FE29D9B18C00FFF234 /* TunnelsOptionsProvider.swift in Sources */,
6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */, 6F7774E2217181B1006A79B3 /* AppDelegate.swift in Sources */,
6FDEF80021863C0100D8FBF6 /* ioapi.c in Sources */, 6FDEF80021863C0100D8FBF6 /* ioapi.c in Sources */,
6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */, 6F7F7E5F21C7D74B00527607 /* TunnelErrors.swift in Sources */,
@@ -1473,7 +1437,6 @@
6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */, 6F919EC3218A2AE90023B400 /* ErrorPresenter.swift in Sources */,
6B62E45F220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */, 6B62E45F220A6FA900EF34A6 /* PrivateDataConfirmation.swift in Sources */,
6F5A2B4821AFF49A0081EDD8 /* FileManager+Extension.swift in Sources */, 6F5A2B4821AFF49A0081EDD8 /* FileManager+Extension.swift in Sources */,
A6E361FC29D9AEEA00FFF234 /* BuildPeerConfigurationUpdate.swift in Sources */,
5F45418C21C2D48200994C13 /* TunnelEditKeyValueCell.swift in Sources */, 5F45418C21C2D48200994C13 /* TunnelEditKeyValueCell.swift in Sources */,
6FE254FB219C10800028284D /* ZipImporter.swift in Sources */, 6FE254FB219C10800028284D /* ZipImporter.swift in Sources */,
585B107E2577E294004F691E /* PrivateKey.swift in Sources */, 585B107E2577E294004F691E /* PrivateKey.swift in Sources */,