From 720bf3549a217833de47caded51a9375670a8f29 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Thu, 16 Apr 2026 15:53:37 +0800 Subject: [PATCH] fix SDLIPV6AssistClient --- Tun/Punchnet/SDLIPV6AssistClient.swift | 148 +++++++++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100644 Tun/Punchnet/SDLIPV6AssistClient.swift diff --git a/Tun/Punchnet/SDLIPV6AssistClient.swift b/Tun/Punchnet/SDLIPV6AssistClient.swift new file mode 100644 index 0000000..345feaa --- /dev/null +++ b/Tun/Punchnet/SDLIPV6AssistClient.swift @@ -0,0 +1,148 @@ +// +// SDLDNSClient 2.swift +// punchnet +// +// Created by 安礼成 on 2026/4/9. +// +import Foundation +import Network + +actor SDLIPV6AssistClient { + private enum State { + case idle + case running + case stopped + } + + private var state: State = .idle + private var connection: NWConnection? + private var receiveTask: Task? + private let assistServerAddress: NWEndpoint + + init(host: String, port: UInt16 ) { + self.assistServerAddress = .hostPort(host: NWEndpoint.Host(host), port: NWEndpoint.Port(integerLiteral: port)) + } + + func start() { + guard case .idle = self.state else { + return + } + + self.state = .running + + // 1. 配置参数:这是解决环路的关键 + let parameters = NWParameters.udp + + // 禁止此连接走 TUN 网卡(在 NE 中 TUN 通常被归类为 .other) + parameters.prohibitedInterfaceTypes = [.other] + // 2. 增强健壮性:启用多路径切换(替代 pathSelectionOptions 的意图) + parameters.multipathServiceType = .handover + + // 2. 创建连接 + let connection = NWConnection(to: self.assistServerAddress, using: parameters) + self.connection = connection + + connection.stateUpdateHandler = { [weak self] state in + Task { + await self?.handleConnectionStateUpdate(state, for: connection) + } + } + + // 启动连接队列 + connection.start(queue: .global()) + } + + /// 接收数据的递归循环 + private static func makeReceiveStream(for connection: NWConnection) -> AsyncStream { + return AsyncStream(bufferingPolicy: .bufferingNewest(256)) { continuation in + func receiveNext() { + connection.receiveMessage { content, _, _, error in + if let data = content, !data.isEmpty { + // 将收到的 DNS 响应写回 AsyncStream + continuation.yield(data) + } + + if error == nil && connection.state == .ready { + receiveNext() // 继续监听下一个包 + } else { + continuation.finish() + } + } + } + + receiveNext() + } + } + + /// 发送 DNS 查询包(由 TUN 拦截到的原始 IP 包数据) + func forward(ipPacketData: Data) { + guard case .running = self.state, let connection = self.connection, connection.state == .ready else { + return + } + + connection.send(content: ipPacketData, completion: .contentProcessed { error in + if let error = error { + SDLLogger.log("[SDLIPV6AssistClient] Send error: \(error)", for: .debug) + } + }) + } + + func stop() { + guard self.state != .stopped else { + return + } + + self.state = .stopped + self.receiveTask?.cancel() + self.receiveTask = nil + self.connection?.cancel() + self.connection = nil + } + + private func handleConnectionStateUpdate(_ state: NWConnection.State, for connection: NWConnection) { + guard case .running = self.state else { + return + } + + switch state { + case .ready: + SDLLogger.log("[SDLIPV6AssistClient] Connection ready", for: .debug) + self.startReceiveTask(for: connection) + case .failed(let error): + SDLLogger.log("[SDLIPV6AssistClient] Connection failed: \(error)", for: .debug) + self.stop() + case .cancelled: + self.stop() + default: + break + } + } + + private func startReceiveTask(for connection: NWConnection) { + guard self.receiveTask == nil else { + return + } + + let stream = Self.makeReceiveStream(for: connection) + self.receiveTask = Task { [weak self] in + for await data in stream { + guard let self else { + break + } + await self.handleReceivedPacket(data) + } + } + } + + private func handleReceivedPacket(_ data: Data) { + guard case .running = self.state else { + return + } + + NSLog("data: \(data)") + } + + deinit { + self.connection?.cancel() + } +}