@@ -158,41 +158,47 @@ final class CoderVPNService: NSObject, VPNService {
158
158
}
159
159
160
160
extension CoderVPNService {
161
+ // The number of NETunnelProviderSession states makes the excessive branching
162
+ // necessary.
161
163
// swiftlint:disable:next cyclomatic_complexity
162
164
@objc private func vpnDidUpdate( _ notification: Notification ) {
163
165
guard let connection = notification. object as? NETunnelProviderSession else {
164
166
return
165
167
}
166
- switch connection. status {
167
- case . disconnected:
168
+ switch ( tunnelState, connection. status) {
169
+ // Any -> Disconnected: Update UI w/ error if present
170
+ case ( _, . disconnected) :
168
171
connection. fetchLastDisconnectError { err in
169
172
self . tunnelState = if let err {
170
173
. failed( . internalError( err. localizedDescription) )
171
174
} else {
172
175
. disabled
173
176
}
174
177
}
175
- case . connecting:
176
- // If transitioning to 'connecting' from any other state,
177
- // then the network extension is running, and we can connect over XPC
178
- if tunnelState != . connecting {
179
- xpc. connect ( )
180
- xpc. ping ( )
181
- tunnelState = . connecting
182
- }
183
- case . connected:
184
- // If transitioning to 'connected' from any other state, the tunnel has
185
- // finished starting, and we can learn the peer state
186
- if tunnelState != . connected {
187
- xpc. connect ( )
188
- xpc. getPeerState ( )
189
- tunnelState = . connected
190
- }
191
- case . reasserting:
178
+ // Connecting -> Connecting: no-op
179
+ case ( . connecting, . connecting) :
180
+ break
181
+ // Connected -> Connected: no-op
182
+ case ( . connected, . connected) :
183
+ break
184
+ // Non-connecting -> Connecting: Establish XPC
185
+ case ( _, . connecting) :
186
+ xpc. connect ( )
187
+ xpc. ping ( )
188
+ tunnelState = . connecting
189
+ // Non-connected -> Connected: Retrieve Peers
190
+ case ( _, . connected) :
191
+ xpc. connect ( )
192
+ xpc. getPeerState ( )
193
+ tunnelState = . connected
194
+ // Any -> Reasserting
195
+ case ( _, . reasserting) :
192
196
tunnelState = . connecting
193
- case . disconnecting:
197
+ // Any -> Disconnecting
198
+ case ( _, . disconnecting) :
194
199
tunnelState = . disconnecting
195
- case . invalid:
200
+ // Any -> Invalid
201
+ case ( _, . invalid) :
196
202
tunnelState = . failed( . networkExtensionError( . unconfigured) )
197
203
@unknown default :
198
204
tunnelState = . disabled
0 commit comments