61 lines
1.7 KiB
Swift
61 lines
1.7 KiB
Swift
import Foundation
|
|
import UltraMeshCore
|
|
|
|
final class IPCClient {
|
|
let fd: Int32
|
|
private let writeLock = NSLock()
|
|
private var closed = false
|
|
var onClose: ((IPCClient) -> Void)?
|
|
init(fd: Int32) { self.fd = fd }
|
|
|
|
func send(_ message: IPCMessage) {
|
|
writeLock.lock()
|
|
guard !closed else { writeLock.unlock(); return }
|
|
do { try UnixIPC.send(message, to: fd); writeLock.unlock() }
|
|
catch {
|
|
closed = true; writeLock.unlock()
|
|
UnixIPC.close(fd); onClose?(self)
|
|
}
|
|
}
|
|
|
|
func close() {
|
|
writeLock.lock()
|
|
guard !closed else { writeLock.unlock(); return }
|
|
closed = true; writeLock.unlock()
|
|
UnixIPC.close(fd); onClose?(self)
|
|
}
|
|
}
|
|
|
|
final class IPCServer {
|
|
private let path: String
|
|
private var server: Int32 = -1
|
|
private var running = true
|
|
var onMessage: ((IPCClient, IPCMessage) -> Void)?
|
|
|
|
init(path: String = UnixIPC.defaultSocketPath) { self.path = path }
|
|
|
|
func start() throws {
|
|
server = try UnixIPC.listen(path: path)
|
|
DispatchQueue.global(qos: .userInitiated).async { [weak self] in self?.acceptLoop() }
|
|
}
|
|
|
|
func stop() {
|
|
running = false
|
|
if server >= 0 { UnixIPC.close(server) }
|
|
unlink(path)
|
|
}
|
|
|
|
private func acceptLoop() {
|
|
while running {
|
|
guard let fd = try? UnixIPC.accept(server) else { if running { continue }; return }
|
|
let client = IPCClient(fd: fd)
|
|
DispatchQueue.global(qos: .userInitiated).async { [weak self] in
|
|
while let message = try? UnixIPC.receive(from: fd) {
|
|
self?.onMessage?(client, message)
|
|
}
|
|
client.close()
|
|
}
|
|
}
|
|
}
|
|
}
|