From 7ed993a7753462cc8bd6f3c594cf1e2117d45618 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Mon, 13 Apr 2026 17:36:52 +0800 Subject: [PATCH] =?UTF-8?q?fix=E8=B5=84=E6=BA=90=E7=9A=84=E6=B8=85?= =?UTF-8?q?=E7=90=86=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tun/Punchnet/Actors/SDLContextActor.swift | 24 ++++++++++----- Tun/Punchnet/SDLNetworkMonitor.swift | 12 +++++++- Tun/Punchnet/SDLNoticeClient.swift | 14 ++++++++- Tun/Punchnet/SDLUDPHole.swift | 37 +++++++++-------------- 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/Tun/Punchnet/Actors/SDLContextActor.swift b/Tun/Punchnet/Actors/SDLContextActor.swift index fff71b8..c25d1e5 100644 --- a/Tun/Punchnet/Actors/SDLContextActor.swift +++ b/Tun/Punchnet/Actors/SDLContextActor.swift @@ -305,14 +305,8 @@ actor SDLContextActor { // 启动udp服务器 let udpHole = try SDLUDPHole() - try udpHole.start() - SDLLogger.log("[SDLContext] udpHole started") - - // 获取当前udp启动的地址 - let localAddress = udpHole.getLocalAddress() - - // 阻塞等待udpHole是准备好的状态 - await udpHole.channelIsActived() + let localAddress = try udpHole.start() + SDLLogger.log("[SDLContext] udpHole started, on address: \(localAddress.debugDescription)") // 处理心跳逻辑 let pingTask = Task.detached { @@ -370,25 +364,34 @@ actor SDLContextActor { public func stop() async { self.resumeReadyWaiters(.failure(CancellationError())) self.readyState = .stopped + self.state = .unregistered await self.supervisor.stop() self.udpHoleWorkers?.forEach { $0.cancel() } self.udpHoleWorkers = nil + self.udpHole?.stop() + self.udpHole = nil self.quicWorker?.cancel() self.quicWorker = nil + self.quicClient?.stop() + self.quicClient = nil self.dnsClient?.stop() self.dnsWorker?.cancel() self.dnsWorker = nil + self.dnsClient = nil self.dnsLocalClient?.stop() self.dnsLocalWorker?.cancel() self.dnsLocalWorker = nil + self.dnsLocalClient = nil + self.monitor?.stop() self.monitorWorker?.cancel() self.monitorWorker = nil + self.monitor = nil self.readTask?.cancel() self.readTask = nil @@ -398,6 +401,11 @@ actor SDLContextActor { self.updatePolicyTask?.cancel() self.updatePolicyTask = nil + + self.noticeClient?.stop() + self.noticeClient = nil + self.sessionToken = nil + self.dataCipher = nil } private func setNatType(natType: SDLNATProberActor.NatType) { diff --git a/Tun/Punchnet/SDLNetworkMonitor.swift b/Tun/Punchnet/SDLNetworkMonitor.swift index 5a76bee..6b4e11e 100644 --- a/Tun/Punchnet/SDLNetworkMonitor.swift +++ b/Tun/Punchnet/SDLNetworkMonitor.swift @@ -15,6 +15,7 @@ class SDLNetworkMonitor: @unchecked Sendable { private var interfaceType: NWInterface.InterfaceType? private let publisher = PassthroughSubject() private var cancel: AnyCancellable? + private var isStopped = false public let eventStream: AsyncStream private let eventContinuation: AsyncStream.Continuation @@ -55,10 +56,19 @@ class SDLNetworkMonitor: @unchecked Sendable { } } - deinit { + func stop() { + guard !self.isStopped else { + return + } + + self.isStopped = true self.monitor.cancel() self.cancel?.cancel() self.eventContinuation.finish() } + deinit { + self.stop() + } + } diff --git a/Tun/Punchnet/SDLNoticeClient.swift b/Tun/Punchnet/SDLNoticeClient.swift index ded2171..c19913b 100644 --- a/Tun/Punchnet/SDLNoticeClient.swift +++ b/Tun/Punchnet/SDLNoticeClient.swift @@ -26,6 +26,7 @@ final class SDLNoticeClient { private var channel: Channel private let noticePort: Int + private var isStopped = false // 启动函数 init(noticePort: Int) throws { @@ -71,9 +72,20 @@ final class SDLNoticeClient { try await self.channel.closeFuture.get() } - deinit { + func stop() { + guard !self.isStopped else { + return + } + + self.isStopped = true self.writeContinuation.finish() self.task?.cancel() + self.task = nil + self.channel.close(promise: nil) + } + + deinit { + self.stop() try? self.group.syncShutdownGracefully() } diff --git a/Tun/Punchnet/SDLUDPHole.swift b/Tun/Punchnet/SDLUDPHole.swift index 664fee3..03b3983 100644 --- a/Tun/Punchnet/SDLUDPHole.swift +++ b/Tun/Punchnet/SDLUDPHole.swift @@ -21,15 +21,15 @@ final class SDLUDPHole: ChannelInboundHandler { private let messageContinuation: AsyncStream<(SocketAddress, SDLHoleMessage)>.Continuation // 解决channelready的问题 - private var cont: CheckedContinuation? private var isReady: Bool = false + private var isStopped: Bool = false // 启动函数 init() throws { (self.messageStream, self.messageContinuation) = AsyncStream.makeStream(of: (SocketAddress, SDLHoleMessage).self, bufferingPolicy: .unbounded) } - func start() throws { + func start() throws -> SocketAddress? { let bootstrap = DatagramBootstrap(group: group) .channelOption(ChannelOptions.socketOption(.so_reuseaddr), value: 1) .channelInitializer { channel in @@ -38,31 +38,28 @@ final class SDLUDPHole: ChannelInboundHandler { let channel = try bootstrap.bind(host: "0.0.0.0", port: 0).wait() self.channel = channel - } - - func channelIsActived() async { - await withCheckedContinuation { c in - if isReady { - c.resume() - } else { - self.cont = c - } - } + + return channel.localAddress } func waitClose() async throws { try await self.channel?.closeFuture.get() } + func stop() { + guard !self.isStopped else { + return + } + + self.isStopped = true + self.messageContinuation.finish() + self.channel?.close(promise: nil) + } + // --MARK: ChannelInboundHandler delegate func channelActive(context: ChannelHandlerContext) { - guard !isReady else { - return - } self.isReady = true - self.cont?.resume() - self.cont = nil } func channelRead(context: ChannelHandlerContext, data: NIOAny) { @@ -95,10 +92,6 @@ final class SDLUDPHole: ChannelInboundHandler { 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 { @@ -162,8 +155,8 @@ final class SDLUDPHole: ChannelInboundHandler { } deinit { + self.stop() try? self.group.syncShutdownGracefully() - self.channel?.close(promise: nil) } }