// // SDLUDPHoleActor 2.swift // punchnet // // Created by 安礼成 on 2026/1/28. // // // SDLanServer.swift // Tun // // Created by 安礼成 on 2024/1/31. // import Foundation import NIOCore import NIOPosix import SwiftProtobuf // 处理和sn-server服务器之间的通讯 final class SDLUDPHole: ChannelInboundHandler { typealias InboundIn = AddressedEnvelope private let group = MultiThreadedEventLoopGroup(numberOfThreads: 1) private var channel: Channel? public let signalStream: AsyncStream<(SocketAddress, SDLHoleSignal)> private let signalContinuation: AsyncStream<(SocketAddress, SDLHoleSignal)>.Continuation public let dataStream: AsyncStream private let dataContinuation: AsyncStream.Continuation public let eventStream: AsyncStream private let eventContinuation: AsyncStream.Continuation private let logger: SDLLogger enum HoleEvent { case ready case closed } // 启动函数 init(logger: SDLLogger) throws { self.logger = logger (self.signalStream, self.signalContinuation) = AsyncStream.makeStream(of: (SocketAddress, SDLHoleSignal).self, bufferingPolicy: .unbounded) (self.dataStream, self.dataContinuation) = AsyncStream.makeStream(of: SDLData.self, bufferingPolicy: .unbounded) (self.eventStream, self.eventContinuation) = AsyncStream.makeStream(of: HoleEvent.self, bufferingPolicy: .unbounded) } func start() throws { let bootstrap = DatagramBootstrap(group: group) .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) .channelInitializer { channel in channel.pipeline.addHandler(self) } self.channel = try bootstrap.bind(host: "0.0.0.0", port: 0).wait() self.logger.log("[UDPHole] started", level: .debug) } // --MARK: ChannelInboundHandler delegate func channelActive(context: ChannelHandlerContext) { self.eventContinuation.yield(.ready) } func channelRead(context: ChannelHandlerContext, data: NIOAny) { let envelope = unwrapInboundIn(data) var buffer = envelope.data let remoteAddress = envelope.remoteAddress do { if let message = try decode(buffer: &buffer) { switch message { case .data(let data): self.dataContinuation.yield(data) case .signal(let signal): self.signalContinuation.yield((remoteAddress, signal)) } } else { self.logger.log("[SDLUDPHole] decode message, get null", level: .warning) } } catch let err { self.logger.log("[SDLUDPHole] decode message, get error: \(err)", level: .warning) } } func channelInactive(context: ChannelHandlerContext) { self.signalContinuation.finish() self.dataContinuation.finish() self.eventContinuation.yield(.closed) self.eventContinuation.finish() context.close(promise: nil) } func errorCaught(context: ChannelHandlerContext, error: any Error) { context.close(promise: nil) } func getLocalAddress() -> SocketAddress? { return self.channel?.localAddress } // 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.execute { channel.writeAndFlush(envelope, promise: nil) } } // --MARK: 编解码器 private func decode(buffer: inout ByteBuffer) throws -> SDLHoleMessage? { guard let type = buffer.readInteger(as: UInt8.self), let packetType = SDLPacketType(rawValue: type), let bytes = buffer.readBytes(length: buffer.readableBytes) else { return nil } switch packetType { case .data: let dataPacket = try SDLData(serializedBytes: bytes) return .data(dataPacket) case .register: let registerPacket = try SDLRegister(serializedBytes: bytes) return .signal(.register(registerPacket)) case .registerAck: let registerAck = try SDLRegisterAck(serializedBytes: bytes) return .signal(.registerAck(registerAck)) case .stunProbeReply: let stunProbeReply = try SDLStunProbeReply(serializedBytes: bytes) return .signal(.stunProbeReply(stunProbeReply)) case .registerSuperAck: guard let bytes = buffer.readBytes(length: buffer.readableBytes), let registerSuperAck = try? SDLRegisterSuperAck(serializedBytes: bytes) else { return nil } return .signal(.registerSuperAck(registerSuperAck)) case .registerSuperNak: guard let bytes = buffer.readBytes(length: buffer.readableBytes), let registerSuperNak = try? SDLRegisterSuperNak(serializedBytes: bytes) else { return nil } return .signal(.registerSuperNak(registerSuperNak)) case .peerInfo: guard let bytes = buffer.readBytes(length: buffer.readableBytes), let peerInfo = try? SDLPeerInfo(serializedBytes: bytes) else { return nil } return .signal(.peerInfo(peerInfo)) case .event: guard let eventVal = buffer.readInteger(as: UInt8.self), let event = SDLEventType(rawValue: eventVal), let bytes = buffer.readBytes(length: buffer.readableBytes) else { return nil } switch event { case .natChanged: guard let natChangedEvent = try? SDLNatChangedEvent(serializedBytes: bytes) else { return nil } return .signal(.event(.natChanged(natChangedEvent))) case .sendRegister: guard let sendRegisterEvent = try? SDLSendRegisterEvent(serializedBytes: bytes) else { return nil } return .signal(.event(.sendRegister(sendRegisterEvent))) case .networkShutdown: guard let networkShutdownEvent = try? SDLNetworkShutdownEvent(serializedBytes: bytes) else { return nil } return .signal(.event(.networkShutdown(networkShutdownEvent))) } default: return nil } } deinit { try? self.group.syncShutdownGracefully() self.eventContinuation.finish() self.channel?.close(promise: nil) } }