Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce ObservedState.negotiatingKey and TunnelState.negotiatingKey… #5919

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions ios/MullvadVPN/Coordinators/ApplicationCoordinator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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()

Expand Down
16 changes: 11 additions & 5 deletions ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,27 @@
fetchTunnelStatus(tunnel: tunnel) { observedState in
switch observedState {
case let .connected(connectionState):
return connectionState.isNetworkReachable
connectionState.isNetworkReachable
? .connected(connectionState.selectedRelay)

Check warning on line 54 in ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift

View workflow job for this annotation

GitHub Actions / End to end tests

Void Function in Ternary Violation: Using ternary to call Void functions should be avoided (void_function_in_ternary)
: .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)

Check warning on line 68 in ios/MullvadVPN/TunnelManager/MapConnectionStatusOperation.swift

View workflow job for this annotation

GitHub Actions / End to end tests

Void Function in Ternary Violation: Using ternary to call Void functions should be avoided (void_function_in_ternary)
: .waitingForConnectivity(.noConnection)
case let .error(blockedState):
return .error(blockedState.reason)
.error(blockedState.reason)
case .initial, .disconnecting, .disconnected:
return .none
.none
}
}
return
Expand Down
43 changes: 26 additions & 17 deletions ios/MullvadVPN/TunnelManager/StopTunnelOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
doShutDownTunnel()

// 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(()))
}
}
}
#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(()))
}
}
}
}
}
5 changes: 5 additions & 0 deletions ios/MullvadVPN/TunnelManager/TunnelManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
49 changes: 33 additions & 16 deletions ios/MullvadVPN/TunnelManager/TunnelState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -75,46 +80,58 @@ 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
}
}

var isSecured: Bool {
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
}
}
}
Expand All @@ -130,9 +147,9 @@ enum ActionAfterDisconnect: CustomStringConvertible {
var description: String {
switch self {
case .nothing:
return "do nothing"
"do nothing"
case .reconnect:
return "reconnect"
"reconnect"
}
}
}
Loading
Loading