@@ -41,7 +41,6 @@ enum VPNServiceError: Error, Equatable {
4141final class CoderVPNService : NSObject , VPNService {
4242 var logger = Logger ( subsystem: Bundle . main. bundleIdentifier!, category: " vpn " )
4343 lazy var xpc : VPNXPCInterface = . init( vpn: self )
44- var terminating = false
4544 var workspaces : [ UUID : String ] = [ : ]
4645
4746 @Published var tunnelState : VPNServiceState = . disabled
@@ -68,8 +67,14 @@ final class CoderVPNService: NSObject, VPNService {
6867 super. init ( )
6968 installSystemExtension ( )
7069 Task {
71- await loadNetworkExtension ( )
70+ neState = if await hasNetworkExtensionConfig ( ) {
71+ . disabled
72+ } else {
73+ . unconfigured
74+ }
7275 }
76+ xpc. connect ( )
77+ xpc. getPeerState ( )
7378 NotificationCenter . default. addObserver (
7479 self ,
7580 selector: #selector( vpnDidUpdate ( _: ) ) ,
@@ -82,6 +87,11 @@ final class CoderVPNService: NSObject, VPNService {
8287 NotificationCenter . default. removeObserver ( self )
8388 }
8489
90+ func clearPeers( ) {
91+ agents = [ : ]
92+ workspaces = [ : ]
93+ }
94+
8595 func start( ) async {
8696 switch tunnelState {
8797 case . disabled, . failed:
@@ -90,31 +100,18 @@ final class CoderVPNService: NSObject, VPNService {
90100 return
91101 }
92102
93- await enableNetworkExtension ( )
94- // this ping is somewhat load bearing since it causes xpc to init
103+ await startTunnel ( )
104+ xpc. connect ( )
95105 xpc. ping ( )
96106 logger. debug ( " network extension enabled " )
97107 }
98108
99109 func stop( ) async {
100110 guard tunnelState == . connected else { return }
101- await disableNetworkExtension ( )
111+ await stopTunnel ( )
102112 logger. info ( " network extension stopped " )
103113 }
104114
105- // Instructs the service to stop the VPN and then quit once the stop event
106- // is read over XPC.
107- // MUST only be called from `NSApplicationDelegate.applicationShouldTerminate`
108- // MUST eventually call `NSApp.reply(toApplicationShouldTerminate: true)`
109- func quit( ) async {
110- guard tunnelState == . connected else {
111- NSApp . reply ( toApplicationShouldTerminate: true )
112- return
113- }
114- terminating = true
115- await stop ( )
116- }
117-
118115 func configureTunnelProviderProtocol( proto: NETunnelProviderProtocol ? ) {
119116 Task {
120117 if let proto {
@@ -145,6 +142,22 @@ final class CoderVPNService: NSObject, VPNService {
145142 }
146143 }
147144
145+ func onExtensionPeerState( _ data: Data ? ) {
146+ guard let data else {
147+ logger. error ( " could not retrieve peer state from network extension, it may not be running " )
148+ return
149+ }
150+ logger. info ( " received network extension peer state " )
151+ do {
152+ let msg = try Vpn_PeerUpdate ( serializedBytes: data)
153+ debugPrint ( msg)
154+ clearPeers ( )
155+ applyPeerUpdate ( with: msg)
156+ } catch {
157+ logger. error ( " failed to decode peer update \( error) " )
158+ }
159+ }
160+
148161 func applyPeerUpdate( with update: Vpn_PeerUpdate ) {
149162 // Delete agents
150163 update. deletedAgents
@@ -204,9 +217,6 @@ extension CoderVPNService {
204217 }
205218 switch connection. status {
206219 case . disconnected:
207- if terminating {
208- NSApp . reply ( toApplicationShouldTerminate: true )
209- }
210220 connection. fetchLastDisconnectError { err in
211221 self . tunnelState = if let err {
212222 . failed( . internalError( err. localizedDescription) )
0 commit comments