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

chore: use slim binary over dylib#210

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
ethanndickson merged 1 commit intomainfromethan/slim-over-dylib
Aug 6, 2025
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletionsCoder-Desktop/.swiftlint.yml
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -10,3 +10,5 @@ type_name:
identifier_name:
allowed_symbols:"_"
min_length:1
line_length:
ignores_urls:true
2 changes: 0 additions & 2 deletionsCoder-Desktop/Coder-Desktop/VPN/VPNProgress.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -54,8 +54,6 @@ struct VPNProgressView: View {
return0.4* downloadPercent
case.validating:
return0.43
case.removingQuarantine:
return0.46
case.startingTunnel:
return0.50
}
Expand Down
2 changes: 1 addition & 1 deletionCoder-Desktop/Coder-Desktop/Views/LoginForm.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -222,7 +222,7 @@ enum LoginError: Error {
case.outdatedCoderVersion:
"""
The Coder deployment must be version\(Validator.minimumCoderVersion)
or higher to use Coder Desktop.
or higher to usethis version ofCoder Desktop.
"""
caselet.failedAuth(err):
"Could not authenticate with Coder deployment:\n\(err.localizedDescription)"
Expand Down
136 changes: 90 additions & 46 deletionsCoder-Desktop/Coder-DesktopHelper/Manager.swift
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,26 +7,56 @@ actor Manager {
letcfg:ManagerConfig
lettelemetryEnricher:TelemetryEnricher

lettunnelHandle:TunnelHandle
lettunnelDaemon:TunnelDaemon
letspeaker:Speaker<Vpn_ManagerMessage,Vpn_TunnelMessage>
varreadLoop:Task<Void,anyError>!

// /var/root/Downloads
privateletdest=FileManager.default.urls(for:.downloadsDirectory, in:.userDomainMask)
.first!.appending(path:"coder-vpn.dylib")
#if arch(arm64)
privatestaticletbinaryName="coder-darwin-arm64"
#else
privatestaticletbinaryName="coder-darwin-amd64"
#endif

// /var/root/Library/Application Support/com.coder.Coder-Desktop/coder-darwin-{arm64,amd64}
privateletdest=try?FileManager.default
.url(for:.applicationSupportDirectory, in:.userDomainMask, appropriateFor:nil, create:true)
.appendingPathComponent(Bundle.main.bundleIdentifier??"com.coder.Coder-Desktop", isDirectory:true)
.appendingPathComponent(binaryName)

privateletlogger=Logger(subsystem:Bundle.main.bundleIdentifier!, category:"manager")

// swiftlint:disable:next function_body_length
init(cfg:ManagerConfig)asyncthrows(ManagerError){
self.cfg= cfg
telemetryEnricher=TelemetryEnricher()
#if arch(arm64)
letdylibPath= cfg.serverUrl.appending(path:"bin/coder-vpn-darwin-arm64.dylib")
#elseif arch(x86_64)
letdylibPath= cfg.serverUrl.appending(path:"bin/coder-vpn-darwin-amd64.dylib")
#else
fatalError("unknown architecture")
#endif
guardlet destelse{
// This should never happen
throw.fileError("Failed to create path for binary destination"+
"(/var/root/Library/Application Support/com.coder.Coder-Desktop)")
}
do{
tryFileManager.default.ensureDirectories(for: dest)
}catch{
throw.fileError(
"Failed to create directories for binary destination (\(dest)):\(error.localizedDescription)"
)
}
letclient=Client(url: cfg.serverUrl)
letbuildInfo:BuildInfoResponse
do{
buildInfo=tryawait client.buildInfo()
}catch{
throw.serverInfo(error.description)
}
guardlet serverSemver= buildInfo.semverelse{
throw.serverInfo("invalid version:\(buildInfo.version)")
}
guardValidator.minimumCoderVersion
.compare(serverSemver, options:.numeric)!=.orderedDescending
else{
throw.belowMinimumCoderVersion(actualVersion: serverSemver)
}
letbinaryPath= cfg.serverUrl.appending(path:"bin").appending(path:Manager.binaryName)
do{
letsessionConfig=URLSessionConfiguration.default
// The tunnel might be asked to start before the network interfaces have woken up from sleep
Expand All@@ -35,7 +65,7 @@ actor Manager {
sessionConfig.timeoutIntervalForRequest=60
sessionConfig.timeoutIntervalForResource=300
tryawaitdownload(
src:dylibPath,
src:binaryPath,
dest: dest,
urlSession:URLSession(configuration: sessionConfig)
){ progressin
Expand All@@ -45,48 +75,46 @@ actor Manager {
throw.download(error)
}
pushProgress(stage:.validating)
letclient=Client(url: cfg.serverUrl)
letbuildInfo:BuildInfoResponse
do{
buildInfo=tryawait client.buildInfo()
tryValidator.validate(path: dest)
}catch{
throw.serverInfo(error.description)
}
guardlet semver= buildInfo.semverelse{
throw.serverInfo("invalid version:\(buildInfo.version)")
// Cleanup unvalid binary
try?FileManager.default.removeItem(at: dest)
throw.validation(error)
}

// Without this, the TUN fd isn't recognised as a socket in the
// spawned process, and the tunnel fails to start.
do{
tryValidator.validate(path: dest, expectedVersion: semver)
tryunsetCloseOnExec(fd: cfg.tunFd)
}catch{
throw.validation(error)
throw.cloexec(error)
}

do{
try tunnelHandle=TunnelHandle(dylibPath: dest)
try tunnelDaemon=awaitTunnelDaemon(binaryPath: dest){ errin
Task{try?awaitNEXPCServerDelegate.cancelProvider(error:
makeNSError(suffix:"TunnelDaemon", desc:"Tunnel daemon:\(err.description)")
)}
}
}catch{
throw.tunnelSetup(error)
}
speaker=awaitSpeaker<Vpn_ManagerMessage,Vpn_TunnelMessage>(
writeFD:tunnelHandle.writeHandle,
readFD:tunnelHandle.readHandle
writeFD:tunnelDaemon.writeHandle,
readFD:tunnelDaemon.readHandle
)
do{
tryawait speaker.handshake()
}catch{
throw.handshake(error)
}
do{
tryawait tunnelHandle.openTunnelTask?.value
}catchlet error asTunnelHandleError{
logger.error("failed to wait for dylib to open tunnel:\(error, privacy:.public)")
throw.tunnelSetup(error)
}catch{
fatalError("openTunnelTask must only throw TunnelHandleError")
}

readLoop=Task{tryawaitrun()}
}

deinit{ logger.debug("manager deinit")}

func run()asyncthrows{
do{
fortryawaitmin speaker{
Expand All@@ -99,14 +127,14 @@ actor Manager {
}
}catch{
logger.error("tunnel read loop failed:\(error.localizedDescription, privacy:.public)")
tryawaittunnelHandle.close()
tryawaittunnelDaemon.close()
tryawaitNEXPCServerDelegate.cancelProvider(error:
makeNSError(suffix:"Manager", desc:"Tunnel read loop failed:\(error.localizedDescription)")
)
return
}
logger.info("tunnel read loop exited")
tryawaittunnelHandle.close()
tryawaittunnelDaemon.close()
tryawaitNEXPCServerDelegate.cancelProvider(error:nil)
}

Expand DownExpand Up@@ -204,6 +232,12 @@ actor Manager {
if !stopResp.success{
throw.errorResponse(msg: stopResp.errorMessage)
}
do{
tryawait tunnelDaemon.close()
}catch{
throw.tunnelFail(error)
}
readLoop.cancel()
}

// Retrieves the current state of all peers,
Expand DownExpand Up@@ -239,28 +273,32 @@ struct ManagerConfig {

enumManagerError:Error{
case download(DownloadError)
case tunnelSetup(TunnelHandleError)
case fileError(String)
case tunnelSetup(TunnelDaemonError)
case handshake(HandshakeError)
case validation(ValidationError)
case incorrectResponse(Vpn_TunnelMessage)
case cloexec(POSIXError)
case failedRPC(anyError)
case serverInfo(String)
case errorResponse(msg:String)
case noTunnelFileDescriptor
case noApp
case permissionDenied
case tunnelFail(anyError)
case belowMinimumCoderVersion(actualVersion:String)

vardescription:String{
switchself{
caselet.download(err):
"Download error:\(err.localizedDescription)"
caselet.fileError(msg):
msg
caselet.tunnelSetup(err):
"Tunnel setup error:\(err.localizedDescription)"
caselet.handshake(err):
"Handshake error:\(err.localizedDescription)"
caselet.validation(err):
"Validation error:\(err.localizedDescription)"
caselet.cloexec(err):
"Failed to mark TUN fd as non-cloexec:\(err.localizedDescription)"
case.incorrectResponse:
"Received unexpected response over tunnel"
caselet.failedRPC(err):
Expand All@@ -269,14 +307,13 @@ enum ManagerError: Error {
msg
caselet.errorResponse(msg):
msg
case.noTunnelFileDescriptor:
"Could not find a tunnel file descriptor"
case.noApp:
"The VPN must be started with the app open during first-time setup."
case.permissionDenied:
"Permission was not granted to execute the CoderVPN dylib"
caselet.tunnelFail(err):
"Failed to communicate with dylib over tunnel:\(err.localizedDescription)"
"Failed to communicate with daemon over tunnel:\(err.localizedDescription)"
caselet.belowMinimumCoderVersion(actualVersion):
"""
The Coder deployment must be version\(Validator.minimumCoderVersion)
or higher to use Coder Desktop. Current version:\(actualVersion)
"""
}
}

Expand All@@ -297,9 +334,16 @@ func writeVpnLog(_ log: Vpn_Log) {
case.UNRECOGNIZED:.info
}
letlogger=Logger(
subsystem:"\(Bundle.main.bundleIdentifier!).dylib",
subsystem:"\(Bundle.main.bundleIdentifier!).daemon",
category: log.loggerNames.joined(separator:".")
)
letfields= log.fields.map{"\($0.name):\($0.value)"}.joined(separator:",")
logger.log(level: level,"\(log.message, privacy:.public)\(fields.isEmpty?"":":\(fields)", privacy:.public)")
}

extensionFileManager{
func ensureDirectories(for url:URL)throws{
letdir= url.hasDirectoryPath? url: url.deletingLastPathComponent()
trycreateDirectory(at: dir, withIntermediateDirectories:true, attributes:nil)
}
}
116 changes: 0 additions & 116 deletionsCoder-Desktop/Coder-DesktopHelper/TunnelHandle.swift
View file
Open in desktop

This file was deleted.

View file
Open in desktop

This file was deleted.

Loading
Loading

[8]ページ先頭

©2009-2025 Movatter.jp