Skip to content

Commit 27ab4a7

Browse files
committed
review
1 parent b7c9f58 commit 27ab4a7

File tree

4 files changed

+31
-76
lines changed

4 files changed

+31
-76
lines changed

Coder Desktop/Coder Desktop/Coder_DesktopApp.swift

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class AppDelegate: NSObject, NSApplicationDelegate {
4747
}
4848
}
4949

50-
// MUST eventually call `NSApp.reply(toApplicationShouldTerminate: true)`
50+
// This function MUST eventually call `NSApp.reply(toApplicationShouldTerminate: true)`
5151
// or return `.terminateNow`
5252
func applicationShouldTerminate(_: NSApplication) -> NSApplication.TerminateReply {
5353
if !settings.stopVPNOnQuit { return .terminateNow }

Coder Desktop/Coder Desktop/NetworkExtension.swift

+12-3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,15 @@ enum NetworkExtensionState: Equatable {
2424
/// An actor that handles configuring, enabling, and disabling the VPN tunnel via the
2525
/// NetworkExtension APIs.
2626
extension CoderVPNService {
27+
func hasNetworkExtensionConfig() async -> Bool {
28+
do {
29+
_ = try await getTunnelManager()
30+
return true
31+
} catch {
32+
return false
33+
}
34+
}
35+
2736
func configureNetworkExtension(proto: NETunnelProviderProtocol) async {
2837
// removing the old tunnels, rather than reconfiguring ensures that configuration changes
2938
// are picked up.
@@ -61,7 +70,7 @@ extension CoderVPNService {
6170
}
6271
}
6372

64-
func enableNetworkExtension() async {
73+
func startTunnel() async {
6574
do {
6675
let tm = try await getTunnelManager()
6776
try tm.connection.startVPNTunnel()
@@ -74,7 +83,7 @@ extension CoderVPNService {
7483
neState = .enabled
7584
}
7685

77-
func disableNetworkExtension() async {
86+
func stopTunnel() async {
7887
do {
7988
let tm = try await getTunnelManager()
8089
tm.connection.stopVPNTunnel()
@@ -88,7 +97,7 @@ extension CoderVPNService {
8897
}
8998

9099
@discardableResult
91-
func getTunnelManager() async throws(VPNServiceError) -> NETunnelProviderManager {
100+
private func getTunnelManager() async throws(VPNServiceError) -> NETunnelProviderManager {
92101
var tunnels: [NETunnelProviderManager] = []
93102
do {
94103
tunnels = try await NETunnelProviderManager.loadAllFromPreferences()

Coder Desktop/Coder Desktop/SystemExtension.swift

+5-62
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,7 @@ protocol SystemExtensionAsyncRecorder: Sendable {
2929
extension CoderVPNService: SystemExtensionAsyncRecorder {
3030
func recordSystemExtensionState(_ state: SystemExtensionState) async {
3131
sysExtnState = state
32-
if state == .uninstalled {
33-
installSystemExtension()
34-
}
3532
if state == .installed {
36-
do {
37-
try await getTunnelManager()
38-
neState = .disabled
39-
} catch {
40-
neState = .unconfigured
41-
}
4233
// system extension was successfully installed, so we don't need the delegate any more
4334
systemExtnDelegate = nil
4435
}
@@ -73,21 +64,7 @@ extension CoderVPNService: SystemExtensionAsyncRecorder {
7364
return extensionBundle
7465
}
7566

76-
func attemptSystemExtensionInstall() {
77-
logger.info("checking SystemExtension status")
78-
guard let bundleID = extensionBundle.bundleIdentifier else {
79-
logger.error("Bundle has no identifier")
80-
return
81-
}
82-
let request = OSSystemExtensionRequest.propertiesRequest(forExtensionWithIdentifier: bundleID, queue: .main)
83-
let delegate = SystemExtensionDelegate(asyncDelegate: self)
84-
request.delegate = delegate
85-
systemExtnDelegate = delegate
86-
OSSystemExtensionManager.shared.submitRequest(request)
87-
logger.info("submitted SystemExtension properties request with bundleID: \(bundleID)")
88-
}
89-
90-
private func installSystemExtension() {
67+
func installSystemExtension() {
9168
logger.info("activating SystemExtension")
9269
guard let bundleID = extensionBundle.bundleIdentifier else {
9370
logger.error("Bundle has no identifier")
@@ -97,9 +74,11 @@ extension CoderVPNService: SystemExtensionAsyncRecorder {
9774
forExtensionWithIdentifier: bundleID,
9875
queue: .main
9976
)
100-
request.delegate = systemExtnDelegate
77+
let delegate = SystemExtensionDelegate(asyncDelegate: self)
78+
systemExtnDelegate = delegate
79+
request.delegate = delegate
10180
OSSystemExtensionManager.shared.submitRequest(request)
102-
logger.info("submitted SystemExtension activate request with bundleID: \(bundleID)")
81+
logger.info("submitted SystemExtension request with bundleID: \(bundleID)")
10382
}
10483
}
10584

@@ -109,8 +88,6 @@ class SystemExtensionDelegate<AsyncDelegate: SystemExtensionAsyncRecorder>:
10988
NSObject, OSSystemExtensionRequestDelegate
11089
{
11190
private var logger = Logger(subsystem: Bundle.main.bundleIdentifier!, category: "vpn-installer")
112-
// TODO: Refactor this to use a continuation, so the result of a request can be
113-
// 'await'd for the determined state
11491
private var asyncDelegate: AsyncDelegate
11592

11693
init(asyncDelegate: AsyncDelegate) {
@@ -161,38 +138,4 @@ class SystemExtensionDelegate<AsyncDelegate: SystemExtensionAsyncRecorder>:
161138
logger.info("Replacing \(request.identifier) v\(existing.bundleShortVersion) with v\(`extension`.bundleShortVersion)")
162139
return .replace
163140
}
164-
165-
public func request(
166-
_: OSSystemExtensionRequest,
167-
foundProperties properties: [OSSystemExtensionProperties]
168-
) {
169-
// In debug builds we always replace the SE to test
170-
// changes made without bumping the version
171-
#if DEBUG
172-
Task { [asyncDelegate] in
173-
await asyncDelegate.recordSystemExtensionState(.uninstalled)
174-
}
175-
return
176-
#else
177-
let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleVersion") as? String
178-
let shortVersion = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") as? String
179-
180-
let versionMatches = properties.contains { sysex in
181-
sysex.isEnabled
182-
&& sysex.bundleVersion == version
183-
&& sysex.bundleShortVersion == shortVersion
184-
}
185-
if versionMatches {
186-
Task { [asyncDelegate] in
187-
await asyncDelegate.recordSystemExtensionState(.installed)
188-
}
189-
return
190-
}
191-
192-
// Either uninstalled or needs replacing
193-
Task { [asyncDelegate] in
194-
await asyncDelegate.recordSystemExtensionState(.uninstalled)
195-
}
196-
#endif
197-
}
198141
}

Coder Desktop/Coder Desktop/VPNService.swift

+13-10
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,15 @@ final class CoderVPNService: NSObject, VPNService {
6565

6666
override init() {
6767
super.init()
68-
attemptSystemExtensionInstall()
68+
installSystemExtension()
69+
Task {
70+
neState = if await hasNetworkExtensionConfig() {
71+
.disabled
72+
} else {
73+
.unconfigured
74+
}
75+
}
76+
xpc.getPeerState()
6977
NotificationCenter.default.addObserver(
7078
self,
7179
selector: #selector(vpnDidUpdate(_:)),
@@ -91,15 +99,15 @@ final class CoderVPNService: NSObject, VPNService {
9199
return
92100
}
93101

94-
await enableNetworkExtension()
102+
await startTunnel()
95103
// this ping is somewhat load bearing since it causes xpc to init
96104
xpc.ping()
97105
logger.debug("network extension enabled")
98106
}
99107

100108
func stop() async {
101109
guard tunnelState == .connected else { return }
102-
await disableNetworkExtension()
110+
await stopTunnel()
103111
logger.info("network extension stopped")
104112
}
105113

@@ -134,11 +142,11 @@ final class CoderVPNService: NSObject, VPNService {
134142
}
135143

136144
func onExtensionPeerState(_ data: Data?) {
137-
logger.info("network extension peer state")
138145
guard let data else {
139-
logger.error("could not retrieve peer state from network extension")
146+
logger.error("could not retrieve peer state from network extension, it may not be running")
140147
return
141148
}
149+
logger.info("received network extension peer state")
142150
do {
143151
let msg = try Vpn_PeerUpdate(serializedBytes: data)
144152
debugPrint(msg)
@@ -218,11 +226,6 @@ extension CoderVPNService {
218226
case .connecting:
219227
tunnelState = .connecting
220228
case .connected:
221-
// If we moved from disabled to connected, then the NE was already
222-
// running, and we need to request the current peer state
223-
if tunnelState == .disabled {
224-
xpc.getPeerState()
225-
}
226229
tunnelState = .connected
227230
case .reasserting:
228231
tunnelState = .connecting

0 commit comments

Comments
 (0)