This commit is contained in:
anlicheng 2026-05-07 10:34:43 +08:00
parent 66e2877044
commit 3f5beb8410
6 changed files with 92 additions and 5 deletions

View File

@ -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)

View File

@ -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<Result, Never>?
private var finished: Bool = false
func set(_ continuation: CheckedContinuation<Result, Never>) {
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<Void, Never>?
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
}
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
}
for (data, number) in zip(packets, numbers) where number == 2 {
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()
}
}
}