From 3f5beb8410ee88547c6ae26f35e420b14a7fb271 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Thu, 7 May 2026 10:34:43 +0800 Subject: [PATCH] fix --- Tun/Punchnet/Context/SDLContextActor.swift | 2 +- .../Context/SDLPacketReaderService.swift | 95 ++++++++++++++++++- .../{Context => DNS}/SDLDNSService.swift | 0 .../{Actors => Super}/SDLSuperClient.swift | 0 .../{Context => Super}/SDLSuperService.swift | 0 .../SDLUDPHoleService.swift | 0 6 files changed, 92 insertions(+), 5 deletions(-) rename Tun/Punchnet/{Context => DNS}/SDLDNSService.swift (100%) rename Tun/Punchnet/{Actors => Super}/SDLSuperClient.swift (100%) rename Tun/Punchnet/{Context => Super}/SDLSuperService.swift (100%) rename Tun/Punchnet/{Context => UDPHole}/SDLUDPHoleService.swift (100%) diff --git a/Tun/Punchnet/Context/SDLContextActor.swift b/Tun/Punchnet/Context/SDLContextActor.swift index 461d79f..a4b635e 100644 --- a/Tun/Punchnet/Context/SDLContextActor.swift +++ b/Tun/Punchnet/Context/SDLContextActor.swift @@ -140,7 +140,7 @@ actor SDLContextActor { await self?.handleUDPHoleEvent(event) } self.udpHoleService = udpHoleService - await udpHoleService.start() + await udpHoleService.start(includeV6: false) let superService = SDLSuperService(host: self.config.serverHost) { [weak self] message in await self?.handleSuperMessage(message: message) diff --git a/Tun/Punchnet/Context/SDLPacketReaderService.swift b/Tun/Punchnet/Context/SDLPacketReaderService.swift index 581cf22..50a4b9c 100644 --- a/Tun/Punchnet/Context/SDLPacketReaderService.swift +++ b/Tun/Punchnet/Context/SDLPacketReaderService.swift @@ -8,9 +8,68 @@ actor SDLPacketReaderService { typealias EventHandler = @Sendable (Event) async -> Void + private final class CancellationToken: @unchecked Sendable { + private let lock = NSLock() + private var cancelled: Bool = false + + var isCancelled: Bool { + lock.lock() + defer { + lock.unlock() + } + return cancelled + } + + func cancel() { + lock.lock() + cancelled = true + lock.unlock() + } + } + + private final class PacketReadContinuation: @unchecked Sendable { + typealias Result = (packets: [Data], protocols: [NSNumber])? + + private let lock = NSLock() + private var continuation: CheckedContinuation? + private var finished: Bool = false + + func set(_ continuation: CheckedContinuation) { + lock.lock() + if finished { + lock.unlock() + continuation.resume(returning: nil) + return + } + + self.continuation = continuation + lock.unlock() + } + + func resume(returning result: Result) { + lock.lock() + guard !finished else { + lock.unlock() + return + } + + finished = true + let continuation = self.continuation + self.continuation = nil + lock.unlock() + + continuation?.resume(returning: result) + } + + func cancel() { + resume(returning: nil) + } + } + private let provider: NEPacketTunnelProvider private let onEvent: EventHandler private var readTask: Task? + private var readToken: CancellationToken? init(provider: NEPacketTunnelProvider, onEvent: @escaping EventHandler) { self.provider = provider @@ -24,14 +83,24 @@ actor SDLPacketReaderService { let provider = self.provider let onEvent = self.onEvent + let readToken = CancellationToken() + self.readToken = readToken + self.readTask = Task(priority: .high) { - while !Task.isCancelled { - let (packets, numbers) = await provider.packetFlow.readPackets() - if Task.isCancelled { + while !Task.isCancelled && !readToken.isCancelled { + guard let batch = await Self.readPackets(from: provider) else { break } - for (data, number) in zip(packets, numbers) where number == 2 { + if Task.isCancelled || readToken.isCancelled { + break + } + + for (data, number) in zip(batch.packets, batch.protocols) where number.int32Value == 2 { + if Task.isCancelled || readToken.isCancelled { + break + } + if let packet = IPPacket(data) { await onEvent(.packet(packet)) } @@ -44,6 +113,24 @@ actor SDLPacketReaderService { func stop() { let readTask = self.readTask self.readTask = nil + let readToken = self.readToken + self.readToken = nil + readToken?.cancel() readTask?.cancel() } + + private static func readPackets(from provider: NEPacketTunnelProvider) async -> PacketReadContinuation.Result { + let readContinuation = PacketReadContinuation() + + return await withTaskCancellationHandler { + await withCheckedContinuation { continuation in + readContinuation.set(continuation) + provider.packetFlow.readPackets { packets, protocols in + readContinuation.resume(returning: (packets: packets, protocols: protocols)) + } + } + } onCancel: { + readContinuation.cancel() + } + } } diff --git a/Tun/Punchnet/Context/SDLDNSService.swift b/Tun/Punchnet/DNS/SDLDNSService.swift similarity index 100% rename from Tun/Punchnet/Context/SDLDNSService.swift rename to Tun/Punchnet/DNS/SDLDNSService.swift diff --git a/Tun/Punchnet/Actors/SDLSuperClient.swift b/Tun/Punchnet/Super/SDLSuperClient.swift similarity index 100% rename from Tun/Punchnet/Actors/SDLSuperClient.swift rename to Tun/Punchnet/Super/SDLSuperClient.swift diff --git a/Tun/Punchnet/Context/SDLSuperService.swift b/Tun/Punchnet/Super/SDLSuperService.swift similarity index 100% rename from Tun/Punchnet/Context/SDLSuperService.swift rename to Tun/Punchnet/Super/SDLSuperService.swift diff --git a/Tun/Punchnet/Context/SDLUDPHoleService.swift b/Tun/Punchnet/UDPHole/SDLUDPHoleService.swift similarity index 100% rename from Tun/Punchnet/Context/SDLUDPHoleService.swift rename to Tun/Punchnet/UDPHole/SDLUDPHoleService.swift