summaryrefslogtreecommitdiffhomepage
path: root/ios
diff options
context:
space:
mode:
authorAndrej Mihajlov <and@mullvad.net>2022-10-11 11:35:37 +0200
committerAndrej Mihajlov <and@mullvad.net>2022-10-11 11:35:37 +0200
commit7ddd910f6dae63a12d9f924e8e967e7b2c068b67 (patch)
treeb16e4d794ad2229c6c06dde08afad37f07ccdb0c /ios
parent46e8823158b6e857c8f24b1e7cecf51612f48efd (diff)
parent94b908c8ad064051ac52b7029517191078a8eb82 (diff)
downloadmullvadvpn-7ddd910f6dae63a12d9f924e8e967e7b2c068b67.tar.xz
mullvadvpn-7ddd910f6dae63a12d9f924e8e967e7b2c068b67.zip
Merge branch 'fix-formatting'
Diffstat (limited to 'ios')
-rw-r--r--ios/MullvadVPN/AutomaticKeyboardResponder.swift3
-rw-r--r--ios/MullvadVPN/PreferencesDataSource.swift3
-rw-r--r--ios/MullvadVPN/ProblemReportViewController.swift3
-rw-r--r--ios/MullvadVPN/RootContainerViewController.swift3
-rw-r--r--ios/MullvadVPN/SceneDelegate.swift3
-rw-r--r--ios/MullvadVPN/TunnelManager/LoadTunnelOperation.swift279
-rw-r--r--ios/MullvadVPN/TunnelManager/RegenerateTunnelPrivateKeyOperation.swift111
-rw-r--r--ios/MullvadVPN/TunnelManager/SetTunnelSettingsOperation.swift53
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManagerError.swift119
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManagerState.swift140
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
- )
- }
- }
- }
-}