Bind and connect to Unix domain sockets using relative paths

This commit is contained in:
Nikolay Edigaryev 2026-02-05 14:28:46 +01:00
parent 372affb0dc
commit fe1ddf30b5
5 changed files with 32 additions and 8 deletions

View File

@ -47,8 +47,16 @@ struct Exec: AsyncParsableCommand {
try! group.syncShutdownGracefully()
}
// Change the current working directory to a VM's base directory
// to work around Unix domain socket 104 byte limitation [1]
//
// [1]: https://blog.8-p.info/en/2020/06/11/unix-domain-socket-length/
if let baseURL = vmDir.controlSocketURL.baseURL {
FileManager.default.changeCurrentDirectoryPath(baseURL.path())
}
let channel = try GRPCChannelPool.with(
target: .unixDomainSocket(vmDir.controlSocketURL.path()),
target: .unixDomainSocket(vmDir.controlSocketURL.relativePath),
transportSecurity: .plaintext,
eventLoopGroup: group,
)

View File

@ -68,7 +68,15 @@ struct IP: AsyncParsableCommand {
throw RuntimeError.Generic("Cannot perform IP resolution via Tart Guest Agent when control socket URL is not set")
}
if let ip = try await AgentResolver.ResolveIP(controlSocketURL) {
// Change the current working directory to a VM's base directory
// to work around Unix domain socket 104 byte limitation [1]
//
// [1]: https://blog.8-p.info/en/2020/06/11/unix-domain-socket-length/
if let baseURL = controlSocketURL.baseURL {
FileManager.default.changeCurrentDirectoryPath(baseURL.path())
}
if let ip = try await AgentResolver.ResolveIP(controlSocketURL.relativePath) {
return ip
}
}

View File

@ -21,8 +21,16 @@ class ControlSocket {
// if any, otherwise we may get the "address already in use" error
try? FileManager.default.removeItem(atPath: controlSocketURL.path())
// Change the current working directory to a VM's base directory
// to work around Unix domain socket 104 byte limitation [1]
//
// [1]: https://blog.8-p.info/en/2020/06/11/unix-domain-socket-length/
if let baseURL = controlSocketURL.baseURL {
FileManager.default.changeCurrentDirectoryPath(baseURL.path())
}
let serverChannel = try await ServerBootstrap(group: eventLoopGroup)
.bind(unixDomainSocketPath: controlSocketURL.path()) { childChannel in
.bind(unixDomainSocketPath: controlSocketURL.relativePath) { childChannel in
childChannel.eventLoop.makeCompletedFuture {
return try NIOAsyncChannel<ByteBuffer, ByteBuffer>(
wrappingChannelSynchronously: childChannel

View File

@ -6,15 +6,15 @@ import Cirruslabs_TartGuestAgent_Apple_Swift
import Cirruslabs_TartGuestAgent_Grpc_Swift
class AgentResolver {
static func ResolveIP(_ controlSocketURL: URL) async throws -> IPv4Address? {
static func ResolveIP(_ controlSocketPath: String) async throws -> IPv4Address? {
do {
return try await resolveIP(controlSocketURL)
return try await resolveIP(controlSocketPath)
} catch let error as GRPCConnectionPoolError {
return nil
}
}
private static func resolveIP(_ controlSocketURL: URL) async throws -> IPv4Address? {
private static func resolveIP(_ controlSocketPath: String) async throws -> IPv4Address? {
// Create a gRPC channel connected to the VM's control socket
let group = MultiThreadedEventLoopGroup(numberOfThreads: 1)
defer {
@ -22,7 +22,7 @@ class AgentResolver {
}
let channel = try GRPCChannelPool.with(
target: .unixDomainSocket(controlSocketURL.path()),
target: .unixDomainSocket(controlSocketPath),
transportSecurity: .plaintext,
eventLoopGroup: group,
)

View File

@ -27,7 +27,7 @@ struct VMDirectory: Prunable {
baseURL.appendingPathComponent("manifest.json")
}
var controlSocketURL: URL {
baseURL.appendingPathComponent("control.sock")
URL(fileURLWithPath: "control.sock", relativeTo: baseURL)
}
var explicitlyPulledMark: URL {