// // SDLUDPHoleV6.swift // Tun // // Created by 安礼成 on 2026/4/15. // import Foundation import NIOCore import NIOPosix import SwiftProtobuf // 处理和sn-server服务器之间的通讯 final class SDLUDPHoleV6: ChannelInboundHandler { typealias InboundIn = AddressedEnvelope // 事件 enum HoleEvent { case ready case closed case errorCaught } private var isStopped: Bool = false private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1) private var channel: Channel? public let messageStream: AsyncStream<(SocketAddress, SDLHoleMessage)> private let messageContinuation: AsyncStream<(SocketAddress, SDLHoleMessage)>.Continuation // 事件相关逻辑 public let eventStream: AsyncStream private let eventContinuation: AsyncStream.Continuation // 启动函数 init() throws { let (stream, continuation) = AsyncStream.makeStream(of: (SocketAddress, SDLHoleMessage).self, bufferingPolicy: .bufferingNewest(2048)) self.messageStream = stream self.messageContinuation = continuation let eventPair = AsyncStream.makeStream(of: HoleEvent.self) self.eventStream = eventPair.stream self.eventContinuation = eventPair.continuation } func start() throws -> SocketAddress? { let bootstrap = DatagramBootstrap(group: group) .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) .channelInitializer { channel in channel.pipeline.addHandler(self) } // 绑定到IPv6通配地址,只处理IPv6流量 let channel = try bootstrap.bind(host: "::", port: 0).wait() self.channel = channel return channel.localAddress } // --MARK: ChannelInboundHandler delegate func channelRead(context: ChannelHandlerContext, data: NIOAny) { let envelope = unwrapInboundIn(data) var buffer = envelope.data let remoteAddress = envelope.remoteAddress if let rawBytes = buffer.getBytes(at: buffer.readerIndex, length: buffer.readableBytes) { SDLLogger.log("[SDLUDPHoleV6] get raw bytes: \(rawBytes.count), from: \(remoteAddress)", for: .debug) } do { if let message = try SDLHoleMessage.decode(buffer: &buffer) { self.messageContinuation.yield((remoteAddress, message)) } else { SDLLogger.log("[SDLUDPHoleV6] decode message, get null", for: .debug) } } catch let err { SDLLogger.log("[SDLUDPHoleV6] decode message, get error: \(err)", for: .debug) } } func channelInactive(context: ChannelHandlerContext) { SDLLogger.log("[SDLUDPHoleV6] channelInactive", for: .debug) self.eventContinuation.yield(.closed) } func errorCaught(context: ChannelHandlerContext, error: any Error) { SDLLogger.log("[SDLUDPHoleV6] channel error: \(error)", for: .debug) context.close(promise: nil) self.eventContinuation.yield(.errorCaught) } // MARK: 处理写入逻辑 func send(type: SDLPacketType, data: Data, remoteAddress: SocketAddress) { guard let channel = self.channel else { return } var buffer = channel.allocator.buffer(capacity: data.count + 1) buffer.writeBytes([type.rawValue]) buffer.writeBytes(data) let envelope = AddressedEnvelope(remoteAddress: remoteAddress, data: buffer) _ = channel.eventLoop.submit { channel.writeAndFlush(envelope, promise: nil) } } func stop() { guard !self.isStopped else { return } self.isStopped = true SDLLogger.log("[SDLUDPHoleV6] stop", for: .debug) self.messageContinuation.finish() self.eventContinuation.finish() let channel = self.channel self.channel = nil try? channel?.close().wait() try? self.group.syncShutdownGracefully() } deinit { SDLLogger.log("[SDLUDPHoleV6] deinit", for: .debug) } }