diff options
| author | Andrej Mihajlov <and@mullvad.net> | 2022-10-11 11:35:37 +0200 |
|---|---|---|
| committer | Andrej Mihajlov <and@mullvad.net> | 2022-10-11 11:35:37 +0200 |
| commit | 7ddd910f6dae63a12d9f924e8e967e7b2c068b67 (patch) | |
| tree | b16e4d794ad2229c6c06dde08afad37f07ccdb0c /ios | |
| parent | 46e8823158b6e857c8f24b1e7cecf51612f48efd (diff) | |
| parent | 94b908c8ad064051ac52b7029517191078a8eb82 (diff) | |
| download | mullvadvpn-7ddd910f6dae63a12d9f924e8e967e7b2c068b67.tar.xz mullvadvpn-7ddd910f6dae63a12d9f924e8e967e7b2c068b67.zip | |
Merge branch 'fix-formatting'
Diffstat (limited to 'ios')
| -rw-r--r-- | ios/MullvadVPN/AutomaticKeyboardResponder.swift | 3 | ||||
| -rw-r--r-- | ios/MullvadVPN/PreferencesDataSource.swift | 3 | ||||
| -rw-r--r-- | ios/MullvadVPN/ProblemReportViewController.swift | 3 | ||||
| -rw-r--r-- | ios/MullvadVPN/RootContainerViewController.swift | 3 | ||||
| -rw-r--r-- | ios/MullvadVPN/SceneDelegate.swift | 3 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift | 279 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/RegenerateTunnelPrivateKeyOperation.swift | 111 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift | 53 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/TunnelManagerError.swift | 119 | ||||
| -rw-r--r-- | ios/MullvadVPN/TunnelManager/TunnelManagerState.swift | 140 |
10 files changed, 10 insertions, 707 deletions
diff --git a/ios/MullvadVPN/AutomaticKeyboardResponder.swift b/ios/MullvadVPN/AutomaticKeyboardResponder.swift index d10216b352..110b2dccc9 100644 --- a/ios/MullvadVPN/AutomaticKeyboardResponder.swift +++ b/ios/MullvadVPN/AutomaticKeyboardResponder.swift @@ -166,7 +166,8 @@ class AutomaticKeyboardResponder { } extension AutomaticKeyboardResponder { - /// A convenience initializer that automatically assigns the offset to the scroll view subclasses + /// A convenience initializer that automatically assigns the offset to the scroll view + /// subclasses convenience init<T: UIScrollView>(targetView: T) { self.init(targetView: targetView) { scrollView, offset in if scrollView.canBecomeFirstResponder { diff --git a/ios/MullvadVPN/PreferencesDataSource.swift b/ios/MullvadVPN/PreferencesDataSource.swift index 6451571bf4..4f39ad1403 100644 --- a/ios/MullvadVPN/PreferencesDataSource.swift +++ b/ios/MullvadVPN/PreferencesDataSource.swift @@ -103,7 +103,8 @@ class PreferencesDataSource: NSObject, UITableViewDataSource, UITableViewDelegat updateSnapshot() - // Reconfigure cells for items with corresponding DNS entries that were changed during sanitization. + // Reconfigure cells for items with corresponding DNS entries that were changed during + // sanitization. let itemsToReload: [Item] = oldDNSDomains.filter { oldDNSEntry in guard let newDNSEntry = viewModel.dnsEntry(entryIdentifier: oldDNSEntry.identifier) else { return false } diff --git a/ios/MullvadVPN/ProblemReportViewController.swift b/ios/MullvadVPN/ProblemReportViewController.swift index 823cd450fc..5432b94c4c 100644 --- a/ios/MullvadVPN/ProblemReportViewController.swift +++ b/ios/MullvadVPN/ProblemReportViewController.swift @@ -736,7 +736,8 @@ class ProblemReportViewController: UIViewController, UITextFieldDelegate, Condit return !emailTextField.isFirstResponder && !messageTextView.isFirstResponder case .backButton: - // Dismiss the keyboard to fix a visual glitch when moving back to the previous controller + // Dismiss the keyboard to fix a visual glitch when moving back to the previous + // controller view.endEditing(true) return true } diff --git a/ios/MullvadVPN/RootContainerViewController.swift b/ios/MullvadVPN/RootContainerViewController.swift index 573f4c5c7f..cfeb445484 100644 --- a/ios/MullvadVPN/RootContainerViewController.swift +++ b/ios/MullvadVPN/RootContainerViewController.swift @@ -609,7 +609,8 @@ class RootContainerViewController: UIViewController { } private func updateAccessibilityElementsAndNotifyScreenChange() { - // Update accessibility elements to define the correct navigation order: header bar, content view. + // Update accessibility elements to define the correct navigation order: header bar, content + // view. view.accessibilityElements = [headerBarView, topViewController?.view].compactMap { $0 } // Tell accessibility that the significant part of screen was changed. diff --git a/ios/MullvadVPN/SceneDelegate.swift b/ios/MullvadVPN/SceneDelegate.swift index 3297e66d6b..f87a2ad428 100644 --- a/ios/MullvadVPN/SceneDelegate.swift +++ b/ios/MullvadVPN/SceneDelegate.swift @@ -596,7 +596,8 @@ extension SceneDelegate: LoginViewControllerDelegate { TunnelManager.shared.setAccount(action: action.setAccountAction) { operationCompletion in switch operationCompletion { case .success: - // RootContainer's settings button will be re-enabled in `loginViewControllerDidFinishLogin` + // RootContainer's settings button will be re-enabled in + // `loginViewControllerDidFinishLogin` completion(operationCompletion) case let .failure(error): diff --git a/ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift deleted file mode 100644 index 39d474e38c..0000000000 --- a/ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift +++ /dev/null @@ -1,279 +0,0 @@ -// -// LoadTunnelOperation.swift -// MullvadVPN -// -// Created by pronebird on 16/12/2021. -// Copyright © 2021 Mullvad VPN AB. All rights reserved. -// - -import Foundation -import Logging - -class LoadTunnelOperation: ResultOperation<Void, TunnelManager.Error> { - private let accountToken: String? - private let state: TunnelManager.State - - private let logger = Logger(label: "TunnelManager.LoadTunnelOperation") - - init( - dispatchQueue: DispatchQueue, - state: TunnelManager.State, - accountToken: String?, - completionHandler: @escaping CompletionHandler - ) { - self.state = state - self.accountToken = accountToken - - super.init( - dispatchQueue: dispatchQueue, - completionQueue: dispatchQueue, - completionHandler: completionHandler - ) - } - - override func main() { - execute { completion in - self.finish(completion: completion) - } - } - - private func execute(completionHandler: @escaping CompletionHandler) { - // Migrate the tunnel settings if needed - if let accountToken = accountToken { - let migrationResult = migrateTunnelSettings(accountToken: accountToken) - - if case let .failure(migrationError) = migrationResult { - completionHandler(.failure(migrationError)) - return - } - } - - TunnelProviderManagerType.loadAllFromPreferences { tunnels, error in - self.dispatchQueue.async { - if let error = error { - completionHandler(.failure(.loadAllVPNConfigurations(error))) - } else { - self.didLoadVPNConfigurations( - tunnels: tunnels, - completionHandler: completionHandler - ) - } - } - } - } - - private func didLoadVPNConfigurations( - tunnels: [TunnelProviderManagerType]?, - completionHandler: @escaping CompletionHandler - ) { - if let tunnelProvider = tunnels?.first { - if let accountToken = accountToken { - // Case 1: tunnel exists and account token is set. - // Verify that tunnel can access the configuration via the persistent keychain reference - // stored in `passwordReference` field of VPN configuration. - handleTunnelConsistency( - tunnelProvider: tunnelProvider, - accountToken: accountToken, - completionHandler: completionHandler - ) - } else { - // Case 2: tunnel exists but account token is unset. - // Remove the orphaned tunnel. - tunnelProvider.removeFromPreferences { error in - self.dispatchQueue.async { - if let error = error { - completionHandler(.failure(.removeInconsistentVPNConfiguration(error))) - } else { - completionHandler(.success(())) - } - } - } - } - } else { - if let accountToken = accountToken { - // Case 3: tunnel does not exist but the account token is set. - // Verify that tunnel settings exists in keychain. - let tunnelSettingsResult = TunnelSettingsManager - .load(searchTerm: .accountToken(accountToken)) - .mapError { TunnelManager.Error.readTunnelSettings($0) } - - if case let .success(keychainEntry) = tunnelSettingsResult { - let tunnelInfo = TunnelInfo( - token: keychainEntry.accountToken, - tunnelSettings: keychainEntry.tunnelSettings - ) - - state.tunnelInfo = tunnelInfo - } - - completionHandler(OperationCompletion(result: tunnelSettingsResult.map { _ in () })) - } else { - // Case 4: no tunnels exist and account token is unset. - completionHandler(.success(())) - } - } - } - - private func handleTunnelConsistency( - tunnelProvider: TunnelProviderManagerType, - accountToken: String, - completionHandler: @escaping CompletionHandler - ) { - let verificationResult = verifyTunnel( - tunnelProvider: tunnelProvider, - expectedAccountToken: accountToken - ) - let tunnelSettingsResult = TunnelSettingsManager - .load(searchTerm: .accountToken(accountToken)) - .mapError { TunnelManager.Error.readTunnelSettings($0) } - - switch (verificationResult, tunnelSettingsResult) { - case (.success(true), let .success(keychainEntry)): - let tunnelInfo = TunnelInfo( - token: accountToken, - tunnelSettings: keychainEntry.tunnelSettings - ) - - state.tunnelInfo = tunnelInfo - state.setTunnel(Tunnel(tunnelProvider: tunnelProvider), shouldRefreshTunnelState: true) - - completionHandler(.success(())) - - // Remove the tunnel with corrupt configuration. - // It will be re-created upon the first attempt to connect the tunnel. - case (.success(false), let .success(keychainEntry)): - tunnelProvider.removeFromPreferences { error in - self.dispatchQueue.async { - if let error = error { - completionHandler(.failure(.removeInconsistentVPNConfiguration(error))) - } else { - let tunnelInfo = TunnelInfo( - token: accountToken, - tunnelSettings: keychainEntry.tunnelSettings - ) - self.state.tunnelInfo = tunnelInfo - - completionHandler(.success(())) - } - } - } - - // Remove the tunnel when failed to verify it but successfuly loaded the tunnel - // settings. - case let (.failure(verificationError), .success(keychainEntry)): - logger.error( - chainedError: verificationError, - message: "Failed to verify the tunnel but successfully loaded the tunnel settings. Removing the tunnel." - ) - - // Remove the tunnel with corrupt configuration. - // It will be re-created upon the first attempt to connect the tunnel. - tunnelProvider.removeFromPreferences { error in - self.dispatchQueue.async { - if let error = error { - completionHandler(.failure(.removeInconsistentVPNConfiguration(error))) - } else { - let tunnelInfo = TunnelInfo( - token: accountToken, - tunnelSettings: keychainEntry.tunnelSettings - ) - self.state.tunnelInfo = tunnelInfo - - completionHandler(.success(())) - } - } - } - - // Remove the tunnel when failed to verify the tunnel and load tunnel settings. - case let (.failure(verificationError), .failure(_)): - logger.error( - chainedError: verificationError, - message: "Failed to verify the tunnel and load tunnel settings. Removing the tunnel." - ) - - tunnelProvider.removeFromPreferences { error in - self.dispatchQueue.async { - if let error = error { - completionHandler(.failure(.removeInconsistentVPNConfiguration(error))) - } else { - completionHandler(.failure(verificationError)) - } - } - } - - // Remove the tunnel when the app is not able to read tunnel settings - case let (.success(_), .failure(settingsReadError)): - logger.error( - chainedError: settingsReadError, - message: "Failed to load tunnel settings. Removing the tunnel." - ) - - tunnelProvider.removeFromPreferences { error in - self.dispatchQueue.async { - if let error = error { - completionHandler(.failure(.removeInconsistentVPNConfiguration(error))) - } else { - completionHandler(.failure(settingsReadError)) - } - } - } - } - } - - private func verifyTunnel( - tunnelProvider: TunnelProviderManagerType, - expectedAccountToken accountToken: String - ) -> Result<Bool, TunnelManager.Error> { - // Check that the VPN configuration points to the same account token - guard let username = tunnelProvider.protocolConfiguration?.username, - username == accountToken - else { - logger - .warning( - "The token assigned to the VPN configuration does not match the logged in account." - ) - return .success(false) - } - - // Check that the passwordReference, containing the keychain reference for tunnel - // configuration, is set. - guard let keychainReference = tunnelProvider.protocolConfiguration?.passwordReference else { - logger.warning("VPN configuration is missing the passwordReference.") - return .success(false) - } - - // Verify that the keychain reference points to the existing entry in Keychain. - // Bad reference is possible when migrating the user data from one device to the other. - return TunnelSettingsManager.exists(searchTerm: .persistentReference(keychainReference)) - .mapError { error -> TunnelManager.Error in - logger.error( - chainedError: error, - message: "Failed to verify the persistent keychain reference for tunnel settings." - ) - - return .readTunnelSettings(error) - } - } - - private func migrateTunnelSettings(accountToken: String) -> Result<Bool, TunnelManager.Error> { - let result = TunnelSettingsManager - .migrateKeychainEntry(searchTerm: .accountToken(accountToken)) - .mapError { error -> TunnelManager.Error in - return .migrateTunnelSettings(error) - } - - switch result { - case let .success(migrated): - if migrated { - logger.info("Migrated Keychain tunnel configuration.") - } else { - logger.info("Tunnel settings are up to date. No migration needed.") - } - - case let .failure(error): - logger.error(chainedError: error) - } - - return result - } -} diff --git a/ios/MullvadVPN/TunnelManager/RegenerateTunnelPrivateKeyOperation.swift b/ios/MullvadVPN/TunnelManager/RegenerateTunnelPrivateKeyOperation.swift deleted file mode 100644 index 14c7245908..0000000000 --- a/ios/MullvadVPN/TunnelManager/RegenerateTunnelPrivateKeyOperation.swift +++ /dev/null @@ -1,111 +0,0 @@ -// -// RegeneratePrivateKeyOperation.swift -// MullvadVPN -// -// Created by pronebird on 15/12/2021. -// Copyright © 2021 Mullvad VPN AB. All rights reserved. -// - -import Foundation - -class RegeneratePrivateKeyOperation: AsyncOperation { - typealias CompletionHandler = (OperationCompletion<Void, TunnelManager.Error>) -> Void - - private let queue: DispatchQueue - private let state: TunnelManager.State - private let restClient: REST.Client - private var completionHandler: CompletionHandler? - private var restRequest: Cancellable? - - init( - queue: DispatchQueue, - state: TunnelManager.State, - restClient: REST.Client, - completionHandler: @escaping CompletionHandler - ) { - self.queue = queue - self.state = state - self.restClient = restClient - self.completionHandler = completionHandler - } - - override func main() { - queue.async { - self.execute { [weak self] completion in - guard let self = self else { return } - - self.completionHandler?(completion) - self.completionHandler = nil - - self.finish() - } - } - } - - override func cancel() { - super.cancel() - - queue.async { - self.restRequest?.cancel() - } - } - - private func execute(completionHandler: @escaping CompletionHandler) { - guard !isCancelled else { - completionHandler(.cancelled) - return - } - - guard let tunnelInfo = state.tunnelInfo else { - completionHandler(.failure(.missingAccount)) - return - } - - let newPrivateKey = PrivateKeyWithMetadata() - let oldPublicKey = tunnelInfo.tunnelSettings.interface.publicKey - - let restRequestAdapter = restClient.replaceWireguardKey( - token: tunnelInfo.token, - oldPublicKey: oldPublicKey, - newPublicKey: newPrivateKey.publicKey - ) - - restRequest = restRequestAdapter.execute(retryStrategy: .default) { restResult in - self.queue.async { - let saveResult = Self.handleResponse( - accountToken: tunnelInfo.token, - newPrivateKey: newPrivateKey, - result: restResult - ) - - if case let .success(newTunnelSettings) = saveResult { - self.state.tunnelInfo?.tunnelSettings = newTunnelSettings - } - - completionHandler(OperationCompletion(result: saveResult.map { _ in () })) - } - } - } - - private class func handleResponse( - accountToken: String, - newPrivateKey: PrivateKeyWithMetadata, - result: Result<REST.WireguardAddressesResponse, REST.Error> - ) -> Result<TunnelSettings, TunnelManager.Error> { - return result.flatMapError { restError in - return .failure(.replaceWireguardKey(restError)) - } - .flatMap { associatedAddresses in - return TunnelSettingsManager - .update(searchTerm: .accountToken(accountToken)) { newTunnelSettings in - newTunnelSettings.interface.privateKey = newPrivateKey - newTunnelSettings.interface.addresses = [ - associatedAddresses.ipv4Address, - associatedAddresses.ipv6Address, - ] - }.mapError { error -> TunnelManager.Error in - return .updateTunnelSettings(error) - } - } - } -} diff --git a/ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift b/ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift deleted file mode 100644 index 28c0731a4c..0000000000 --- a/ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift +++ /dev/null @@ -1,53 +0,0 @@ -// -// SetTunnelSettingsOperation.swift -// MullvadVPN -// -// Created by pronebird on 16/12/2021. -// Copyright © 2021 Mullvad VPN AB. All rights reserved. -// - -import Foundation - -class SetTunnelSettingsOperation: ResultOperation<Void, TunnelManager.Error> { - typealias ModificationHandler = (inout TunnelSettings) -> Void - - private let state: TunnelManager.State - private let modificationBlock: ModificationHandler - - init( - dispatchQueue: DispatchQueue, - state: TunnelManager.State, - modificationBlock: @escaping ModificationHandler, - completionHandler: @escaping CompletionHandler - ) { - self.state = state - self.modificationBlock = modificationBlock - - super.init( - dispatchQueue: dispatchQueue, - completionQueue: dispatchQueue, - completionHandler: completionHandler - ) - } - - override func main() { - guard let accountToken = state.tunnelInfo?.token else { - finish(completion: .failure(.unsetAccount)) - return - } - - let result = TunnelSettingsManager - .update(searchTerm: .accountToken(accountToken)) { tunnelSettings in - modificationBlock(&tunnelSettings) - } - - switch result { - case let .success(newTunnelSettings): - state.tunnelInfo?.tunnelSettings = newTunnelSettings - finish(completion: .success(())) - - case let .failure(error): - finish(completion: .failure(.updateTunnelSettings(error))) - } - } -} diff --git a/ios/MullvadVPN/TunnelManager/TunnelManagerError.swift b/ios/MullvadVPN/TunnelManager/TunnelManagerError.swift deleted file mode 100644 index fa1d095057..0000000000 --- a/ios/MullvadVPN/TunnelManager/TunnelManagerError.swift +++ /dev/null @@ -1,119 +0,0 @@ -// -// TunnelManagerError.swift -// TunnelManagerError -// -// Created by pronebird on 07/09/2021. -// Copyright © 2021 Mullvad VPN AB. All rights reserved. -// - -import Foundation - -extension TunnelManager { - /// An error emitted by all public methods of TunnelManager - enum Error: ChainedError { - /// Account is unset. - case unsetAccount - - /// Tunnel is not set yet. - case unsetTunnel - - /// Failure to start the VPN tunnel via system call. - case startVPNTunnel(Swift.Error) - - /// Failure to load the system VPN configurations created by the app. - case loadAllVPNConfigurations(Swift.Error) - - /// Failure to save the system VPN configuration. - case saveVPNConfiguration(Swift.Error) - - /// Failure to reload the system VPN configuration. - case reloadVPNConfiguration(Swift.Error) - - /// Failure to remove the system VPN configuration. - case removeVPNConfiguration(Swift.Error) - - /// Failure to read settings. - case readSettings(Swift.Error) - - /// Failure to write settings. - case writeSettings(Swift.Error) - - /// Failure to delete settings. - case deleteSettings(Swift.Error) - - /// Failure to read relays cache. - case readRelays - - /// Failure to find a relay satisfying the given constraints. - case cannotSatisfyRelayConstraints - - /// Failure to create device. - case createDevice(REST.Error) - - /// Failure to delete device. - case deleteDevice(REST.Error) - - /// Failure to obtain device data. - case getDevice(REST.Error) - - /// Requested device is already revoked. - case deviceRevoked - - /// Failure to obtain account data. - case getAccountData(REST.Error) - - /// Failure to create account. - case createAccount(REST.Error) - - /// Failure to rotate WireGuard key. - case rotateKey(REST.Error) - - /// Failure to reload tunnel. - case reloadTunnel(Swift.Error) - - var errorDescription: String? { - switch self { - case .unsetAccount: - return "Account is unset." - case .unsetTunnel: - return "Tunnel is unset." - case .startVPNTunnel: - return "Failed to start the VPN tunnel." - case .loadAllVPNConfigurations: - return "Failed to load the system VPN configurations." - case .saveVPNConfiguration: - return "Failed to save the system VPN configuration." - case .reloadVPNConfiguration: - return "Failed to reload the system VPN configuration." - case .removeVPNConfiguration: - return "Failed to remove the system VPN configuration." - case .readSettings: - return "Failed to read settings." - case .readRelays: - return "Failed to read relays." - case .cannotSatisfyRelayConstraints: - return "Failed to satisfy the relay constraints." - case .writeSettings: - return "Failed to write settings." - case .deleteSettings: - return "Failed to delete settings." - case .createDevice: - return "Failed to create a device." - case .deleteDevice: - return "Failed to delete a device." - case .getDevice: - return "Failed to obtain device data." - case .deviceRevoked: - return "Requested device is already revoked." - case .getAccountData: - return "Failed to obtain account data." - case .createAccount: - return "Failed to create new account." - case .rotateKey: - return "Failed to rotate WireGuard key." - case .reloadTunnel: - return "Failed to reload tunnel." - } - } - } -} diff --git a/ios/MullvadVPN/TunnelManager/TunnelManagerState.swift b/ios/MullvadVPN/TunnelManager/TunnelManagerState.swift deleted file mode 100644 index 2e82f59018..0000000000 --- a/ios/MullvadVPN/TunnelManager/TunnelManagerState.swift +++ /dev/null @@ -1,140 +0,0 @@ -// -// TunnelManager.State.swift -// MullvadVPN -// -// Created by pronebird on 26/01/2022. -// Copyright © 2022 Mullvad VPN AB. All rights reserved. -// - -import Foundation -import NetworkExtension - -protocol TunnelManagerStateDelegate: AnyObject { - func tunnelManagerState( - _ state: TunnelManager.State, - didChangeLoadedConfiguration isLoadedConfiguration: Bool - ) - - func tunnelManagerState( - _ state: TunnelManager.State, - didChangeTunnelSettings newTunnelSettings: TunnelSettingsV2? - ) - - func tunnelManagerState( - _ state: TunnelManager.State, - didChangeTunnelStatus newTunnelStatus: TunnelStatus - ) - - func tunnelManagerState( - _ state: TunnelManager.State, - didChangeTunnelProvider newTunnelObject: Tunnel?, - shouldRefreshTunnelState: Bool - ) -} - -extension TunnelManager { - class State { - weak var delegate: TunnelManagerStateDelegate? - let delegateQueue: DispatchQueue - - private let nslock = NSLock() - private var _isLoadedConfiguration = false - private var _tunnelSettings: TunnelSettingsV2? - private var _tunnelObject: Tunnel? - private var _tunnelStatus = TunnelStatus() - - var isLoadedConfiguration: Bool { - get { - nslock.lock() - defer { nslock.unlock() } - - return _isLoadedConfiguration - } - set { - nslock.lock() - defer { nslock.unlock() } - - guard _isLoadedConfiguration != newValue else { return } - - _isLoadedConfiguration = newValue - - delegateQueue.async { - self.delegate?.tunnelManagerState( - self, - didChangeLoadedConfiguration: newValue - ) - } - } - } - - var tunnelSettings: TunnelSettingsV2? { - get { - nslock.lock() - defer { nslock.unlock() } - - return _tunnelSettings - } - set { - nslock.lock() - defer { nslock.unlock() } - - guard _tunnelSettings != newValue else { return } - - _tunnelSettings = newValue - - delegateQueue.async { - self.delegate?.tunnelManagerState(self, didChangeTunnelSettings: newValue) - } - } - } - - var tunnel: Tunnel? { - nslock.lock() - defer { nslock.unlock() } - - return _tunnelObject - } - - var tunnelStatus: TunnelStatus { - get { - nslock.lock() - defer { nslock.unlock() } - - return _tunnelStatus - } - set { - nslock.lock() - defer { nslock.unlock() } - - guard _tunnelStatus != newValue else { return } - - _tunnelStatus = newValue - - delegateQueue.async { - self.delegate?.tunnelManagerState(self, didChangeTunnelStatus: newValue) - } - } - } - - init(delegateQueue: DispatchQueue) { - self.delegateQueue = delegateQueue - } - - func setTunnel(_ newTunnelObject: Tunnel?, shouldRefreshTunnelState: Bool) { - nslock.lock() - defer { nslock.unlock() } - - guard _tunnelObject != newTunnelObject else { return } - - _tunnelObject = newTunnelObject - - delegateQueue.async { - self.delegate?.tunnelManagerState( - self, - didChangeTunnelProvider: newTunnelObject, - shouldRefreshTunnelState: shouldRefreshTunnelState - ) - } - } - } -} |
