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

Commit161e5c2

Browse files
chore: add dylib downloader and validator (#16)
First PR for#2.This PR adds an abstraction for downloading & validating the dylib from a Coder server, and the network extension scaffolding.It also adds a `TunnelHandle` type for owning the pair of pipes passed to the dylib, and the handle to the dylib itself.You cannot create a unit test target that targets a System Extension. So, this PR extracts the portion of the network extension that we'd like to test into it's own Framework, `VPNLib`.Of note is that `SwiftProtobuf` doesn't have a stable ABI (as it doesn't use [library evolution](https://www.swift.org/blog/library-evolution/)), so the Framework has the `Build libraries for distribution` setting disabled. This shouldn't effect anything. Exporting the `SwiftProtobuf` types should be fine provided we don't import `SwiftProtobuf` in to the `VPN` target as well.
1 parente9f5c6f commit161e5c2

21 files changed

+1059
-387
lines changed

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

Lines changed: 304 additions & 75 deletions
Large diffs are not rendered by default.

‎Coder Desktop/Coder Desktop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more aboutcustomizing how changed files appear on GitHub.

‎Coder Desktop/Coder Desktop.xcodeproj/xcshareddata/xcschemes/Coder Desktop.xcscheme

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,20 @@
6262
parallelizable ="YES">
6363
<BuildableReference
6464
BuildableIdentifier ="primary"
65-
BlueprintIdentifier ="961679D82D030E1D00B2B6DF"
66-
BuildableName ="ProtoTests.xctest"
67-
BlueprintName ="ProtoTests"
65+
BlueprintIdentifier ="AA3B3DA02D2D23860099996A"
66+
BuildableName ="VPNLib.framework"
67+
BlueprintName ="VPNLib"
68+
ReferencedContainer ="container:Coder Desktop.xcodeproj">
69+
</BuildableReference>
70+
</TestableReference>
71+
<TestableReference
72+
skipped ="NO"
73+
parallelizable ="YES">
74+
<BuildableReference
75+
BuildableIdentifier ="primary"
76+
BlueprintIdentifier ="AA3B3DA72D2D23860099996A"
77+
BuildableName ="VPNLibTests.xctest"
78+
BlueprintName ="VPNLibTests"
6879
ReferencedContainer ="container:Coder Desktop.xcodeproj">
6980
</BuildableReference>
7081
</TestableReference>

‎Coder Desktop/Coder Desktop.xcodeproj/xcshareddata/xcschemes/ProtoTests.xcschemerenamed to‎Coder Desktop/Coder Desktop.xcodeproj/xcshareddata/xcschemes/VPN.xcscheme

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,29 @@
66
parallelizeBuildables ="YES"
77
buildImplicitDependencies ="YES"
88
buildArchitectures ="Automatic">
9+
<BuildActionEntries>
10+
<BuildActionEntry
11+
buildForTesting ="YES"
12+
buildForRunning ="YES"
13+
buildForProfiling ="YES"
14+
buildForArchiving ="YES"
15+
buildForAnalyzing ="YES">
16+
<BuildableReference
17+
BuildableIdentifier ="primary"
18+
BlueprintIdentifier ="9616792F2CFF117300B2B6DF"
19+
BuildableName ="com.coder.Coder-Desktop.VPN.systemextension"
20+
BlueprintName ="VPN"
21+
ReferencedContainer ="container:Coder Desktop.xcodeproj">
22+
</BuildableReference>
23+
</BuildActionEntry>
24+
</BuildActionEntries>
925
</BuildAction>
1026
<TestAction
1127
buildConfiguration ="Debug"
1228
selectedDebuggerIdentifier ="Xcode.DebuggerFoundation.Debugger.LLDB"
1329
selectedLauncherIdentifier ="Xcode.DebuggerFoundation.Launcher.LLDB"
1430
shouldUseLaunchSchemeArgsEnv ="YES"
1531
shouldAutocreateTestPlan ="YES">
16-
<Testables>
17-
<TestableReference
18-
skipped ="NO"
19-
parallelizable ="YES">
20-
<BuildableReference
21-
BuildableIdentifier ="primary"
22-
BlueprintIdentifier ="961679D82D030E1D00B2B6DF"
23-
BuildableName ="ProtoTests.xctest"
24-
BlueprintName ="ProtoTests"
25-
ReferencedContainer ="container:Coder Desktop.xcodeproj">
26-
</BuildableReference>
27-
</TestableReference>
28-
</Testables>
2932
</TestAction>
3033
<LaunchAction
3134
buildConfiguration ="Debug"
@@ -37,16 +40,6 @@
3740
debugDocumentVersioning ="YES"
3841
debugServiceExtension ="internal"
3942
allowLocationSimulation ="YES">
40-
<BuildableProductRunnable
41-
runnableDebuggingMode ="0">
42-
<BuildableReference
43-
BuildableIdentifier ="primary"
44-
BlueprintIdentifier ="961678FB2CFF100D00B2B6DF"
45-
BuildableName ="Coder Desktop.app"
46-
BlueprintName ="Coder Desktop"
47-
ReferencedContainer ="container:Coder Desktop.xcodeproj">
48-
</BuildableReference>
49-
</BuildableProductRunnable>
5043
</LaunchAction>
5144
<ProfileAction
5245
buildConfiguration ="Release"
@@ -57,9 +50,9 @@
5750
<MacroExpansion>
5851
<BuildableReference
5952
BuildableIdentifier ="primary"
60-
BlueprintIdentifier ="961678FB2CFF100D00B2B6DF"
61-
BuildableName ="CoderDesktop.app"
62-
BlueprintName ="Coder Desktop"
53+
BlueprintIdentifier ="9616792F2CFF117300B2B6DF"
54+
BuildableName ="com.coder.Coder-Desktop.VPN.systemextension"
55+
BlueprintName ="VPN"
6356
ReferencedContainer ="container:Coder Desktop.xcodeproj">
6457
</BuildableReference>
6558
</MacroExpansion>

‎Coder Desktop/Coder Desktop.xctestplan

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
{
2020
"target" : {
2121
"containerPath" : "container:Coder Desktop.xcodeproj",
22-
"identifier" : "961679D82D030E1D00B2B6DF",
23-
"name" : "ProtoTests"
22+
"identifier" : "9616790E2CFF100E00B2B6DF",
23+
"name" : "Coder DesktopTests"
2424
}
2525
},
2626
{
2727
"target" : {
2828
"containerPath" : "container:Coder Desktop.xcodeproj",
29-
"identifier" : "9616790E2CFF100E00B2B6DF",
30-
"name" : "Coder DesktopTests"
29+
"identifier" : "AA3B3DA72D2D23860099996A",
30+
"name" : "VPNLibTests"
3131
}
3232
},
3333
{

‎Coder Desktop/Coder Desktop/SDK/Client.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import Alamofire
22
import Foundation
33

4-
protocolClient{
4+
protocolClient:Sendable{
55
init(url:URL, token:String?)
66
func user(_ ident:String)asyncthrows(ClientError)->User
77
}
@@ -114,10 +114,10 @@ struct APIError: Decodable {
114114
structResponse:Decodable{
115115
letmessage:String
116116
letdetail:String?
117-
letvalidations:[ValidationError]?
117+
letvalidations:[FieldValidation]?
118118
}
119119

120-
structValidationError:Decodable{
120+
structFieldValidation:Decodable{
121121
letfield:String
122122
letdetail:String
123123
}

‎Coder Desktop/VPN/Manager.swift

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import NetworkExtension
2+
import os
3+
import VPNLib
4+
5+
actorManager{
6+
letptp:PacketTunnelProvider
7+
8+
vartunnelHandle:TunnelHandle?
9+
varspeaker:Speaker<Vpn_ManagerMessage,Vpn_TunnelMessage>?
10+
// TODO: XPC Speaker
11+
12+
privateletdest=FileManager.default.urls(for:.documentDirectory, in:.userDomainMask)
13+
.first!.appending(path:"coder-vpn.dylib")
14+
privateletlogger=Logger(subsystem:Bundle.main.bundleIdentifier!, category:"manager")
15+
16+
init(with:PacketTunnelProvider){
17+
ptp= with
18+
}
19+
}

‎Coder Desktop/VPN/PacketTunnelProvider.swift

Lines changed: 54 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,62 @@
11
import NetworkExtension
2+
import os
23

3-
classPacketTunnelProvider:NEPacketTunnelProvider{
4-
overridefunc startTunnel(options _:[String:NSObject]?, completionHandler _:@escaping(Error?)->Void){
5-
// Add code here to start the process of connecting the tunnel.
4+
/* From <sys/kern_control.h> */
5+
letCTLIOCGINFO:UInt=0xC064_4E03
6+
7+
classPacketTunnelProvider:NEPacketTunnelProvider,@uncheckedSendable{
8+
privateletlogger=Logger(subsystem:Bundle.main.bundleIdentifier!, category:"network-extension")
9+
privatevarmanager:Manager?
10+
11+
privatevartunnelFileDescriptor:Int32?{
12+
varctlInfo=ctl_info()
13+
withUnsafeMutablePointer(to:&ctlInfo.ctl_name){
14+
$0.withMemoryRebound(to:CChar.self, capacity:MemoryLayout.size(ofValue: $0.pointee)){
15+
_=strcpy($0,"com.apple.net.utun_control")
16+
}
17+
}
18+
forfd:Int32in0...1024{
19+
varaddr=sockaddr_ctl()
20+
varret:Int32=-1
21+
varlen=socklen_t(MemoryLayout.size(ofValue: addr))
22+
withUnsafeMutablePointer(to:&addr){
23+
$0.withMemoryRebound(to: sockaddr.self, capacity:1){
24+
ret=getpeername(fd, $0,&len)
25+
}
26+
}
27+
if ret!=0 || addr.sc_family!= AF_SYSTEM{
28+
continue
29+
}
30+
if ctlInfo.ctl_id==0{
31+
ret=ioctl(fd, CTLIOCGINFO,&ctlInfo)
32+
if ret!=0{
33+
continue
34+
}
35+
}
36+
if addr.sc_id== ctlInfo.ctl_id{
37+
return fd
38+
}
39+
}
40+
returnnil
41+
}
42+
43+
overridefunc startTunnel(options _:[String:NSObject]?, completionHandler:@escaping(Error?)->Void){
44+
guard manager==nilelse{
45+
logger.error("startTunnel called with non-nil Manager")
46+
completionHandler(nil)
47+
return
48+
}
49+
manager=Manager(with:self)
50+
completionHandler(nil)
651
}
752

853
overridefunc stopTunnel(with _:NEProviderStopReason, completionHandler:@escaping()->Void){
9-
// Add code here to start the process of stopping the tunnel.
54+
guard manager==nilelse{
55+
logger.error("stopTunnel called with nil Manager")
56+
completionHandler()
57+
return
58+
}
59+
manager=nil
1060
completionHandler()
1161
}
1262

‎Coder Desktop/VPN/TunnelHandle.swift

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
import Foundation
2+
import os
3+
4+
letstartSymbol="OpenTunnel"
5+
6+
actorTunnelHandle{
7+
privateletlogger=Logger(subsystem:Bundle.main.bundleIdentifier!, category:"tunnel-handle")
8+
9+
privatelettunnelWritePipe:Pipe
10+
privatelettunnelReadPipe:Pipe
11+
privateletdylibHandle:UnsafeMutableRawPointer
12+
13+
varwriteHandle:FileHandle{ tunnelReadPipe.fileHandleForWriting}
14+
varreadHandle:FileHandle{ tunnelWritePipe.fileHandleForReading}
15+
16+
init(dylibPath:URL)throws(TunnelHandleError){
17+
guardlet dylibHandle=dlopen(dylibPath.path, RTLD_NOW | RTLD_LOCAL)else{
18+
throw.dylib(dlerror().flatMap{String(cString: $0)}??"UNKNOWN")
19+
}
20+
self.dylibHandle= dylibHandle
21+
22+
guardlet startSym=dlsym(dylibHandle, startSymbol)else{
23+
throw.symbol(startSymbol,dlerror().flatMap{String(cString: $0)}??"UNKNOWN")
24+
}
25+
letopenTunnelFn=unsafeBitCast(startSym, to:OpenTunnel.self)
26+
tunnelReadPipe=Pipe()
27+
tunnelWritePipe=Pipe()
28+
letres=openTunnelFn(tunnelReadPipe.fileHandleForReading.fileDescriptor,
29+
tunnelWritePipe.fileHandleForWriting.fileDescriptor)
30+
guard res==0else{
31+
throw.openTunnel(OpenTunnelError(rawValue: res)??.unknown)
32+
}
33+
}
34+
35+
// This could be an isolated deinit in Swift 6.1
36+
func close()throws(TunnelHandleError){
37+
varerrs:[Error]=[]
38+
ifdlclose(dylibHandle)==0{
39+
errs.append(TunnelHandleError.dylib(dlerror().flatMap{String(cString: $0)}??"UNKNOWN"))
40+
}
41+
do{
42+
try writeHandle.close()
43+
}catch{
44+
errs.append(error)
45+
}
46+
do{
47+
try readHandle.close()
48+
}catch{
49+
errs.append(error)
50+
}
51+
if !errs.isEmpty{
52+
throw.close(errs)
53+
}
54+
}
55+
}
56+
57+
enumTunnelHandleError:Error{
58+
case dylib(String)
59+
case symbol(String,String)
60+
case openTunnel(OpenTunnelError)
61+
case pipe(anyError)
62+
case close([anyError])
63+
64+
vardescription:String{
65+
switchself{
66+
caselet.pipe(err):return"pipe error:\(err)"
67+
caselet.dylib(d):return d
68+
caselet.symbol(symbol, message):return"\(symbol):\(message)"
69+
caselet.openTunnel(error):return"OpenTunnel:\(error.message)"
70+
caselet.close(errs):return"close tunnel:\(errs.map(\.localizedDescription).joined(separator:","))"
71+
}
72+
}
73+
}
74+
75+
enumOpenTunnelError:Int32{
76+
case errDupReadFD=-2
77+
case errDupWriteFD=-3
78+
case errOpenPipe=-4
79+
case errNewTunnel=-5
80+
case unknown=-99
81+
82+
varmessage:String{
83+
switchself{
84+
case.errDupReadFD:return"Failed to duplicate read file descriptor"
85+
case.errDupWriteFD:return"Failed to duplicate write file descriptor"
86+
case.errOpenPipe:return"Failed to open the pipe"
87+
case.errNewTunnel:return"Failed to create a new tunnel"
88+
case.unknown:return"Unknown error code"
89+
}
90+
}
91+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#ifndefCoderPacketTunnelProvider_Bridging_Header_h
2+
#defineCoderPacketTunnelProvider_Bridging_Header_h
3+
4+
// GoInt32 OpenTunnel(GoInt32 cReadFD, GoInt32 cWriteFD);
5+
typedefint(*OpenTunnel)(int,int);
6+
7+
#endif/* CoderPacketTunnelProvider_Bridging_Header_h */

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp