Files
umn/Sources/umnd/IPCServer.swift
T
2026-08-31 15:55:09 -05:00

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()
}
}
}
}