Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit06b4c16

Browse files
fix: concurrently open tunnel & handshake (#30)
1 parentfdb8545 commit06b4c16

File tree

9 files changed

+154
-29
lines changed

9 files changed

+154
-29
lines changed

‎Coder Desktop/Coder Desktop.xcodeproj/project.pbxproj

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,17 @@
1717
AA3B3DCE2D2D249F0099996A /* VPNLib.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B3DA12D2D23860099996A /* VPNLib.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
1818
AA3B3E8E2D2E0FF40099996A /* Mocker in Frameworks */ = {isa = PBXBuildFile; productRef = AA3B3E8D2D2E0FF40099996A /* Mocker */; };
1919
AA3B40992D2FC8560099996A /* CoderSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B40912D2FC8560099996A /* CoderSDK.framework */; };
20-
AA3B40A42D2FC8560099996A /* CoderSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B40912D2FC8560099996A /* CoderSDK.framework */; };
2120
AA3B40B62D2FD9DD0099996A /* Mocker in Frameworks */ = {isa = PBXBuildFile; productRef = AA3B40B52D2FD9DD0099996A /* Mocker */; };
2221
AA3B40B72D2FDA5C0099996A /* CoderSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B40912D2FC8560099996A /* CoderSDK.framework */; };
2322
AA3B40BD2D2FDFBA0099996A /* Mocker in Frameworks */ = {isa = PBXBuildFile; productRef = AA3B40BC2D2FDFBA0099996A /* Mocker */; };
2423
AA3B40C02D2FE7760099996A /* CoderSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B40912D2FC8560099996A /* CoderSDK.framework */; };
2524
AA8BC3392D0060A900E1ABAA /* ViewInspector in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC3382D0060A900E1ABAA /* ViewInspector */; };
2625
AA8BC33F2D0061F200E1ABAA /* FluidMenuBarExtra in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC33E2D0061F200E1ABAA /* FluidMenuBarExtra */; };
2726
AA8BC4CF2D00A4B700E1ABAA /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC4CE2D00A4B700E1ABAA /* KeychainAccess */; };
27+
AAC382352D427B7600F6DFB4 /* CoderSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B40912D2FC8560099996A /* CoderSDK.framework */; };
28+
AAC382362D427B7600F6DFB4 /* CoderSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B40912D2FC8560099996A /* CoderSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
29+
AAC382392D427B8300F6DFB4 /* CoderSDK.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B40912D2FC8560099996A /* CoderSDK.framework */; };
30+
AAC3823A2D427B8300F6DFB4 /* CoderSDK.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = AA3B40912D2FC8560099996A /* CoderSDK.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
2831
/* End PBXBuildFile section */
2932

3033
/* Begin PBXContainerItemProxy section */
@@ -105,6 +108,13 @@
105108
remoteGlobalIDString = AA3B40902D2FC8560099996A;
106109
remoteInfo = CoderSDK;
107110
};
111+
AAC382372D427B7600F6DFB4 /* PBXContainerItemProxy */ = {
112+
isa = PBXContainerItemProxy;
113+
containerPortal = 961678F42CFF100D00B2B6DF /* Project object */;
114+
proxyType = 1;
115+
remoteGlobalIDString = AA3B40902D2FC8560099996A;
116+
remoteInfo = CoderSDK;
117+
};
108118
/* End PBXContainerItemProxy section */
109119

