From 20a339f6ff3c0dde7a1da7852d65e8af2db6a9e2 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Fri, 10 Apr 2026 16:00:28 +0800 Subject: [PATCH] fix dns --- Tun/Punchnet/DNS/DNSLocalClient.swift | 45 +++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/Tun/Punchnet/DNS/DNSLocalClient.swift b/Tun/Punchnet/DNS/DNSLocalClient.swift index 76b0d90..9c6613c 100644 --- a/Tun/Punchnet/DNS/DNSLocalClient.swift +++ b/Tun/Punchnet/DNS/DNSLocalClient.swift @@ -12,14 +12,18 @@ final class DNSLocalClient { private var connections: [NWConnection] = [] - // 准备多个公共 DNS - private let dnsServers = ["114.114.114.114", "223.5.5.5", "8.8.8.8"] - + // 阿里云 + 腾讯云 + private let dnsServers = ["223.5.5.5", "119.29.29.29"] + public let packetFlow: AsyncStream private let packetContinuation: AsyncStream.Continuation private let locker = NSLock() private var trackers: [UInt16: [DNSTracker]] = [:] + + // 定期的任务清理 + private var cleanupTask: Task? + private let timeoutInterval: TimeInterval = 10.0 // 超过10秒认为丢包 init() { let (stream, continuation) = AsyncStream.makeStream(of: Data.self, bufferingPolicy: .unbounded) @@ -52,11 +56,21 @@ final class DNSLocalClient { connections.append(conn) } + + // 启动清理循环 + self.cleanupTask = Task { [weak self] in + while !Task.isCancelled { + // 每隔 cleanupTick 秒运行一次 + try? await Task.sleep(nanoseconds: 5 * 1_000_000_000) + self?.performCleanup() + } + } } /// 并发查询:对所有服务器广播 func query(tracker: DNSTracker, dnsPayload: Data) { locker.lock() + SDLLogger.shared.log("[DNSLocalClient] query transId: \(tracker.transactionID)") self.trackers[tracker.transactionID, default: []].append(tracker) locker.unlock() @@ -71,6 +85,7 @@ final class DNSLocalClient { // !!!核心:由于 AsyncStream 是流式的 // 谁先 yield,上层就先收到谁。 // 只要上层收到了第一个有效响应并回填给系统, + SDLLogger.shared.log("[DNSLocalClient] get response data: \(data.count)") self?.handleResponse(data: data) } @@ -91,6 +106,8 @@ final class DNSLocalClient { let items = self.trackers.removeValue(forKey: tranId) locker.unlock() + SDLLogger.shared.log("[DNSLocalClient] transId: \(tranId) get response items: \(items?.count)") + items?.forEach { tracker in let packet = Self.createDNSResponse( payload: data, @@ -103,11 +120,33 @@ final class DNSLocalClient { } } + private func performCleanup() { + locker.lock() + defer { + locker.unlock() + } + + // 遍历所有 ID,过滤掉过期的 tracker + let now = Date() + for (id, list) in trackers { + let validItems = list.filter { now.timeIntervalSince($0.createdAt) < timeoutInterval } + + if validItems.isEmpty { + trackers.removeValue(forKey: id) + } else { + trackers[id] = validItems + } + } + } + func stop() { connections.forEach { conn in conn.cancel() } self.connections.removeAll() + + self.cleanupTask?.cancel() + self.cleanupTask = nil } }