summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift5
-rw-r--r--ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift16
-rw-r--r--ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift43
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelManager.swift5
-rw-r--r--ios/MullvadVPN/TunnelManager/TunnelState.swift49
-rw-r--r--ios/MullvadVPN/View controllers/Tunnel/TunnelControlView.swift100
-rw-r--r--ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift7
-rw-r--r--ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift5
-rw-r--r--ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift28
-rw-r--r--ios/PacketTunnelCore/Actor/ObservedState.swift3
10 files changed, 185 insertions, 76 deletions
diff --git a/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift b/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
index 19db4c7297..d0fc0c6bc3 100644
--- a/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
+++ b/ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
@@ -980,6 +980,11 @@ final class ApplicationCoordinator: Coordinator, Presenting, RootContainerViewCo
case .connected, .connecting, .reconnecting, .waitingForConnectivity(.noConnection), .error:
tunnelManager.reconnectTunnel(selectNewRelay: true)
+ #if DEBUG
+ case .negotiatingKey:
+ tunnelManager.reconnectTunnel(selectNewRelay: true)
+ #endif
+
case .disconnecting, .disconnected:
tunnelManager.startTunnel()
diff --git a/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift b/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift
index 5d61428497..9c13398422 100644
--- a/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift
@@ -50,21 +50,27 @@ class MapConnectionStatusOperation: AsyncOperation {
fetchTunnelStatus(tunnel: tunnel) { observedState in
switch observedState {
case let .connected(connectionState):
- return connectionState.isNetworkReachable
+ connectionState.isNetworkReachable
? .connected(connectionState.selectedRelay)
: .waitingForConnectivity(.noConnection)
case let .connecting(connectionState):
- return connectionState.isNetworkReachable
+ connectionState.isNetworkReachable
? .connecting(connectionState.selectedRelay)
: .waitingForConnectivity(.noConnection)
+ #if DEBUG
+ case let .negotiatingKey(connectionState):
+ connectionState.isNetworkReachable
+ ? .negotiatingKey(connectionState.selectedRelay)
+ : .waitingForConnectivity(.noConnection)
+ #endif
case let .reconnecting(connectionState):
- return connectionState.isNetworkReachable
+ connectionState.isNetworkReachable
? .reconnecting(connectionState.selectedRelay)
: .waitingForConnectivity(.noConnection)
case let .error(blockedState):
- return .error(blockedState.reason)
+ .error(blockedState.reason)
case .initial, .disconnecting, .disconnected:
- return .none
+ .none
}
}
return
diff --git a/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift b/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift
index 7bcce98a73..4701a4238c 100644
--- a/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift
+++ b/ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift
@@ -36,27 +36,36 @@ class StopTunnelOperation: ResultOperation<Void> {
finish(result: .success(()))
case .connected, .connecting, .reconnecting, .waitingForConnectivity(.noConnection), .error:
- guard let tunnel = interactor.tunnel else {
- finish(result: .failure(UnsetTunnelError()))
- return
- }
-
- // Disable on-demand when stopping the tunnel to prevent it from coming back up
- tunnel.isOnDemandEnabled = false
+ doShutDownTunnel()
- tunnel.saveToPreferences { error in
- self.dispatchQueue.async {
- if let error {
- self.finish(result: .failure(error))
- } else {
- tunnel.stop()
- self.finish(result: .success(()))
- }
- }
- }
+ #if DEBUG
+ case .negotiatingKey:
+ doShutDownTunnel()
+ #endif
case .disconnected, .disconnecting, .pendingReconnect, .waitingForConnectivity(.noNetwork):
finish(result: .success(()))
}
}
+
+ private func doShutDownTunnel() {
+ guard let tunnel = interactor.tunnel else {
+ finish(result: .failure(UnsetTunnelError()))
+ return
+ }
+
+ // Disable on-demand when stopping the tunnel to prevent it from coming back up
+ tunnel.isOnDemandEnabled = false
+
+ tunnel.saveToPreferences { error in
+ self.dispatchQueue.async {
+ if let error {
+ self.finish(result: .failure(error))
+ } else {
+ tunnel.stop()
+ self.finish(result: .success(()))
+ }
+ }
+ }
+ }
}
diff --git a/ios/MullvadVPN/TunnelManager/TunnelManager.swift b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
index b3d53b5613..3f4c4c67d5 100644
--- a/ios/MullvadVPN/TunnelManager/TunnelManager.swift
+++ b/ios/MullvadVPN/TunnelManager/TunnelManager.swift
@@ -675,6 +675,11 @@ final class TunnelManager: StorePaymentObserver {
// while the tunnel process is trying to connect.
startPollingTunnelStatus(interval: establishingTunnelStatusPollInterval)
+ #if DEBUG
+ case .negotiatingKey:
+ startPollingTunnelStatus(interval: establishingTunnelStatusPollInterval)
+ #endif
+
case .connected, .waitingForConnectivity(.noConnection):
// Start polling tunnel status to keep connectivity status up to date.
startPollingTunnelStatus(interval: establishedTunnelStatusPollInterval)
diff --git a/ios/MullvadVPN/TunnelManager/TunnelState.swift b/ios/MullvadVPN/TunnelManager/TunnelState.swift
index fad2977568..08b889899e 100644
--- a/ios/MullvadVPN/TunnelManager/TunnelState.swift
+++ b/ios/MullvadVPN/TunnelManager/TunnelState.swift
@@ -50,6 +50,11 @@ enum TunnelState: Equatable, CustomStringConvertible {
/// Connecting the tunnel.
case connecting(SelectedRelay?)
+ #if DEBUG
+ /// Negotiating a key for post-quantum resistance
+ case negotiatingKey(SelectedRelay)
+ #endif
+
/// Connected the tunnel
case connected(SelectedRelay)
@@ -75,25 +80,29 @@ enum TunnelState: Equatable, CustomStringConvertible {
var description: String {
switch self {
case .pendingReconnect:
- return "pending reconnect after disconnect"
+ "pending reconnect after disconnect"
case let .connecting(tunnelRelay):
if let tunnelRelay {
- return "connecting to \(tunnelRelay.hostname)"
+ "connecting to \(tunnelRelay.hostname)"
} else {
- return "connecting, fetching relay"
+ "connecting, fetching relay"
}
case let .connected(tunnelRelay):
- return "connected to \(tunnelRelay.hostname)"
+ "connected to \(tunnelRelay.hostname)"
case let .disconnecting(actionAfterDisconnect):
- return "disconnecting and then \(actionAfterDisconnect)"
+ "disconnecting and then \(actionAfterDisconnect)"
case .disconnected:
- return "disconnected"
+ "disconnected"
case let .reconnecting(tunnelRelay):
- return "reconnecting to \(tunnelRelay.hostname)"
+ "reconnecting to \(tunnelRelay.hostname)"
case .waitingForConnectivity:
- return "waiting for connectivity"
+ "waiting for connectivity"
case let .error(blockedStateReason):
- return "error state: \(blockedStateReason)"
+ "error state: \(blockedStateReason)"
+ #if DEBUG
+ case let .negotiatingKey(tunnelRelay):
+ "negotiating key with \(tunnelRelay.hostname)"
+ #endif
}
}
@@ -101,20 +110,28 @@ enum TunnelState: Equatable, CustomStringConvertible {
switch self {
case .reconnecting, .connecting, .connected, .waitingForConnectivity(.noConnection), .error(.accountExpired),
.error(.deviceRevoked):
- return true
+ true
case .pendingReconnect, .disconnecting, .disconnected, .waitingForConnectivity(.noNetwork), .error:
- return false
+ false
+ #if DEBUG
+ case .negotiatingKey:
+ false
+ #endif
}
}
var relay: SelectedRelay? {
switch self {
case let .connected(relay), let .reconnecting(relay):
- return relay
+ relay
case let .connecting(relay):
- return relay
+ relay
+ #if DEBUG
+ case let .negotiatingKey(relay):
+ relay
+ #endif
case .disconnecting, .disconnected, .waitingForConnectivity, .pendingReconnect, .error:
- return nil
+ nil
}
}
}
@@ -130,9 +147,9 @@ enum ActionAfterDisconnect: CustomStringConvertible {
var description: String {
switch self {
case .nothing:
- return "do nothing"
+ "do nothing"
case .reconnect:
- return "reconnect"
+ "reconnect"
}
}
}
diff --git a/ios/MullvadVPN/View controllers/Tunnel/TunnelControlView.swift b/ios/MullvadVPN/View controllers/Tunnel/TunnelControlView.swift
index bd991142e6..1472515927 100644
--- a/ios/MullvadVPN/View controllers/Tunnel/TunnelControlView.swift
+++ b/ios/MullvadVPN/View controllers/Tunnel/TunnelControlView.swift
@@ -450,13 +450,18 @@ private extension TunnelState {
var textColorForSecureLabel: UIColor {
switch self {
case .connecting, .reconnecting, .waitingForConnectivity(.noConnection):
- return .white
+ .white
+
+ #if DEBUG
+ case .negotiatingKey:
+ .white
+ #endif
case .connected:
- return .successColor
+ .successColor
case .disconnecting, .disconnected, .pendingReconnect, .waitingForConnectivity(.noNetwork), .error:
- return .dangerColor
+ .dangerColor
}
}
@@ -471,15 +476,25 @@ private extension TunnelState {
var localizedTitleForSecureLabel: String {
switch self {
case .connecting, .reconnecting:
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_CONNECTING",
tableName: "Main",
value: "Creating secure connection",
comment: ""
)
+ #if DEBUG
+ case .negotiatingKey:
+ NSLocalizedString(
+ "TUNNEL_STATE_NEGOTIATING_KEY",
+ tableName: "Main",
+ value: "Negotiating key",
+ comment: ""
+ )
+ #endif
+
case .connected:
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_CONNECTED",
tableName: "Main",
value: "Secure connection",
@@ -487,14 +502,14 @@ private extension TunnelState {
)
case .disconnecting(.nothing):
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_DISCONNECTING",
tableName: "Main",
value: "Disconnecting",
comment: ""
)
case .disconnecting(.reconnect), .pendingReconnect:
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_PENDING_RECONNECT",
tableName: "Main",
value: "Reconnecting",
@@ -502,7 +517,7 @@ private extension TunnelState {
)
case .disconnected:
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_DISCONNECTED",
tableName: "Main",
value: "Unsecured connection",
@@ -510,7 +525,7 @@ private extension TunnelState {
)
case .waitingForConnectivity(.noConnection), .error:
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_WAITING_FOR_CONNECTIVITY",
tableName: "Main",
value: "Blocked connection",
@@ -518,7 +533,7 @@ private extension TunnelState {
)
case .waitingForConnectivity(.noNetwork):
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_NO_NETWORK",
tableName: "Main",
value: "No network",
@@ -530,7 +545,7 @@ private extension TunnelState {
var localizedTitleForSelectLocationButton: String? {
switch self {
case .disconnecting(.reconnect), .pendingReconnect:
- return NSLocalizedString(
+ NSLocalizedString(
"SWITCH_LOCATION_BUTTON_TITLE",
tableName: "Main",
value: "Select location",
@@ -538,7 +553,7 @@ private extension TunnelState {
)
case .disconnected, .disconnecting(.nothing):
- return NSLocalizedString(
+ NSLocalizedString(
"SELECT_LOCATION_BUTTON_TITLE",
tableName: "Main",
value: "Select location",
@@ -546,27 +561,47 @@ private extension TunnelState {
)
case .connecting, .connected, .reconnecting, .waitingForConnectivity, .error:
- return NSLocalizedString(
+ NSLocalizedString(
"SWITCH_LOCATION_BUTTON_TITLE",
tableName: "Main",
value: "Switch location",
comment: ""
)
+
+ #if DEBUG
+ case .negotiatingKey:
+ NSLocalizedString(
+ "SWITCH_LOCATION_BUTTON_TITLE",
+ tableName: "Main",
+ value: "Switch location",
+ comment: ""
+ )
+ #endif
}
}
var localizedAccessibilityLabel: String {
switch self {
case .connecting:
- return NSLocalizedString(
+ NSLocalizedString(
+ "TUNNEL_STATE_CONNECTING_ACCESSIBILITY_LABEL",
+ tableName: "Main",
+ value: "Creating secure connection",
+ comment: ""
+ )
+
+ #if DEBUG
+ case .negotiatingKey:
+ NSLocalizedString(
"TUNNEL_STATE_CONNECTING_ACCESSIBILITY_LABEL",
tableName: "Main",
value: "Creating secure connection",
comment: ""
)
+ #endif
case let .connected(tunnelInfo):
- return String(
+ String(
format: NSLocalizedString(
"TUNNEL_STATE_CONNECTED_ACCESSIBILITY_LABEL",
tableName: "Main",
@@ -578,7 +613,7 @@ private extension TunnelState {
)
case .disconnected:
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_DISCONNECTED_ACCESSIBILITY_LABEL",
tableName: "Main",
value: "Unsecured connection",
@@ -586,7 +621,7 @@ private extension TunnelState {
)
case let .reconnecting(tunnelInfo):
- return String(
+ String(
format: NSLocalizedString(
"TUNNEL_STATE_RECONNECTING_ACCESSIBILITY_LABEL",
tableName: "Main",
@@ -598,7 +633,7 @@ private extension TunnelState {
)
case .waitingForConnectivity(.noConnection), .error:
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_WAITING_FOR_CONNECTIVITY_ACCESSIBILITY_LABEL",
tableName: "Main",
value: "Blocked connection",
@@ -606,7 +641,7 @@ private extension TunnelState {
)
case .waitingForConnectivity(.noNetwork):
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_NO_NETWORK_ACCESSIBILITY_LABEL",
tableName: "Main",
value: "No network",
@@ -614,7 +649,7 @@ private extension TunnelState {
)
case .disconnecting(.nothing):
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_DISCONNECTING_ACCESSIBILITY_LABEL",
tableName: "Main",
value: "Disconnecting",
@@ -622,7 +657,7 @@ private extension TunnelState {
)
case .disconnecting(.reconnect), .pendingReconnect:
- return NSLocalizedString(
+ NSLocalizedString(
"TUNNEL_STATE_PENDING_RECONNECT_ACCESSIBILITY_LABEL",
tableName: "Main",
value: "Reconnecting",
@@ -636,31 +671,40 @@ private extension TunnelState {
case (.phone, _), (.pad, .compact):
switch self {
case .disconnected, .disconnecting(.nothing), .waitingForConnectivity(.noNetwork):
- return [.selectLocation, .connect]
+ [.selectLocation, .connect]
case .connecting, .pendingReconnect, .disconnecting(.reconnect),
.waitingForConnectivity(.noConnection):
- return [.selectLocation, .cancel]
+ [.selectLocation, .cancel]
+
+ #if DEBUG
+ case .negotiatingKey:
+ [.selectLocation, .cancel]
+ #endif
case .connected, .reconnecting, .error:
- return [.selectLocation, .disconnect]
+ [.selectLocation, .disconnect]
}
case (.pad, .regular):
switch self {
case .disconnected, .disconnecting(.nothing), .waitingForConnectivity(.noNetwork):
- return [.connect]
+ [.connect]
case .connecting, .pendingReconnect, .disconnecting(.reconnect),
.waitingForConnectivity(.noConnection):
- return [.cancel]
+ [.cancel]
+ #if DEBUG
+ case .negotiatingKey:
+ [.cancel]
+ #endif
case .connected, .reconnecting, .error:
- return [.disconnect]
+ [.disconnect]
}
default:
- return []
+ []
}
}
diff --git a/ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift b/ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift
index d01b3b3133..7d68b3dd41 100644
--- a/ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift
+++ b/ios/MullvadVPN/View controllers/Tunnel/TunnelViewController.swift
@@ -157,6 +157,13 @@ class TunnelViewController: UIViewController, RootContainment {
contentView.setAnimatingActivity(true)
mapViewController.setCenter(tunnelRelay.location.geoCoordinate, animated: animated)
+ #if DEBUG
+ case let .negotiatingKey(tunnelRelay):
+ mapViewController.removeLocationMarker()
+ contentView.setAnimatingActivity(true)
+ mapViewController.setCenter(tunnelRelay.location.geoCoordinate, animated: animated)
+ #endif
+
case let .connected(tunnelRelay):
let center = tunnelRelay.location.geoCoordinate
mapViewController.setCenter(center, animated: animated) {
diff --git a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
index d2aba984ca..ed9c700af8 100644
--- a/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
+++ b/ios/PacketTunnel/PacketTunnelProvider/PacketTunnelProvider.swift
@@ -229,6 +229,11 @@ extension PacketTunnelProvider {
// Cache last connection attempt to filter out repeating calls.
lastConnectionAttempt = connectionAttempt
+ #if DEBUG
+ case .negotiatingKey:
+ break
+ #endif
+
case .initial, .connected, .disconnecting, .disconnected, .error:
break
}
diff --git a/ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift b/ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift
index 05624a6565..1504f3e47d 100644
--- a/ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift
+++ b/ios/PacketTunnelCore/Actor/ObservedState+Extensions.swift
@@ -13,32 +13,40 @@ extension ObservedState {
public var relayConstraints: RelayConstraints? {
switch self {
case let .connecting(connState), let .connected(connState), let .reconnecting(connState):
- return connState.relayConstraints
+ connState.relayConstraints
+ #if DEBUG
+ case let .negotiatingKey(connState):
+ connState.relayConstraints
+ #endif
case let .error(blockedState):
- return blockedState.relayConstraints
+ blockedState.relayConstraints
case .initial, .disconnecting, .disconnected:
- return nil
+ nil
}
}
public var name: String {
switch self {
case .connected:
- return "Connected"
+ "Connected"
case .connecting:
- return "Connecting"
+ "Connecting"
+ #if DEBUG
+ case .negotiatingKey:
+ "Negotiating key"
+ #endif
case .reconnecting:
- return "Reconnecting"
+ "Reconnecting"
case .disconnecting:
- return "Disconnecting"
+ "Disconnecting"
case .disconnected:
- return "Disconnected"
+ "Disconnected"
case .initial:
- return "Initial"
+ "Initial"
case .error:
- return "Error"
+ "Error"
}
}
diff --git a/ios/PacketTunnelCore/Actor/ObservedState.swift b/ios/PacketTunnelCore/Actor/ObservedState.swift
index a6b7d741bc..94a1aa19c8 100644
--- a/ios/PacketTunnelCore/Actor/ObservedState.swift
+++ b/ios/PacketTunnelCore/Actor/ObservedState.swift
@@ -16,6 +16,9 @@ public enum ObservedState: Equatable, Codable {
case initial
case connecting(ObservedConnectionState)
case reconnecting(ObservedConnectionState)
+ #if DEBUG
+ case negotiatingKey(ObservedConnectionState)
+ #endif
case connected(ObservedConnectionState)
case disconnecting(ObservedConnectionState)
case disconnected