From 0a7c8eca85a0cb6b321b271bc51c6d941441af75 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Wed, 6 May 2026 15:13:36 +0800 Subject: [PATCH] fix udpHole --- Tun/Punchnet/Actors/SDLContextActor.swift | 5 +- Tun/Punchnet/Actors/SDLQuicClient.swift | 6 ++ Tun/Punchnet/DNS/DNSCloudClient.swift | 6 ++ Tun/Punchnet/DNS/DNSLocalClient.swift | 6 ++ Tun/Punchnet/UDPHole/SDLUDPCounter.swift | 74 +++++++++++++++++++++++ Tun/Punchnet/UDPHole/SDLUDPHole.swift | 33 ++++++++-- 6 files changed, 125 insertions(+), 5 deletions(-) create mode 100644 Tun/Punchnet/UDPHole/SDLUDPCounter.swift diff --git a/Tun/Punchnet/Actors/SDLContextActor.swift b/Tun/Punchnet/Actors/SDLContextActor.swift index 6b5b613..0a81e71 100644 --- a/Tun/Punchnet/Actors/SDLContextActor.swift +++ b/Tun/Punchnet/Actors/SDLContextActor.swift @@ -166,6 +166,7 @@ actor SDLContextActor { defer { self.quicClient = nil + SDLLogger.log("[SDLContext] startSuperClient defer") } // 这里必须等待quic的协商完成 @@ -197,13 +198,15 @@ actor SDLContextActor { try await group.next() } } onCancel: { - SDLLogger.log("[SDLQUICClient] quicClient taskGroup cancel", for: .debug) + SDLLogger.log("[SDLQUICClient] startSuperClient taskGroup cancel", for: .debug) Task { + SDLLogger.log("[SDLContext] startSuperClient onCancel") await quicClient.stop() } } } catch let err { await quicClient.stop() + SDLLogger.log("[SDLContext] startSuperClient catch err: \(err)") throw err } } diff --git a/Tun/Punchnet/Actors/SDLQuicClient.swift b/Tun/Punchnet/Actors/SDLQuicClient.swift index d6cf263..d860bde 100644 --- a/Tun/Punchnet/Actors/SDLQuicClient.swift +++ b/Tun/Punchnet/Actors/SDLQuicClient.swift @@ -192,6 +192,12 @@ actor SDLQUICClient { self.readTask?.cancel() self.connection?.cancel() self.finishMessageContinuationIfNeed(throwing: nil) + + SDLLogger.log("[SDLQUICClient] stopped") + } + + deinit { + SDLLogger.log("[SDLQUICClient] deinit") } } diff --git a/Tun/Punchnet/DNS/DNSCloudClient.swift b/Tun/Punchnet/DNS/DNSCloudClient.swift index aceda18..83d78ad 100644 --- a/Tun/Punchnet/DNS/DNSCloudClient.swift +++ b/Tun/Punchnet/DNS/DNSCloudClient.swift @@ -88,6 +88,8 @@ final class DNSCloudClient { self.connection = nil self.finishPacketContinuationIfNeed(throwing: nil) + + SDLLogger.log("[SDLCloudClient] stopped") } private func handleConnectionStateUpdate(_ state: NWConnection.State, for connection: NWConnection) { @@ -156,4 +158,8 @@ final class DNSCloudClient { } } + deinit { + SDLLogger.log("[DNSCloudClient] deinit", for: .debug) + } + } diff --git a/Tun/Punchnet/DNS/DNSLocalClient.swift b/Tun/Punchnet/DNS/DNSLocalClient.swift index d603153..ec5e5f1 100644 --- a/Tun/Punchnet/DNS/DNSLocalClient.swift +++ b/Tun/Punchnet/DNS/DNSLocalClient.swift @@ -132,6 +132,8 @@ actor DNSLocalClient { connection?.cancel() cleanupTask?.cancel() self.finishPacketContinuationIfNeed(throwing: nil) + + SDLLogger.log("[SDLLocalClient] stopped") } private func handleConnectionStateUpdate(_ state: NWConnection.State, for conn: NWConnection) { @@ -292,6 +294,10 @@ actor DNSLocalClient { receiveNext() } } + + deinit { + SDLLogger.log("[DNSLocalClient] deinit", for: .debug) + } } extension DNSLocalClient { diff --git a/Tun/Punchnet/UDPHole/SDLUDPCounter.swift b/Tun/Punchnet/UDPHole/SDLUDPCounter.swift new file mode 100644 index 0000000..09c76d0 --- /dev/null +++ b/Tun/Punchnet/UDPHole/SDLUDPCounter.swift @@ -0,0 +1,74 @@ +// +// SDLUDPCounter.swift +// punchnet +// +// Created by 安礼成 on 2026/5/6. +// + +import Foundation + +actor SDLUDPCounter { + + enum Direction { + case inbound + case outbound + } + + class Metrics { + var packetsNum: Int + var bytesNum: Int + + init() { + self.packetsNum = 0 + self.bytesNum = 0 + } + } + + private var inboundCounters: [String: Metrics] = [:] + private var outboundCounters: [String: Metrics] = [:] + + private var printTask: Task? + + func start() { + self.printTask = Task { + while true { + do { + try Task.checkCancellation() + try await Task.sleep(for: .seconds(1)) + for (from, metric) in inboundCounters { + SDLLogger.log("[SDLUDPCounter] inbound from: \(from), packet: \(metric.packetsNum), bytes: \(metric.bytesNum)") + } + self.inboundCounters.removeAll() + + for (from, metric) in outboundCounters { + SDLLogger.log("[SDLUDPCounter] outbound from: \(from), packet: \(metric.packetsNum), bytes: \(metric.bytesNum)") + } + self.outboundCounters.removeAll() + } catch { + break + } + } + } + } + + func increment(direction: Direction, from: String, bytes: Int) { + switch direction { + case .inbound: + let metric = inboundCounters[from, default: .init()] + metric.packetsNum += 1 + metric.bytesNum += bytes + inboundCounters[from] = metric + case .outbound: + let metric = outboundCounters[from, default: .init()] + metric.packetsNum += 1 + metric.bytesNum += bytes + outboundCounters[from] = metric + } + } + + func stop() { + self.printTask?.cancel() + self.printTask = nil + } + +} diff --git a/Tun/Punchnet/UDPHole/SDLUDPHole.swift b/Tun/Punchnet/UDPHole/SDLUDPHole.swift index 584b15a..49f213e 100644 --- a/Tun/Punchnet/UDPHole/SDLUDPHole.swift +++ b/Tun/Punchnet/UDPHole/SDLUDPHole.swift @@ -58,6 +58,9 @@ actor SDLUDPHole { self.udpHoleHandler.stop() } + deinit { + SDLLogger.log("[SDLUDPHoleActor] deinit", for: .debug) + } } // 处理和sn-server服务器之间的通讯 @@ -73,11 +76,15 @@ private final class SDLUDPHoleHandler: ChannelInboundHandler { private let messageContinuation: AsyncThrowingStream<(SocketAddress, SDLHoleMessage), Error>.Continuation private var isMessageContinuationFinished: Bool = false + private var counterActor: SDLUDPCounter + // 启动函数 init() throws { let (stream, continuation) = AsyncThrowingStream.makeStream(of: (SocketAddress, SDLHoleMessage).self, bufferingPolicy: .bufferingNewest(2048)) self.messageStream = stream self.messageContinuation = continuation + + self.counterActor = SDLUDPCounter() } func start() throws -> SocketAddress { @@ -95,6 +102,10 @@ private final class SDLUDPHoleHandler: ChannelInboundHandler { self.channel = channel + Task { + await self.counterActor.start() + } + return localAddress } @@ -105,7 +116,10 @@ private final class SDLUDPHoleHandler: ChannelInboundHandler { var buffer = envelope.data let remoteAddress = envelope.remoteAddress - SDLLogger.log("[SDLUDPHole] get raw bytes: \(buffer.readableBytes), from: \(remoteAddress)", for: .debug) + let bytesCount = buffer.readableBytes + Task { + await self.counterActor.increment(direction: .inbound, from: remoteAddress.description, bytes: bytesCount) + } do { if let message = try SDLHoleMessage.decode(buffer: &buffer) { @@ -119,12 +133,10 @@ private final class SDLUDPHoleHandler: ChannelInboundHandler { } func channelInactive(context: ChannelHandlerContext) { - SDLLogger.log("[SDLUDPHole] channelInactive", for: .debug) self.finishMessageContinuationIfNeed(throwing: .closed) } func errorCaught(context: ChannelHandlerContext, error: any Error) { - SDLLogger.log("[SDLUDPHole] channel error: \(error)", for: .debug) context.close(promise: nil) self.finishMessageContinuationIfNeed(throwing: .errorCaught) } @@ -135,6 +147,10 @@ private final class SDLUDPHoleHandler: ChannelInboundHandler { return } + Task { + await self.counterActor.increment(direction: .outbound, from: remoteAddress.description, bytes: data.count) + } + var buffer = channel.allocator.buffer(capacity: data.count + 1) buffer.writeBytes([type.rawValue]) buffer.writeBytes(data) @@ -152,11 +168,16 @@ private final class SDLUDPHoleHandler: ChannelInboundHandler { } func stop() { - SDLLogger.log("[SDLUDPHole] stop", for: .debug) self.finishMessageContinuationIfNeed(throwing: nil) try? self.channel?.close().wait() self.channel = nil try? self.group.syncShutdownGracefully() + + Task { + await self.counterActor.stop() + } + + SDLLogger.log("[SDLUDPHole] stopped", for: .debug) } private func finishMessageContinuationIfNeed(throwing error: SDLUDPHoleError?) { @@ -173,4 +194,8 @@ private final class SDLUDPHoleHandler: ChannelInboundHandler { self.messageContinuation.finish(throwing: error) } + deinit { + SDLLogger.log("[SDLUDPHole] deinit", for: .debug) + } + }