Skip to content

Commit

Permalink
Musl
Browse files Browse the repository at this point in the history
  • Loading branch information
swhitty committed Sep 27, 2024
1 parent 3c81443 commit 68b5086
Show file tree
Hide file tree
Showing 7 changed files with 319 additions and 1 deletion.
49 changes: 49 additions & 0 deletions FlyingFox/Sources/SocketAddress+Musl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// SocketAddress+Musl.swift
// FlyingFox
//
// Created by Simon Whitty on 23/09/2024.
// Copyright © 2024 Simon Whitty. All rights reserved.
//
// Distributed under the permissive MIT license
// Get the latest version from here:
//
// https://github.com/swhitty/FlyingFox
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#if canImport(Musl)
// swift on linux fails to import comformance for these Glibc types 🤷🏻‍♂️:
import Musl
import FlyingSocks

extension sockaddr_in: SocketAddress {
public static let family = sa_family_t(AF_INET)
}

extension sockaddr_in6: SocketAddress {
public static let family = sa_family_t(AF_INET6)
}

extension sockaddr_un: SocketAddress {
public static let family = sa_family_t(AF_UNIX)
}

#endif
42 changes: 42 additions & 0 deletions FlyingSocks/Sources/Mutex.swift
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,48 @@ extension Mutex {
}
}

#elseif canImport(Musl)

import Musl

extension Mutex {

final class Storage {
private let _lock: UnsafeMutablePointer<pthread_mutex_t>

var value: Value

init(_ initialValue: Value) {
var attr = pthread_mutexattr_t()
pthread_mutexattr_init(&attr)
self._lock = .allocate(capacity: 1)
let err = pthread_mutex_init(self._lock, &attr)
precondition(err == 0, "pthread_mutex_init error: \(err)")
self.value = initialValue
}

func lock() {
let err = pthread_mutex_lock(_lock)
precondition(err == 0, "pthread_mutex_lock error: \(err)")
}

func unlock() {
let err = pthread_mutex_unlock(_lock)
precondition(err == 0, "pthread_mutex_unlock error: \(err)")
}

func tryLock() -> Bool {
pthread_mutex_trylock(_lock) == 0
}

deinit {
let err = pthread_mutex_destroy(self._lock)
precondition(err == 0, "pthread_mutex_destroy error: \(err)")
self._lock.deallocate()
}
}
}

#elseif canImport(WinSDK)

import ucrt
Expand Down
171 changes: 171 additions & 0 deletions FlyingSocks/Sources/Socket+Musl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
//
// Socket+Glibc.swift
// FlyingFox
//
// Created by Simon Whitty on 19/02/2022.
// Copyright © 2022 Simon Whitty. All rights reserved.
//
// Distributed under the permissive MIT license
// Get the latest version from here:
//
// https://github.com/swhitty/FlyingFox
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#if canImport(Musl)
import Musl

public extension Socket {
typealias FileDescriptorType = Int32
}

extension Socket.FileDescriptor {
static let invalid = Socket.FileDescriptor(rawValue: -1)
}

extension Socket {
static let stream = Int32(SOCK_STREAM)
static let in_addr_any = Musl.in_addr(s_addr: Musl.in_addr_t(0))

static func makeAddressINET(port: UInt16) -> Musl.sockaddr_in {
Musl.sockaddr_in(
sin_family: sa_family_t(AF_INET),
sin_port: port.bigEndian,
sin_addr: in_addr_any,
sin_zero: (0, 0, 0, 0, 0, 0, 0, 0)
)
}

static func makeAddressINET6(port: UInt16) -> Musl.sockaddr_in6 {
Musl.sockaddr_in6(
sin6_family: sa_family_t(AF_INET6),
sin6_port: port.bigEndian,
sin6_flowinfo: 0,
sin6_addr: in6addr_any,
sin6_scope_id: 0
)
}

static func makeAddressLoopback(port: UInt16) -> Musl.sockaddr_in6 {
Musl.sockaddr_in6(
sin6_family: sa_family_t(AF_INET6),
sin6_port: port.bigEndian,
sin6_flowinfo: 0,
sin6_addr: in6addr_loopback,
sin6_scope_id: 0
)
}

static func makeAddressUnix(path: String) -> Musl.sockaddr_un {
var addr = Musl.sockaddr_un()
addr.sun_family = sa_family_t(AF_UNIX)
let pathCount = min(path.utf8.count, 104)
let len = UInt8(MemoryLayout<UInt8>.size + MemoryLayout<sa_family_t>.size + pathCount + 1)
_ = withUnsafeMutablePointer(to: &addr.sun_path.0) { ptr in
path.withCString {
strncpy(ptr, $0, Int(len))
}
}
return addr
}

static func socket(_ domain: Int32, _ type: Int32, _ protocol: Int32) -> Int32 {
Musl.socket(domain, type, `protocol`)
}

static func fcntl(_ fd: Int32, _ cmd: Int32) -> Int32 {
Musl.fcntl(fd, cmd)
}

static func fcntl(_ fd: Int32, _ cmd: Int32, _ value: Int32) -> Int32 {
Musl.fcntl(fd, cmd, value)
}

static func setsockopt(_ fd: Int32, _ level: Int32, _ name: Int32,
_ value: UnsafeRawPointer!, _ len: socklen_t) -> Int32 {
Musl.setsockopt(fd, level, name, value, len)
}

static func getsockopt(_ fd: Int32, _ level: Int32, _ name: Int32,
_ value: UnsafeMutableRawPointer!, _ len: UnsafeMutablePointer<socklen_t>!) -> Int32 {
Musl.getsockopt(fd, level, name, value, len)
}

static func getpeername(_ fd: Int32, _ addr: UnsafeMutablePointer<sockaddr>!, _ len: UnsafeMutablePointer<socklen_t>!) -> Int32 {
Musl.getpeername(fd, addr, len)
}

static func getsockname(_ fd: Int32, _ addr: UnsafeMutablePointer<sockaddr>!, _ len: UnsafeMutablePointer<socklen_t>!) -> Int32 {
Musl.getsockname(fd, addr, len)
}

static func inet_ntop(_ domain: Int32, _ addr: UnsafeRawPointer!,
_ buffer: UnsafeMutablePointer<CChar>!, _ addrLen: socklen_t) throws {
if Musl.inet_ntop(domain, addr, buffer, addrLen) == nil {
throw SocketError.makeFailed("inet_ntop")
}
}

static func inet_pton(_ domain: Int32, _ buffer: UnsafePointer<CChar>!, _ addr: UnsafeMutableRawPointer!) -> Int32 {
Musl.inet_pton(domain, buffer, addr)
}

static func bind(_ fd: Int32, _ addr: UnsafePointer<sockaddr>!, _ len: socklen_t) -> Int32 {
Musl.bind(fd, addr, len)
}

static func listen(_ fd: Int32, _ backlog: Int32) -> Int32 {
Musl.listen(fd, backlog)
}

static func accept(_ fd: Int32, _ addr: UnsafeMutablePointer<sockaddr>!, _ len: UnsafeMutablePointer<socklen_t>!) -> Int32 {
Musl.accept(fd, addr, len)
}

static func connect(_ fd: Int32, _ addr: UnsafePointer<sockaddr>!, _ len: socklen_t) -> Int32 {
Musl.connect(fd, addr, len)
}

static func read(_ fd: Int32, _ buffer: UnsafeMutableRawPointer!, _ nbyte: Int) -> Int {
Musl.read(fd, buffer, nbyte)
}

static func write(_ fd: Int32, _ buffer: UnsafeRawPointer!, _ nbyte: Int) -> Int {
Musl.send(fd, buffer, nbyte, Int32(MSG_NOSIGNAL))
}

static func close(_ fd: Int32) -> Int32 {
Musl.close(fd)
}

static func unlink(_ addr: UnsafePointer<CChar>!) -> Int32 {
Musl.unlink(addr)
}

static func poll(_ fds: UnsafeMutablePointer<pollfd>!, _ nfds: UInt32, _ tmo_p: Int32) -> Int32 {
Musl.poll(fds, UInt(nfds), tmo_p)
}

static func pollfd(fd: FileDescriptorType, events: Int16, revents: Int16) -> Musl.pollfd {
Musl.pollfd(fd: fd, events: events, revents: revents)
}
}

