diff --git a/FlyingSocks/Sources/Socket+Android.swift b/FlyingSocks/Sources/Socket+Android.swift index b311308..e9bb2d8 100644 --- a/FlyingSocks/Sources/Socket+Android.swift +++ b/FlyingSocks/Sources/Socket+Android.swift @@ -99,6 +99,24 @@ extension Socket { return addr } + static func makeAbstractNamespaceUnix(name: String) -> Android.sockaddr_un { + var addr: sockaddr_un = Android.sockaddr_un() + addr.sun_family = sa_family_t(AF_UNIX) + + _ = withUnsafeMutableBytes(of: &addr.sun_path) { raw in + raw.initializeMemory(as: CChar.self, repeating: 0) + } + + let nameBytes = Array(name.utf8.prefix(107)) + nameBytes.withUnsafeBytes { src in + withUnsafeMutableBytes(of: &addr.sun_path) { dst in + dst[1 ..< 1 + src.count].copyBytes(from: src) + } + } + + return addr + } + static func socket(_ domain: Int32, _ type: Int32, _ protocol: Int32) -> FileDescriptorType { Android.socket(domain, type, `protocol`) } diff --git a/FlyingSocks/Sources/Socket+Glibc.swift b/FlyingSocks/Sources/Socket+Glibc.swift index 56103bc..bd6a001 100644 --- a/FlyingSocks/Sources/Socket+Glibc.swift +++ b/FlyingSocks/Sources/Socket+Glibc.swift @@ -96,6 +96,24 @@ extension Socket { return addr } + static func makeAbstractNamespaceUnix(name: String) -> Glibc.sockaddr_un { + var addr: sockaddr_un = Glibc.sockaddr_un() + addr.sun_family = sa_family_t(AF_UNIX) + + _ = withUnsafeMutableBytes(of: &addr.sun_path) { raw in + raw.initializeMemory(as: CChar.self, repeating: 0) + } + + let nameBytes = Array(name.utf8.prefix(107)) + nameBytes.withUnsafeBytes { src in + withUnsafeMutableBytes(of: &addr.sun_path) { dst in + dst[1 ..< 1 + src.count].copyBytes(from: src) + } + } + + return addr + } + static func socket(_ domain: Int32, _ type: Int32, _ protocol: Int32) -> FileDescriptorType { Glibc.socket(domain, type, `protocol`) } diff --git a/FlyingSocks/Sources/Socket+Musl.swift b/FlyingSocks/Sources/Socket+Musl.swift index 7e7ebc0..dfd074a 100644 --- a/FlyingSocks/Sources/Socket+Musl.swift +++ b/FlyingSocks/Sources/Socket+Musl.swift @@ -96,6 +96,24 @@ extension Socket { return addr } + static func makeAbstractNamespaceUnix(name: String) -> Musl.sockaddr_un { + var addr: sockaddr_un = Musl.sockaddr_un() + addr.sun_family = sa_family_t(AF_UNIX) + + _ = withUnsafeMutableBytes(of: &addr.sun_path) { raw in + raw.initializeMemory(as: CChar.self, repeating: 0) + } + + let nameBytes = Array(name.utf8.prefix(107)) + nameBytes.withUnsafeBytes { src in + withUnsafeMutableBytes(of: &addr.sun_path) { dst in + dst[1 ..< 1 + src.count].copyBytes(from: src) + } + } + + return addr + } + static func socket(_ domain: Int32, _ type: Int32, _ protocol: Int32) -> FileDescriptorType { Musl.socket(domain, type, `protocol`) } diff --git a/FlyingSocks/Sources/Socket+WinSock2.swift b/FlyingSocks/Sources/Socket+WinSock2.swift index 41c31bc..4421f5f 100755 --- a/FlyingSocks/Sources/Socket+WinSock2.swift +++ b/FlyingSocks/Sources/Socket+WinSock2.swift @@ -107,6 +107,24 @@ extension Socket { return addr } + static func makeAbstractNamespaceUnix(name: String) -> WinSDK.sockaddr_un { + var addr: sockaddr_un = WinSDK.sockaddr_un() + addr.sun_family = ADDRESS_FAMILY(AF_UNIX) + + _ = withUnsafeMutableBytes(of: &addr.sun_path) { raw in + raw.initializeMemory(as: CChar.self, repeating: 0) + } + + let nameBytes = Array(name.utf8.prefix(107)) + nameBytes.withUnsafeBytes { src in + withUnsafeMutableBytes(of: &addr.sun_path) { dst in + dst[1 ..< 1 + src.count].copyBytes(from: src) + } + } + + return addr + } + static func fcntl(_ fd: FileDescriptorType, _ cmd: Int32) -> Int32 { return -1 } diff --git a/FlyingSocks/Sources/SocketAddress.swift b/FlyingSocks/Sources/SocketAddress.swift index 93df552..789d779 100644 --- a/FlyingSocks/Sources/SocketAddress.swift +++ b/FlyingSocks/Sources/SocketAddress.swift @@ -107,10 +107,15 @@ public extension SocketAddress where Self == sockaddr_in6 { } public extension SocketAddress where Self == sockaddr_un { - static func unix(path: String) -> Self { Socket.makeAddressUnix(path: path) } + + #if canImport(Glibc) || canImport(Musl) || canImport(Android) || canImport(WinSDK) + static func unix(abstractNamespace: String) -> Self { + Socket.makeAbstractNamespaceUnix(name: abstractNamespace) + } + #endif } #if compiler(>=6.0) diff --git a/FlyingSocks/Tests/SocketAddressTests.swift b/FlyingSocks/Tests/SocketAddressTests.swift index 39bbbfb..c022a8c 100644 --- a/FlyingSocks/Tests/SocketAddressTests.swift +++ b/FlyingSocks/Tests/SocketAddressTests.swift @@ -148,6 +148,23 @@ struct SocketAddressTests { ) } + #if canImport(Glibc) || canImport(Musl) || canImport(Android) || canImport(WinSDK) + @Test + func unixAbstractNamespace_IsCorrectlyDecodedFromStorage() throws { + let storage = sockaddr_un + .unix(abstractNamespace: "mygreatnamespace") + .makeStorage() + + var unix = try sockaddr_un.make(from: storage) + let path = withUnsafePointer(to: &unix.sun_path.1) { + return String(cString: $0) + } + #expect( + path == "mygreatnamespace" + ) + } + #endif + @Test func unix_ThrowsInvalidAddress_WhenFamilyIncorrect() { let storage = sockaddr_in6 @@ -183,6 +200,16 @@ struct SocketAddressTests { ) } + #if canImport(Glibc) || canImport(Musl) || canImport(Android) || canImport(WinSDK) + @Test + func unixAbstractNamespace_CheckSize() throws { + let sun = sockaddr_un.unix(abstractNamespace: "some_great_namespace") + #expect( + sun.size == socklen_t(MemoryLayout.size) + ) + } + #endif + @Test func unknown_CheckSize() throws { var sa = sockaddr()