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