#endif
4 changes: 4 additions & 0 deletions FlyingSocks/Sources/Socket+Pair.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@

#if canImport(Darwin)
import Darwin
#elseif canImport(Musl)
import Musl
#else
import Glibc
#endif
Expand All @@ -41,6 +43,8 @@ package extension Socket {
var sockets: [Int32] = [-1, -1]
#if canImport(Darwin)
_ = Darwin.socketpair(domain, type, `protocol`, &sockets)
#elseif canImport(Musl)
_ = Musl.socketpair(domain, type, `protocol`, &sockets)
#else
_ = Glibc.socketpair(domain, type, `protocol`, &sockets)
#endif
Expand Down
11 changes: 11 additions & 0 deletions FlyingSocks/Sources/SocketPool+ePoll.swift
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,24 @@ extension EventNotification {
private struct EPOLLEvents: OptionSet, Hashable {
var rawValue: UInt32

#if canImport(Musl)
static let read = EPOLLEvents(rawValue: UInt32(EPOLLIN))
static let write = EPOLLEvents(rawValue: UInt32(EPOLLOUT))
static let hup = EPOLLEvents(rawValue: UInt32(EPOLLHUP))
static let rdhup = EPOLLEvents(rawValue: UInt32(EPOLLRDHUP))
static let err = EPOLLEvents(rawValue: UInt32(EPOLLERR))
static let pri = EPOLLEvents(rawValue: UInt32(EPOLLPRI))
static let edgeTriggered = EPOLLEvents(rawValue: UInt32(EPOLLET))
#else
static let read = EPOLLEvents(rawValue: EPOLLIN.rawValue)
static let write = EPOLLEvents(rawValue: EPOLLOUT.rawValue)
static let hup = EPOLLEvents(rawValue: EPOLLHUP.rawValue)
static let rdhup = EPOLLEvents(rawValue: EPOLLRDHUP.rawValue)
static let err = EPOLLEvents(rawValue: EPOLLERR.rawValue)
static let pri = EPOLLEvents(rawValue: EPOLLPRI.rawValue)
static let edgeTriggered = EPOLLEvents(rawValue: EPOLLET.rawValue)
#endif

}

private extension Socket.Events {
Expand Down
41 changes: 41 additions & 0 deletions FlyingSocks/XCTests/SocketAddress+Musl.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// SocketAddress+Musl.swift
// FlyingFox
//
// Created by Simon Whitty on 23/09/2024.
// Copyright © 2024 Simon Whitty. All rights reserved.
//
// Distributed under the permissive MIT license
// Get the latest version from here:
//
// https://github.com/swhitty/FlyingFox
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//

#if canImport(Musl)
import Musl
import FlyingSocks

extension sockaddr_in: SocketAddress { }

extension sockaddr_in6: SocketAddress { }

extension sockaddr_un: SocketAddress { }
#endif
2 changes: 1 addition & 1 deletion docker-run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@ set -eu
docker run -it \
--rm \
--mount src="$(pwd)",target=/flyingfox,type=bind \
swiftlang/swift:nightly-jammy \
swift/latest \
/usr/bin/swift test --package-path /flyingfox

0 comments on commit 68b5086

Please sign in to comment.