@@ -70,8 +70,6 @@ final class CoderVPNService: NSObject, VPNService {
70
70
Task {
71
71
await loadNetworkExtensionConfig ( )
72
72
}
73
- xpc. connect ( )
74
- xpc. getPeerState ( )
75
73
NotificationCenter . default. addObserver (
76
74
self ,
77
75
selector: #selector( vpnDidUpdate ( _: ) ) ,
@@ -93,8 +91,6 @@ final class CoderVPNService: NSObject, VPNService {
93
91
}
94
92
95
93
await startTunnel ( )
96
- xpc. connect ( )
97
- xpc. ping ( )
98
94
logger. debug ( " network extension enabled " )
99
95
}
100
96
@@ -162,28 +158,47 @@ final class CoderVPNService: NSObject, VPNService {
162
158
}
163
159
164
160
extension CoderVPNService {
161
+ // The number of NETunnelProviderSession states makes the excessive branching
162
+ // necessary.
163
+ // swiftlint:disable:next cyclomatic_complexity
165
164
@objc private func vpnDidUpdate( _ notification: Notification ) {
166
165
guard let connection = notification. object as? NETunnelProviderSession else {
167
166
return
168
167
}
169
- switch connection. status {
170
- case . disconnected:
168
+ switch ( tunnelState, connection. status) {
169
+ // Any -> Disconnected: Update UI w/ error if present
170
+ case ( _, . disconnected) :
171
171
connection. fetchLastDisconnectError { err in
172
172
self . tunnelState = if let err {
173
173
. failed( . internalError( err. localizedDescription) )
174
174
} else {
175
175
. disabled
176
176
}
177
177
}
178
- case . connecting:
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 ( )
179
188
tunnelState = . connecting
180
- case . connected:
189
+ // Non-connected -> Connected: Retrieve Peers
190
+ case ( _, . connected) :
191
+ xpc. connect ( )
192
+ xpc. getPeerState ( )
181
193
tunnelState = . connected
182
- case . reasserting:
194
+ // Any -> Reasserting
195
+ case ( _, . reasserting) :
183
196
tunnelState = . connecting
184
- case . disconnecting:
197
+ // Any -> Disconnecting
198
+ case ( _, . disconnecting) :
185
199
tunnelState = . disconnecting
186
- case . invalid:
200
+ // Any -> Invalid
201
+ case ( _, . invalid) :
187
202
tunnelState = . failed( . networkExtensionError( . unconfigured) )
188
203
@unknown default :
189
204
tunnelState = . disabled
0 commit comments