From e6c79d751991e4021d07ecd78a5b46c53d6edccd Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Wed, 20 May 2026 16:11:17 +0800 Subject: [PATCH] fix outbound --- .../Outbound/PacketOutboundActor.swift | 73 +++++++++++--- .../Outbound/SDLPacketReaderService.swift | 98 ------------------- .../SDLTunPacketRouter.swift | 0 3 files changed, 60 insertions(+), 111 deletions(-) delete mode 100644 Tun/Punchnet/Outbound/SDLPacketReaderService.swift rename Tun/Punchnet/{Context => Outbound}/SDLTunPacketRouter.swift (100%) diff --git a/Tun/Punchnet/Outbound/PacketOutboundActor.swift b/Tun/Punchnet/Outbound/PacketOutboundActor.swift index 7d1f558..c02d0b0 100644 --- a/Tun/Punchnet/Outbound/PacketOutboundActor.swift +++ b/Tun/Punchnet/Outbound/PacketOutboundActor.swift @@ -10,6 +10,8 @@ import NetworkExtension import NIOCore actor PacketOutboundActor { + private typealias PacketReadResult = (packets: [Data], protocols: [NSNumber])? + private let provider: NEPacketTunnelProvider private let sessionManager: SessionManager private let arpServer: ArpServer @@ -18,7 +20,8 @@ actor PacketOutboundActor { private let superServiceProxy: SDLSuperServiceProxy private let udpHoleServiceProxy: SDLUDPHoleServiceProxy private let flowTracer: SDLFlowTracer - private var packetReaderService: SDLPacketReaderService? + private var packetReaderTask: Task? + private var packetReaderGeneration: UInt64 = 0 private var networkAddress: SDLConfiguration.NetworkAddress private var identityId: UInt32 @@ -65,19 +68,47 @@ actor PacketOutboundActor { } func startPacketReader() async { - if self.packetReaderService == nil { - self.packetReaderService = SDLPacketReaderService(provider: self.provider) { [weak self] event in - await self?.handlePacketReaderEvent(event) - } + guard self.packetReaderTask == nil else { + return } - await self.packetReaderService?.start() + self.packetReaderGeneration &+= 1 + + let provider = self.provider + let generation = self.packetReaderGeneration + + self.packetReaderTask = Task(priority: .high) { [weak self] in + while !Task.isCancelled { + guard let batch = await Self.readPackets(from: provider) else { + break + } + + if Task.isCancelled { + break + } + + for (data, number) in zip(batch.packets, batch.protocols) where number.int32Value == 2 { + if Task.isCancelled { + break + } + + if let packet = IPPacket(data) { + await self?.handleTunPacket(packet) + } + } + } + + await self?.finishPacketReader(generation: generation) + SDLLogger.log("[PacketOutboundActor] packet reader task finished") + } } func stop() async { - let packetReaderService = self.packetReaderService - self.packetReaderService = nil - await packetReaderService?.stop() + self.packetReaderGeneration &+= 1 + + let packetReaderTask = self.packetReaderTask + self.packetReaderTask = nil + packetReaderTask?.cancel() } func handleTunPacket(_ packet: IPPacket) async { @@ -91,10 +122,26 @@ actor PacketOutboundActor { await self.handleTunRouteDecision(decision) } - private func handlePacketReaderEvent(_ event: SDLPacketReaderService.Event) async { - switch event { - case .packet(let packet): - await self.handleTunPacket(packet) + private func finishPacketReader(generation: UInt64) { + guard generation == self.packetReaderGeneration else { + return + } + + self.packetReaderTask = nil + } + + private static func readPackets(from provider: NEPacketTunnelProvider) async -> PacketReadResult { + let readContinuation = OnceContinuation() + + 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.resume(returning: nil) } } diff --git a/Tun/Punchnet/Outbound/SDLPacketReaderService.swift b/Tun/Punchnet/Outbound/SDLPacketReaderService.swift deleted file mode 100644 index e09c215..0000000 --- a/Tun/Punchnet/Outbound/SDLPacketReaderService.swift +++ /dev/null @@ -1,98 +0,0 @@ -import Foundation -import NetworkExtension - -actor SDLPacketReaderService { - enum Event { - case packet(IPPacket) - } - - typealias EventHandler = @Sendable (Event) async -> Void - private typealias PacketReadResult = (packets: [Data], protocols: [NSNumber])? - - 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 let provider: NEPacketTunnelProvider - private let onEvent: EventHandler - private var readTask: Task? - private var readToken: CancellationToken? - - init(provider: NEPacketTunnelProvider, onEvent: @escaping EventHandler) { - self.provider = provider - self.onEvent = onEvent - } - - func start() { - guard self.readTask == nil else { - return - } - - let provider = self.provider - let onEvent = self.onEvent - let readToken = CancellationToken() - self.readToken = readToken - - self.readTask = Task(priority: .high) { - while !Task.isCancelled && !readToken.isCancelled { - guard let batch = await Self.readPackets(from: provider) else { - break - } - - 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)) - } - } - } - SDLLogger.log("[SDLPacketReaderService] readTask finished") - } - } - - 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 -> PacketReadResult { - let readContinuation = OnceContinuation() - - 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.resume(returning: nil) - } - } -} diff --git a/Tun/Punchnet/Context/SDLTunPacketRouter.swift b/Tun/Punchnet/Outbound/SDLTunPacketRouter.swift similarity index 100% rename from Tun/Punchnet/Context/SDLTunPacketRouter.swift rename to Tun/Punchnet/Outbound/SDLTunPacketRouter.swift