110120
/* Begin PBXCopyFilesBuildPhase section */
@@ -126,6 +136,18 @@
126136
dstSubfolderSpec = 10;
127137
files = (
128138
AA3B3DCE2D2D249F0099996A /* VPNLib.framework in Embed Frameworks */,
139+
AAC382362D427B7600F6DFB4 /* CoderSDK.framework in Embed Frameworks */,
140+
);
141+
name = "Embed Frameworks";
142+
runOnlyForDeploymentPostprocessing = 0;
143+
};
144+
AAC3823B2D427B8300F6DFB4 /* Embed Frameworks */ = {
145+
isa = PBXCopyFilesBuildPhase;
146+
buildActionMask = 2147483647;
147+
dstPath = "";
148+
dstSubfolderSpec = 10;
149+
files = (
150+
AAC3823A2D427B8300F6DFB4 /* CoderSDK.framework in Embed Frameworks */,
129151
);
130152
name = "Embed Frameworks";
131153
runOnlyForDeploymentPostprocessing = 0;
@@ -228,8 +250,8 @@
228250
isa = PBXFrameworksBuildPhase;
229251
buildActionMask = 2147483647;
230252
files = (
231-
AA3B40A42D2FC8560099996A /* CoderSDK.framework in Frameworks */,
232253
AA8BC4CF2D00A4B700E1ABAA /* KeychainAccess in Frameworks */,
254+
AAC382392D427B8300F6DFB4 /* CoderSDK.framework in Frameworks */,
233255
AA2C690F2D34F6920059AFAF /* LaunchAtLogin in Frameworks */,
234256
AA8BC33F2D0061F200E1ABAA /* FluidMenuBarExtra in Frameworks */,
235257
);
@@ -257,6 +279,7 @@
257279
buildActionMask = 2147483647;
258280
files = (
259281
961679332CFF117300B2B6DF /* NetworkExtension.framework in Frameworks */,
282+
AAC382352D427B7600F6DFB4 /* CoderSDK.framework in Frameworks */,
260283
AA3B3DCD2D2D249F0099996A /* VPNLib.framework in Frameworks */,
261284
);
262285
runOnlyForDeploymentPostprocessing = 0;
@@ -366,6 +389,7 @@
366389
961678F92CFF100D00B2B6DF /* Frameworks */,
367390
961678FA2CFF100D00B2B6DF /* Resources */,
368391
961679422CFF117300B2B6DF /* Embed System Extensions */,
392+
AAC3823B2D427B8300F6DFB4 /* Embed Frameworks */,
369393
);
370394
buildRules = (
371395
);
@@ -452,6 +476,7 @@
452476
dependencies = (
453477
AA2C69922D354A8B0059AFAF /* PBXTargetDependency */,
454478
AA3B3DD02D2D249F0099996A /* PBXTargetDependency */,
479+
AAC382382D427B7600F6DFB4 /* PBXTargetDependency */,
455480
);
456481
fileSystemSynchronizedGroups = (
457482
AA3C69AD2D2D143400A45481 /* VPN */,
@@ -847,6 +872,11 @@
847872
target = AA3B40902D2FC8560099996A /* CoderSDK */;
848873
targetProxy = AA3B40C22D2FE7760099996A /* PBXContainerItemProxy */;
849874
};
875+
AAC382382D427B7600F6DFB4 /* PBXTargetDependency */ = {
876+
isa = PBXTargetDependency;
877+
target = AA3B40902D2FC8560099996A /* CoderSDK */;
878+
targetProxy = AAC382372D427B7600F6DFB4 /* PBXContainerItemProxy */;
879+
};
850880
/* End PBXTargetDependency section */
851881

