summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAndrew Bulhak <andrew.bulhak@mullvad.net>2024-05-29 11:22:32 +0200
committerBug Magnet <marco.nikic@mullvad.net>2024-05-29 13:40:11 +0200
commit7393ed2eb15c1fcad13fd9efb77317b1077d5253 (patch)
treef2bac6156b8c963397ed7ff39aef6b282ac2cbc5
parent61ca50af93d185c9b7563adf0740bc06446ca96e (diff)
downloadmullvadvpn-7393ed2eb15c1fcad13fd9efb77317b1077d5253.tar.xz
mullvadvpn-7393ed2eb15c1fcad13fd9efb77317b1077d5253.zip
Move reducer function to Reducer struct namespace
-rw-r--r--ios/PacketTunnelCore/Actor/PacketTunnelActorReducer.swift206
1 files changed, 103 insertions, 103 deletions
diff --git a/ios/PacketTunnelCore/Actor/PacketTunnelActorReducer.swift b/ios/PacketTunnelCore/Actor/PacketTunnelActorReducer.swift
index 3fc7d9f8b3..338677e6c9 100644
--- a/ios/PacketTunnelCore/Actor/PacketTunnelActorReducer.swift
+++ b/ios/PacketTunnelCore/Actor/PacketTunnelActorReducer.swift
@@ -9,8 +9,6 @@
import Foundation
import WireGuardKitTypes
-extension WireGuardKey where Self: Equatable {}
-
extension PacketTunnelActor {
/// A structure encoding an effect; each event will yield zero or more of those, which can then be sequentially executed.
enum Effect: Equatable {
@@ -52,133 +50,135 @@ extension PacketTunnelActor {
}
}
- static func reducer(_ state: inout State, _ event: Event) -> [Effect] {
- switch event {
- case let .start(options):
- guard case .initial = state else { return [] }
- return [
- .startDefaultPathObserver,
- .startTunnelMonitor,
- .startConnection(options.selectedRelay.map { .preSelected($0) } ?? .random),
- ]
- case .stop:
- return subreducerForStop(&state)
+ struct Reducer {
+ static func reduce(_ state: inout State, _ event: Event) -> [Effect] {
+ switch event {
+ case let .start(options):
+ guard case .initial = state else { return [] }
+ return [
+ .startDefaultPathObserver,
+ .startTunnelMonitor,
+ .startConnection(options.selectedRelay.map { .preSelected($0) } ?? .random),
+ ]
+ case .stop:
+ return subreducerForStop(&state)
- case let .reconnect(nextRelay, reason: reason):
- return subreducerForReconnect(state, reason, nextRelay)
+ case let .reconnect(nextRelay, reason: reason):
+ return subreducerForReconnect(state, reason, nextRelay)
- case let .error(reason):
- // the transition from error to blocked state currently has side-effects, so will be handled as an effect for now.
- return [.configureForErrorState(reason)]
+ case let .error(reason):
+ // the transition from error to blocked state currently has side-effects, so will be handled as an effect for now.
+ return [.configureForErrorState(reason)]
- case let .notifyKeyRotated(lastKeyRotation):
- // the cacheActiveKey operation is currently effectful, starting a key-switch task within the mutation of state, so this is entirely done in an effect. Perhaps teasing effects out of state mutation is a future refactoring?
- guard state.keyPolicy == .useCurrent else { return [] }
- return [.cacheActiveKey(lastKeyRotation)]
+ case let .notifyKeyRotated(lastKeyRotation):
+ // the cacheActiveKey operation is currently effectful, starting a key-switch task within the mutation of state, so this is entirely done in an effect. Perhaps teasing effects out of state mutation is a future refactoring?
+ guard state.keyPolicy == .useCurrent else { return [] }
+ return [.cacheActiveKey(lastKeyRotation)]
- case .switchKey:
- return subreducerForSwitchKey(&state)
+ case .switchKey:
+ return subreducerForSwitchKey(&state)
- case let .monitorEvent(event):
- return subreducerForTunnelMonitorEvent(event, &state)
+ case let .monitorEvent(event):
+ return subreducerForTunnelMonitorEvent(event, &state)
- case let .networkReachability(defaultPath):
- let newReachability = defaultPath.networkReachability
- state.mutateAssociatedData { $0.networkReachability = newReachability }
- return [.updateTunnelMonitorPath(defaultPath)]
+ case let .networkReachability(defaultPath):
+ let newReachability = defaultPath.networkReachability
+ state.mutateAssociatedData { $0.networkReachability = newReachability }
+ return [.updateTunnelMonitorPath(defaultPath)]
- case let .replaceDevicePrivateKey(key, ephemeralKey: ephemeralKey):
- return [.postQuantumConnect(key, privateKey: ephemeralKey)]
+ case let .replaceDevicePrivateKey(key, ephemeralKey: ephemeralKey):
+ return [.postQuantumConnect(key, privateKey: ephemeralKey)]
+ }
}
- }
- // Parts of the reducer path broken out for specific incoming events
+ // Parts of the reducer path broken out for specific incoming events
- fileprivate static func subreducerForStop(_ state: inout State) -> [PacketTunnelActor.Effect] {
- // a call of the reducer produces one state transition and a sequence of effects. In the app, a stop transitions to .disconnecting, shuts down various processes, and finally transitions to .disconnected. We currently do this by having an effect which acknowledges the completion of disconnection and just sets the state. This is a bit messy, and could possibly do with some rethinking.
- switch state {
- case let .connected(connState), let .connecting(connState), let .reconnecting(connState),
- let .negotiatingPostQuantumKey(connState, _):
- state = .disconnecting(connState)
- return [
- .stopTunnelMonitor,
- .stopDefaultPathObserver,
- .stopTunnelAdapter,
- .setDisconnectedState,
- ]
- case .error:
- return [
- .stopDefaultPathObserver,
- .stopTunnelAdapter,
- .setDisconnectedState,
- ]
+ fileprivate static func subreducerForStop(_ state: inout State) -> [PacketTunnelActor.Effect] {
+ // a call of the reducer produces one state transition and a sequence of effects. In the app, a stop transitions to .disconnecting, shuts down various processes, and finally transitions to .disconnected. We currently do this by having an effect which acknowledges the completion of disconnection and just sets the state. This is a bit messy, and could possibly do with some rethinking.
+ switch state {
+ case let .connected(connState), let .connecting(connState), let .reconnecting(connState),
+ let .negotiatingPostQuantumKey(connState, _):
+ state = .disconnecting(connState)
+ return [
+ .stopTunnelMonitor,
+ .stopDefaultPathObserver,
+ .stopTunnelAdapter,
+ .setDisconnectedState,
+ ]
+ case .error:
+ return [
+ .stopDefaultPathObserver,
+ .stopTunnelAdapter,
+ .setDisconnectedState,
+ ]
- case .initial, .disconnected:
- return []
+ case .initial, .disconnected:
+ return []
- case .disconnecting:
- assertionFailure("stop(): out of order execution.")
- return []
+ case .disconnecting:
+ assertionFailure("stop(): out of order execution.")
+ return []
+ }
}
- }
- fileprivate static func subreducerForReconnect(
- _ state: State,
- _ reason: PacketTunnelActor.ReconnectReason,
- _ nextRelay: NextRelay
- ) -> [PacketTunnelActor.Effect] {
- switch state {
- case .disconnected, .disconnecting, .initial:
- // There is no connection monitoring going on when exchanging keys.
- // The procedure starts from scratch for each reconnection attempts.
- return []
- case .connecting, .connected, .reconnecting, .error, .negotiatingPostQuantumKey:
- if reason == .userInitiated {
- return [.stopTunnelMonitor, .restartConnection(nextRelay, reason)]
- } else {
- return [.restartConnection(nextRelay, reason)]
+ fileprivate static func subreducerForReconnect(
+ _ state: State,
+ _ reason: PacketTunnelActor.ReconnectReason,
+ _ nextRelay: NextRelay
+ ) -> [PacketTunnelActor.Effect] {
+ switch state {
+ case .disconnected, .disconnecting, .initial:
+ // There is no connection monitoring going on when exchanging keys.
+ // The procedure starts from scratch for each reconnection attempts.
+ return []
+ case .connecting, .connected, .reconnecting, .error, .negotiatingPostQuantumKey:
+ if reason == .userInitiated {
+ return [.stopTunnelMonitor, .restartConnection(nextRelay, reason)]
+ } else {
+ return [.restartConnection(nextRelay, reason)]
+ }
}
}
- }
- fileprivate static func subreducerForSwitchKey(_ state: inout State) -> [PacketTunnelActor.Effect] {
- let oldKeyPolicy = state.keyPolicy
- state.mutateKeyPolicy { keyPolicy in
- if case .usePrior = keyPolicy {
- keyPolicy = .useCurrent
+ fileprivate static func subreducerForSwitchKey(_ state: inout State) -> [PacketTunnelActor.Effect] {
+ let oldKeyPolicy = state.keyPolicy
+ state.mutateKeyPolicy { keyPolicy in
+ if case .usePrior = keyPolicy {
+ keyPolicy = .useCurrent
+ }
}
+ if case .error = state { return [] }
+ return state.keyPolicy != oldKeyPolicy ? [.reconnect(.random)] : []
}
- if case .error = state { return [] }
- return state.keyPolicy != oldKeyPolicy ? [.reconnect(.random)] : []
- }
- fileprivate static func subreducerForTunnelMonitorEvent(
- _ event: TunnelMonitorEvent,
- _ state: inout State
- ) -> [PacketTunnelActor.Effect] {
- switch event {
- case .connectionEstablished:
- switch state {
- case var .connecting(connState), var .reconnecting(connState):
- // Reset connection attempt once successfully connected.
- connState.connectionAttemptCount = 0
- state = .connected(connState)
+ fileprivate static func subreducerForTunnelMonitorEvent(
+ _ event: TunnelMonitorEvent,
+ _ state: inout State
+ ) -> [PacketTunnelActor.Effect] {
+ switch event {
+ case .connectionEstablished:
+ switch state {
+ case var .connecting(connState), var .reconnecting(connState):
+ // Reset connection attempt once successfully connected.
+ connState.connectionAttemptCount = 0
+ state = .connected(connState)
- case .initial, .connected, .disconnecting, .disconnected, .error, .negotiatingPostQuantumKey:
- break
- }
- return []
- case .connectionLost:
- switch state {
- case .connecting, .reconnecting, .connected:
- return [.restartConnection(.random, .connectionLoss)]
- case .initial, .disconnected, .disconnecting, .error, .negotiatingPostQuantumKey:
+ case .initial, .connected, .disconnecting, .disconnected, .error, .negotiatingPostQuantumKey:
+ break
+ }
return []
+ case .connectionLost:
+ switch state {
+ case .connecting, .reconnecting, .connected:
+ return [.restartConnection(.random, .connectionLoss)]
+ case .initial, .disconnected, .disconnecting, .error, .negotiatingPostQuantumKey:
+ return []
+ }
}
}
}
func runReducer(_ event: Event) -> [Effect] {
- PacketTunnelActor.reducer(&state, event)
+ PacketTunnelActor.Reducer.reduce(&state, event)
}
}