@@ -41,7 +41,6 @@ enum VPNServiceError: Error, Equatable {
4141final class CoderVPNService : NSObject , VPNService {
4242var logger = Logger ( subsystem: Bundle . main. bundleIdentifier!, category: " vpn " )
4343 lazyvar xpc : VPNXPCInterface = . init( vpn: self )
44- var terminating = false
4544var workspaces : [ UUID : String ] = [ : ]
4645
4746@Published var tunnelState : VPNServiceState = . disabled
@@ -68,8 +67,14 @@ final class CoderVPNService: NSObject, VPNService {
6867 super. init ( )
6968installSystemExtension ( )
7069Task {
71- await loadNetworkExtension ( )
70+ neState= if await hasNetworkExtensionConfig ( ) {
71+ . disabled
72+ } else {
73+ . unconfigured
74+ }
7275}
76+ xpc. connect ( )
77+ xpc. getPeerState ( )
7378NotificationCenter . default. addObserver (
7479self ,
7580 selector: #selector( vpnDidUpdate ( _: ) ) ,
@@ -82,6 +87,11 @@ final class CoderVPNService: NSObject, VPNService {
8287NotificationCenter . default. removeObserver ( self )
8388}
8489
90+ func clearPeers( ) {
91+ agents= [ : ]
92+ workspaces= [ : ]
93+ }
94+
8595func start( ) async {
8696switch tunnelState{
8797case . disabled, . failed:
@@ -90,31 +100,18 @@ final class CoderVPNService: NSObject, VPNService {
90100return
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
99109func stop( ) async {
100110guard tunnelState== . connectedelse { 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== . connectedelse {
111- NSApp . reply ( toApplicationShouldTerminate: true )
112- return
113- }
114- terminating= true
115- await stop ( )
116- }
117-
118115func configureTunnelProviderProtocol( proto: NETunnelProviderProtocol ? ) {
119116Task {
120117if let proto{
@@ -145,6 +142,22 @@ final class CoderVPNService: NSObject, VPNService {
145142}
146143}
147144
145+ func onExtensionPeerState( _ data: Data ? ) {
146+ guard let dataelse {
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+
148161func applyPeerUpdate( with update: Vpn_PeerUpdate ) {
149162 // Delete agents
150163 update. deletedAgents
@@ -204,9 +217,6 @@ extension CoderVPNService {
204217}
205218switch connection. status{
206219case . disconnected:
207- if terminating{
208- NSApp . reply ( toApplicationShouldTerminate: true )
209- }
210220 connection. fetchLastDisconnectError { errin
211221self . tunnelState= if let err{
212222. failed( . internalError( err. localizedDescription) )