852882
/* Begin XCBuildConfiguration section */
@@ -1216,6 +1246,7 @@
12161246
buildSettings = {
12171247
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
12181248
CODE_SIGN_IDENTITY = "";
1249+
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
12191250
CODE_SIGN_STYLE = Automatic;
12201251
COMBINE_HIDPI_IMAGES = YES;
12211252
CURRENT_PROJECT_VERSION = 1;
@@ -1324,6 +1355,7 @@
13241355
buildSettings = {
13251356
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
13261357
CODE_SIGN_IDENTITY = "";
1358+
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
13271359
CODE_SIGN_STYLE = Automatic;
13281360
COMBINE_HIDPI_IMAGES = YES;
13291361
CURRENT_PROJECT_VERSION = 1;

‎Coder Desktop/Coder Desktop/Coder_DesktopApp.swift

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ struct DesktopApp: App {
1111
EmptyView()
1212
}
1313
Window("Sign In", id:Windows.login.rawValue){
14-
LoginForm<PreviewSession>().environmentObject(appDelegate.session)
14+
LoginForm<SecureSession>()
15+
.environmentObject(appDelegate.session)
16+
.environmentObject(appDelegate.settings)
1517
}
1618
.windowResizability(.contentSize)
17-
SwiftUI.Settings{SettingsView<PreviewVPN>()
19+
SwiftUI.Settings{SettingsView<CoderVPNService>()
1820
.environmentObject(appDelegate.vpn)
1921
.environmentObject(appDelegate.settings)
2022
}
@@ -25,20 +27,20 @@ struct DesktopApp: App {
2527
@MainActor
2628
classAppDelegate:NSObject,NSApplicationDelegate{
2729
privatevarmenuBarExtra:FluidMenuBarExtra?
28-
letvpn:PreviewVPN
29-
letsession:PreviewSession
30+
letvpn:CoderVPNService
31+
letsession:SecureSession
3032
letsettings:Settings
3133

3234
overrideinit(){
3335
// TODO: Replace with real implementation
34-
vpn=PreviewVPN()
36+
vpn=CoderVPNService()
3537
settings=Settings()
36-
session=PreviewSession()
38+
session=SecureSession(onChange: vpn.configureTunnelProviderProtocol)
3739
}
3840

3941
func applicationDidFinishLaunching(_:Notification){
4042
menuBarExtra=FluidMenuBarExtra(title:"Coder Desktop", image:"MenuBarIcon"){
41-
VPNMenu<PreviewVPN,PreviewSession>().frame(width:256)
43+
VPNMenu<CoderVPNService,SecureSession>().frame(width:256)
4244
.environmentObject(self.vpn)
4345
.environmentObject(self.session)
4446
.environmentObject(self.settings)

‎Coder Desktop/Coder Desktop/NetworkExtension.swift

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,17 @@ import os
33

44
enumNetworkExtensionState:Equatable{
55
case unconfigured
6-
casedisbled
6+
casedisabled
77
case enabled
88
case failed(String)
99

1010
vardescription:String{
1111
switchself{
1212
case.unconfigured:
13-
return"Not logged in to Coder"
13+
return"NetworkExtension not configured, try logging in again"
1414
case.enabled:
1515
return"NetworkExtension tunnel enabled"
16-
case.disbled:
16+
case.disabled:
1717
return"NetworkExtension tunnel disabled"
1818
caselet.failed(error):
1919
return"NetworkExtension config failed:\(error)"
@@ -24,6 +24,16 @@ enum NetworkExtensionState: Equatable {
2424
/// An actor that handles configuring, enabling, and disabling the VPN tunnel via the
2525
/// NetworkExtension APIs.
2626
extensionCoderVPNService{
27+
// Updates the UI if a previous configuration exists
28+
func loadNetworkExtension()async{
29+
do{
30+
tryawaitgetTunnelManager()
31+
neState=.disabled
32+
}catch{
33+
neState=.unconfigured
34+
}
35+
}
36+
2737
func configureNetworkExtension(proto:NETunnelProviderProtocol)async{
2838
// removing the old tunnels, rather than reconfiguring ensures that configuration changes
2939
// are picked up.
@@ -47,6 +57,7 @@ extension CoderVPNService {
4757
logger.error("save tunnel failed:\(error)")
4858
neState=.failed(error.localizedDescription)
4959
}
60+
neState=.disabled
5061
}
5162

5263
func removeNetworkExtension()asyncthrows(VPNServiceError){
@@ -91,9 +102,10 @@ extension CoderVPNService {
91102
return
92103
}
93104
logger.debug("saved tunnel with enabled=false")
94-
neState=.disbled
105+
neState=.disabled
95106
}
96107

108+
@discardableResult
97109
privatefunc getTunnelManager()asyncthrows(VPNServiceError)->NETunnelProviderManager{
98110
vartunnels:[NETunnelProviderManager]=[]
99111
do{

‎Coder Desktop/Coder Desktop/VPNService.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ final class CoderVPNService: NSObject, VPNService {
5050
guard sysExtnState==.installedelse{
5151
return.failed(.systemExtensionError(sysExtnState))
5252
}
53-
guard neState==.enabled || neState==.disbledelse{
53+
guard neState==.enabled || neState==.disabledelse{
5454
return.failed(.networkExtensionError(neState))
5555
}
5656
return tunnelState
@@ -66,6 +66,9 @@ final class CoderVPNService: NSObject, VPNService {
6666
overrideinit(){
6767
super.init()
6868
installSystemExtension()
69+
Task{
70+
awaitloadNetworkExtension()
71+
}
6972
}
7073

7174
varstartTask:Task<Void,Never>?

‎Coder Desktop/VPN/Manager.swift

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,14 @@ actor Manager {
1616
.first!.appending(path:"coder-vpn.dylib")
1717
privateletlogger=Logger(subsystem:Bundle.main.bundleIdentifier!, category:"manager")
1818

19+
// swiftlint:disable:next function_body_length
1920
init(with:PacketTunnelProvider, cfg:ManagerConfig)asyncthrows(ManagerError){
2021
ptp= with
2122
self.cfg= cfg
2223
#if arch(arm64)
23-
letdylibPath= cfg.serverUrl.appending(path:"bin/coder-vpn-arm64.dylib")
24+
letdylibPath= cfg.serverUrl.appending(path:"bin/coder-vpn-darwin-arm64.dylib")
2425
#elseif arch(x86_64)
25-
letdylibPath= cfg.serverUrl.appending(path:"bin/coder-vpn-amd64.dylib")
26+
letdylibPath= cfg.serverUrl.appending(path:"bin/coder-vpn-darwin-amd64.dylib")
2627
#else
2728
fatalError("unknown architecture")
2829
#endif
@@ -60,6 +61,14 @@ actor Manager {
6061
}catch{
6162
throw.handshake(error)
6263
}
64+
do{
65+
tryawait tunnelHandle.openTunnelTask?.value
66+
}catchlet error asTunnelHandleError{
67+
logger.error("failed to wait for dylib to open tunnel:\(error, privacy:.public)")
68+
throw.tunnelSetup(error)
69+
}catch{
70+
fatalError("openTunnelTask must only throw TunnelHandleError")
71+
}
6372
readLoop=Task{tryawaitrun()}
6473
}
6574

@@ -180,7 +189,7 @@ actor Manager {
180189
}
181190
}
182191

183-
publicstructManagerConfig{
192+
structManagerConfig{
184193
letapiToken:String
185194
letserverUrl:URL
186195
}
@@ -195,6 +204,29 @@ enum ManagerError: Error {
195204
case serverInfo(String)
196205
case errorResponse(msg:String)
197206
case noTunnelFileDescriptor
207+
208+
vardescription:String{
209+
switchself{
210+
caselet.download(err):
211+
return"Download error:\(err)"
212+
caselet.tunnelSetup(err):
213+
return"Tunnel setup error:\(err)"
214+
caselet.handshake(err):
215+
return"Handshake error:\(err)"
216+
caselet.validation(err):
217+
return"Validation error:\(err)"
218+
case.incorrectResponse:
219+
return"Received unexpected response over tunnel"
220+
caselet.failedRPC(err):
221+
return"Failed rpc:\(err)"
222+
caselet.serverInfo(msg):
223+
return msg
224+
caselet.errorResponse(msg):
225+
return msg
226+
case.noTunnelFileDescriptor:
227+
return"Could not find a tunnel file descriptor"
228+
}
229+
}
198230
}
199231

200232
func writeVpnLog(_ log:Vpn_Log){

‎Coder Desktop/VPN/PacketTunnelProvider.swift

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import NetworkExtension
22
import os
3+
import VPNLib
34

45
/* From <sys/kern_control.h> */
56
letCTLIOCGINFO:UInt=0xC064_4E03
@@ -8,7 +9,7 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
89
privateletlogger=Logger(subsystem:Bundle.main.bundleIdentifier!, category:"provider")
910
privatevarmanager:Manager?
1011

11-
publicvartunnelFileDescriptor:Int32?{
12+
vartunnelFileDescriptor:Int32?{
1213
varctlInfo=ctl_info()
1314
withUnsafeMutablePointer(to:&ctlInfo.ctl_name){
1415
$0.withMemoryRebound(to:CChar.self, capacity:MemoryLayout.size(ofValue: $0.pointee)){
@@ -47,19 +48,25 @@ class PacketTunnelProvider: NEPacketTunnelProvider, @unchecked Sendable {
4748
completionHandler(nil)
4849
return
4950
}
51+
letcompletionHandler=CallbackWrapper(completionHandler)
5052
Task{
5153
// TODO: Retrieve access URL & Token via Keychain
52-
manager=tryawaitManager(
53-
with:self,
54-
cfg:.init(apiToken:"fake-token", serverUrl:.init(string:"https://dev.coder.com")!)
55-
)
54+
dothrows(ManagerError){
55+
manager=tryawaitManager(
56+
with:self,
57+
cfg:.init(apiToken:"fake-token", serverUrl:.init(string:"https://dev.coder.com")!)
58+
)
59+
completionHandler(nil)
60+
} catch{
61+
completionHandler(error)
62+
logger.error("error starting manager:\(error.description, privacy:.public)")
63+
}
5664
}
57-
completionHandler(nil)
5865
}
5966

6067
overridefunc stopTunnel(with _:NEProviderStopReason, completionHandler:@escaping()->Void){
6168
logger.debug("stopTunnel called")
62-
guard manager==nilelse{
69+
guard manager!=nilelse{
6370
logger.error("stopTunnel called with nil Manager")
6471
completionHandler()
6572
return

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp