// // SDLNoticeClient.swift // Tun // // Created by 安礼成 on 2024/5/20. // import Foundation // // SDLanServer.swift // Tun // // Created by 安礼成 on 2024/1/31. // import Foundation import NIOCore import NIOPosix // 处理和sn-server服务器之间的通讯 final class SDLNoticeClient { private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1) let (writeStream, writeContinuation) = AsyncStream.makeStream(of: Data.self) private var task: Task? private var channel: Channel private let logger: SDLLogger private let noticePort: Int // 启动函数 init(noticePort: Int, logger: SDLLogger) throws { self.logger = logger self.noticePort = noticePort let bootstrap = DatagramBootstrap(group: self.group) .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) .channelInitializer { channel in channel.pipeline.addHandler(SDLNoticeClientInboundHandler()) } self.channel = try bootstrap.bind(host: "0.0.0.0", port: 0).wait() self.logger.log("[SDLNoticeClient] started", level: .debug) } func start() { let channel = self.channel self.task = Task.detached { self.logger.log("[SDLNoticeClient] task 11", level: .debug) guard let remoteAddress = try? await SDLAddressResolver.shared.resolve(host: "127.0.0.1", port: self.noticePort) else { self.logger.log("[SDLNoticeClient] task 22", level: .debug) return } for await data in self.writeStream { if Task.isCancelled { self.logger.log("[SDLNoticeClient] task 33", level: .debug) break } self.logger.log("[SDLNoticeClient] task 44", level: .debug) self.logger.log("[SDLNoticeClient] send packet", level: .debug) let buf = channel.allocator.buffer(bytes: data) let envelope = AddressedEnvelope(remoteAddress: remoteAddress, data: buf) channel.eventLoop.execute { channel.writeAndFlush(envelope, promise: nil) } } } } // 处理写入逻辑 func send(data: Data) { self.writeContinuation.yield(data) } func waitClose() async throws { try await self.channel.closeFuture.get() } deinit { self.writeContinuation.finish() self.task?.cancel() try? self.group.syncShutdownGracefully() } } extension SDLNoticeClient { private class SDLNoticeClientInboundHandler: ChannelInboundHandler { typealias InboundIn = AddressedEnvelope } }