修复主要流程
This commit is contained in:
parent
c19b916365
commit
875a4c3669
@ -55,6 +55,8 @@ actor SDLContextActor {
|
|||||||
|
|
||||||
// 本地ipv6地址信息探测
|
// 本地ipv6地址信息探测
|
||||||
private var ipv6AssistClient: SDLIPV6AssistClient?
|
private var ipv6AssistClient: SDLIPV6AssistClient?
|
||||||
|
private let ipv6AssistEvents: AsyncStream<SDLV6Info?>
|
||||||
|
private let ipv6AssistContinuation: AsyncStream<SDLV6Info?>.Continuation
|
||||||
|
|
||||||
private let sessionManager: SessionManager
|
private let sessionManager: SessionManager
|
||||||
nonisolated private let arpResolver: ArpResolver
|
nonisolated private let arpResolver: ArpResolver
|
||||||
@ -82,6 +84,7 @@ actor SDLContextActor {
|
|||||||
let superService = SDLSuperService(serverEndpoint: config.serverEndpoint)
|
let superService = SDLSuperService(serverEndpoint: config.serverEndpoint)
|
||||||
let udpHoleService = SDLUDPHoleService(proberActor: proberActor)
|
let udpHoleService = SDLUDPHoleService(proberActor: proberActor)
|
||||||
let tunNetworkManager = SDLTunNetworkManager(provider: provider)
|
let tunNetworkManager = SDLTunNetworkManager(provider: provider)
|
||||||
|
let ipv6AssistPair = AsyncStream.makeStream(of: Optional<SDLV6Info>.self, bufferingPolicy: .bufferingNewest(1))
|
||||||
let packetOutboundActor = PacketOutboundActor(
|
let packetOutboundActor = PacketOutboundActor(
|
||||||
provider: provider,
|
provider: provider,
|
||||||
config: config,
|
config: config,
|
||||||
@ -123,6 +126,8 @@ actor SDLContextActor {
|
|||||||
self.packetOutboundActor = packetOutboundActor
|
self.packetOutboundActor = packetOutboundActor
|
||||||
self.packetInboundActor = packetInboundActor
|
self.packetInboundActor = packetInboundActor
|
||||||
self.tunNetworkManager = tunNetworkManager
|
self.tunNetworkManager = tunNetworkManager
|
||||||
|
self.ipv6AssistEvents = ipv6AssistPair.stream
|
||||||
|
self.ipv6AssistContinuation = ipv6AssistPair.continuation
|
||||||
}
|
}
|
||||||
|
|
||||||
public func start() async throws {
|
public func start() async throws {
|
||||||
@ -231,6 +236,10 @@ actor SDLContextActor {
|
|||||||
try await arpResolver.runCleanup()
|
try await arpResolver.runCleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group.addTask {
|
||||||
|
try await self.runIPv6AssistSupervisor()
|
||||||
|
}
|
||||||
|
|
||||||
group.addTask(priority: .high) {
|
group.addTask(priority: .high) {
|
||||||
_ = try await readySignal.wait()
|
_ = try await readySignal.wait()
|
||||||
try await packetOutboundActor.runPacketReader()
|
try await packetOutboundActor.runPacketReader()
|
||||||
@ -297,6 +306,49 @@ actor SDLContextActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private func runIPv6AssistSupervisor() async throws {
|
||||||
|
do {
|
||||||
|
for await assistInfo in self.ipv6AssistEvents {
|
||||||
|
try Task.checkCancellation()
|
||||||
|
await self.stopCurrentIPv6AssistClient()
|
||||||
|
|
||||||
|
guard let assistInfo else {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
guard let client = SDLIPV6AssistClient(assistServerInfo: assistInfo) else {
|
||||||
|
SDLLogger.log("[SDLContext] invalid ipv6 assist config", for: .debug)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
self.ipv6AssistClient = client
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await client.run()
|
||||||
|
} catch is CancellationError {
|
||||||
|
throw CancellationError()
|
||||||
|
} catch {
|
||||||
|
SDLLogger.log("[SDLContext] ipv6 assist client ended: \(error.localizedDescription)", for: .debug)
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.ipv6AssistClient === client {
|
||||||
|
self.ipv6AssistClient = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch is CancellationError {
|
||||||
|
await self.stopCurrentIPv6AssistClient()
|
||||||
|
throw CancellationError()
|
||||||
|
}
|
||||||
|
|
||||||
|
await self.stopCurrentIPv6AssistClient()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stopCurrentIPv6AssistClient() async {
|
||||||
|
let client = self.ipv6AssistClient
|
||||||
|
self.ipv6AssistClient = nil
|
||||||
|
await client?.stop()
|
||||||
|
}
|
||||||
|
|
||||||
private func cleanupRoot() async {
|
private func cleanupRoot() async {
|
||||||
await self.puncherActor.stop()
|
await self.puncherActor.stop()
|
||||||
await self.arpResolver.stop()
|
await self.arpResolver.stop()
|
||||||
@ -319,8 +371,8 @@ actor SDLContextActor {
|
|||||||
await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: nil)
|
await self.packetOutboundActor.updateRuntime(config: self.config, dataCipher: nil)
|
||||||
await self.packetInboundActor.updateRuntime(config: self.config, dataCipher: nil)
|
await self.packetInboundActor.updateRuntime(config: self.config, dataCipher: nil)
|
||||||
|
|
||||||
await self.ipv6AssistClient?.stop()
|
self.ipv6AssistContinuation.yield(nil)
|
||||||
self.ipv6AssistClient = nil
|
await self.stopCurrentIPv6AssistClient()
|
||||||
}
|
}
|
||||||
|
|
||||||
deinit {
|
deinit {
|
||||||
@ -379,12 +431,12 @@ extension SDLContextActor {
|
|||||||
case .welcome(let welcome):
|
case .welcome(let welcome):
|
||||||
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
|
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
|
||||||
|
|
||||||
await self.ipv6AssistClient?.stop()
|
await self.stopCurrentIPv6AssistClient()
|
||||||
self.ipv6AssistClient = nil
|
|
||||||
// 尝试创建v6地址的辅助探测器
|
// 尝试创建v6地址的辅助探测器
|
||||||
if welcome.hasIpv6Assist {
|
if welcome.hasIpv6Assist {
|
||||||
self.ipv6AssistClient = SDLIPV6AssistClient(assistServerInfo: welcome.ipv6Assist)
|
self.ipv6AssistContinuation.yield(welcome.ipv6Assist)
|
||||||
await self.ipv6AssistClient?.start()
|
} else {
|
||||||
|
self.ipv6AssistContinuation.yield(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册
|
// 注册
|
||||||
|
|||||||
@ -84,13 +84,9 @@ actor DNSService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group.addTask {
|
group.addTask {
|
||||||
try await withTaskCancellationHandler {
|
for try await packet in dnsClient.packetFlow {
|
||||||
for try await packet in dnsClient.packetFlow {
|
try Task.checkCancellation()
|
||||||
try Task.checkCancellation()
|
await onEvent(.packet(packet))
|
||||||
await onEvent(.packet(packet))
|
|
||||||
}
|
|
||||||
} onCancel: {
|
|
||||||
dnsClient.stop()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -122,15 +118,9 @@ actor DNSService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
group.addTask {
|
group.addTask {
|
||||||
try await withTaskCancellationHandler {
|
for try await packet in dnsLocalClient.packetFlow {
|
||||||
for try await packet in dnsLocalClient.packetFlow {
|
try Task.checkCancellation()
|
||||||
try Task.checkCancellation()
|
await onEvent(.packet(packet))
|
||||||
await onEvent(.packet(packet))
|
|
||||||
}
|
|
||||||
} onCancel: {
|
|
||||||
Task {
|
|
||||||
await dnsLocalClient.stop()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,45 +0,0 @@
|
|||||||
//
|
|
||||||
// SDLThrottler.swift
|
|
||||||
// Tun
|
|
||||||
//
|
|
||||||
// Created by 安礼成 on 2024/6/3.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import Combine
|
|
||||||
|
|
||||||
// 限流器
|
|
||||||
actor SDLThrottler {
|
|
||||||
private var limit: Int
|
|
||||||
private var token: Int
|
|
||||||
private var cancel: AnyCancellable?
|
|
||||||
|
|
||||||
init(limit: Int) {
|
|
||||||
self.limit = limit
|
|
||||||
self.token = limit
|
|
||||||
}
|
|
||||||
|
|
||||||
func start() {
|
|
||||||
self.cancel?.cancel()
|
|
||||||
self.cancel = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
|
|
||||||
.sink { _ in
|
|
||||||
Task {
|
|
||||||
self.token = self.limit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setRateLimit(limit: Int) {
|
|
||||||
self.limit = limit
|
|
||||||
}
|
|
||||||
|
|
||||||
func getToken(num: Int) -> Bool {
|
|
||||||
if token > 0 {
|
|
||||||
self.token = self.token - num
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
//
|
|
||||||
// SDLPathDebounceActor.swift
|
|
||||||
// punchnet
|
|
||||||
//
|
|
||||||
// Created by 安礼成 on 2026/4/29.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import Network
|
|
||||||
|
|
||||||
actor SDLPathDebounceActor {
|
|
||||||
private var lastSnapshot: SDLPathSnapshot?
|
|
||||||
private var debounceTask: Task<Void, Never>?
|
|
||||||
|
|
||||||
private let delay: Duration
|
|
||||||
|
|
||||||
public let statusStream: AsyncStream<NWPath.Status>
|
|
||||||
private let statusCont: AsyncStream<NWPath.Status>.Continuation
|
|
||||||
|
|
||||||
init(delay: Duration = .seconds(2)) {
|
|
||||||
self.delay = delay
|
|
||||||
let (stream, cont) = AsyncStream.makeStream(of: NWPath.Status.self)
|
|
||||||
self.statusStream = stream
|
|
||||||
self.statusCont = cont
|
|
||||||
}
|
|
||||||
|
|
||||||
func submit(_ snapshot: SDLPathSnapshot) {
|
|
||||||
guard snapshot != lastSnapshot else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.lastSnapshot = snapshot
|
|
||||||
|
|
||||||
self.debounceTask?.cancel()
|
|
||||||
self.debounceTask = Task { [delay] in
|
|
||||||
try? await Task.sleep(for: delay)
|
|
||||||
|
|
||||||
guard !Task.isCancelled else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await self.handleStableSnapshot(snapshot)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleStableSnapshot(_ snapshot: SDLPathSnapshot) async {
|
|
||||||
self.statusCont.yield(snapshot.status)
|
|
||||||
}
|
|
||||||
|
|
||||||
func stop() {
|
|
||||||
debounceTask?.cancel()
|
|
||||||
debounceTask = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
//
|
|
||||||
// SDLPathMonitor.swift
|
|
||||||
// punchnet
|
|
||||||
//
|
|
||||||
// Created by 安礼成 on 2026/4/29.
|
|
||||||
//
|
|
||||||
import Foundation
|
|
||||||
import Network
|
|
||||||
|
|
||||||
final class SDLPathMonitor {
|
|
||||||
private let monitor = NWPathMonitor()
|
|
||||||
private let queue = DispatchQueue(label: "com.sdlan.path-monitor")
|
|
||||||
private let debouncer = SDLPathDebounceActor(delay: .seconds(2))
|
|
||||||
|
|
||||||
private var isStarted: Bool = false
|
|
||||||
|
|
||||||
func start() {
|
|
||||||
guard !isStarted else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.isStarted = true
|
|
||||||
monitor.pathUpdateHandler = { path in
|
|
||||||
let snapshot = SDLPathSnapshot(path)
|
|
||||||
|
|
||||||
Task {
|
|
||||||
await self.debouncer.submit(snapshot)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
monitor.start(queue: queue)
|
|
||||||
}
|
|
||||||
|
|
||||||
func statusStream() -> AsyncStream<NWPath.Status> {
|
|
||||||
return self.debouncer.statusStream
|
|
||||||
}
|
|
||||||
|
|
||||||
func stop() {
|
|
||||||
Task {
|
|
||||||
await debouncer.stop()
|
|
||||||
}
|
|
||||||
monitor.cancel()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
//
|
|
||||||
// PathSnapshot.swift
|
|
||||||
// punchnet
|
|
||||||
//
|
|
||||||
// Created by 安礼成 on 2026/4/29.
|
|
||||||
//
|
|
||||||
import Foundation
|
|
||||||
import Network
|
|
||||||
|
|
||||||
struct SDLPathSnapshot: Equatable, Sendable {
|
|
||||||
let status: NWPath.Status
|
|
||||||
let isExpensive: Bool
|
|
||||||
let isConstrained: Bool
|
|
||||||
let supportsIPv4: Bool
|
|
||||||
let supportsIPv6: Bool
|
|
||||||
let supportsDNS: Bool
|
|
||||||
let usesWiFi: Bool
|
|
||||||
let usesWired: Bool
|
|
||||||
let usesCellular: Bool
|
|
||||||
|
|
||||||
init(_ path: NWPath) {
|
|
||||||
self.status = path.status
|
|
||||||
self.isExpensive = path.isExpensive
|
|
||||||
self.isConstrained = path.isConstrained
|
|
||||||
self.supportsIPv4 = path.supportsIPv4
|
|
||||||
self.supportsIPv6 = path.supportsIPv6
|
|
||||||
self.supportsDNS = path.supportsDNS
|
|
||||||
self.usesWiFi = path.usesInterfaceType(.wifi)
|
|
||||||
self.usesWired = path.usesInterfaceType(.wiredEthernet)
|
|
||||||
self.usesCellular = path.usesInterfaceType(.cellular)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -26,7 +26,6 @@ actor SDLIPV6AssistClient {
|
|||||||
|
|
||||||
private var state: State = .idle
|
private var state: State = .idle
|
||||||
private var connection: NWConnection?
|
private var connection: NWConnection?
|
||||||
private var receiveTask: Task<Void, Never>?
|
|
||||||
private let assistServerAddress: NWEndpoint
|
private let assistServerAddress: NWEndpoint
|
||||||
|
|
||||||
private var packetId: UInt32 = 1
|
private var packetId: UInt32 = 1
|
||||||
@ -41,7 +40,7 @@ actor SDLIPV6AssistClient {
|
|||||||
self.assistServerAddress = .hostPort(host: .ipv6(address), port: NWEndpoint.Port(integerLiteral: UInt16(assistServerInfo.port)))
|
self.assistServerAddress = .hostPort(host: .ipv6(address), port: NWEndpoint.Port(integerLiteral: UInt16(assistServerInfo.port)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() {
|
func run() async throws {
|
||||||
guard case .idle = self.state else {
|
guard case .idle = self.state else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -73,6 +72,20 @@ actor SDLIPV6AssistClient {
|
|||||||
|
|
||||||
// 启动连接队列
|
// 启动连接队列
|
||||||
connection.start(queue: .global())
|
connection.start(queue: .global())
|
||||||
|
|
||||||
|
defer {
|
||||||
|
self.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
let stream = Self.makeReceiveStream(for: connection)
|
||||||
|
try await withTaskCancellationHandler {
|
||||||
|
for await data in stream {
|
||||||
|
try Task.checkCancellation()
|
||||||
|
self.handleReceivedPacket(data)
|
||||||
|
}
|
||||||
|
} onCancel: {
|
||||||
|
connection.cancel()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 接收数据的递归循环
|
/// 接收数据的递归循环
|
||||||
@ -147,8 +160,6 @@ actor SDLIPV6AssistClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
self.state = .stopped
|
self.state = .stopped
|
||||||
self.receiveTask?.cancel()
|
|
||||||
self.receiveTask = nil
|
|
||||||
self.connection?.cancel()
|
self.connection?.cancel()
|
||||||
self.connection = nil
|
self.connection = nil
|
||||||
self.failAllPendingRequests(error: pendingError)
|
self.failAllPendingRequests(error: pendingError)
|
||||||
@ -162,7 +173,6 @@ actor SDLIPV6AssistClient {
|
|||||||
switch state {
|
switch state {
|
||||||
case .ready:
|
case .ready:
|
||||||
SDLLogger.log("[SDLIPV6AssistClient] Connection ready", for: .debug)
|
SDLLogger.log("[SDLIPV6AssistClient] Connection ready", for: .debug)
|
||||||
self.startReceiveTask(for: connection)
|
|
||||||
case .failed(let error):
|
case .failed(let error):
|
||||||
SDLLogger.log("[SDLIPV6AssistClient] Connection failed: \(error)", for: .debug)
|
SDLLogger.log("[SDLIPV6AssistClient] Connection failed: \(error)", for: .debug)
|
||||||
self.stop(pendingError: error)
|
self.stop(pendingError: error)
|
||||||
@ -173,24 +183,6 @@ actor SDLIPV6AssistClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func startReceiveTask(for connection: NWConnection) {
|
|
||||||
guard self.receiveTask == nil else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let stream = Self.makeReceiveStream(for: connection)
|
|
||||||
self.receiveTask = Task { [weak self] in
|
|
||||||
for await data in stream {
|
|
||||||
guard let self else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
await self.handleReceivedPacket(data)
|
|
||||||
}
|
|
||||||
|
|
||||||
await self?.didFinishReceiving(for: connection)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func handleReceivedPacket(_ data: Data) {
|
private func handleReceivedPacket(_ data: Data) {
|
||||||
do {
|
do {
|
||||||
let packet = try SDLV6AssistProbeReply(serializedBytes: data)
|
let packet = try SDLV6AssistProbeReply(serializedBytes: data)
|
||||||
@ -203,18 +195,6 @@ actor SDLIPV6AssistClient {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private func didFinishReceiving(for connection: NWConnection) {
|
|
||||||
guard case .running = self.state else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.connection === connection, connection.state != .ready {
|
|
||||||
self.stop()
|
|
||||||
} else {
|
|
||||||
self.receiveTask = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func nextPacketId() -> UInt32 {
|
private func nextPacketId() -> UInt32 {
|
||||||
let packetId = self.packetId
|
let packetId = self.packetId
|
||||||
self.packetId &+= 1
|
self.packetId &+= 1
|
||||||
|
|||||||
@ -1,74 +0,0 @@
|
|||||||
//
|
|
||||||
// SDLNetworkMonitor.swift
|
|
||||||
// Tun
|
|
||||||
//
|
|
||||||
// Created by 安礼成 on 2024/5/16.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import Network
|
|
||||||
import Combine
|
|
||||||
|
|
||||||
// 监控网络的变化
|
|
||||||
class SDLNetworkMonitor: @unchecked Sendable {
|
|
||||||
private var monitor: NWPathMonitor
|
|
||||||
private var interfaceType: NWInterface.InterfaceType?
|
|
||||||
private let publisher = PassthroughSubject<NWInterface.InterfaceType, Never>()
|
|
||||||
private var cancel: AnyCancellable?
|
|
||||||
private var isStopped = false
|
|
||||||
|
|
||||||
public let eventStream: AsyncStream<MonitorEvent>
|
|
||||||
private let eventContinuation: AsyncStream<MonitorEvent>.Continuation
|
|
||||||
|
|
||||||
enum MonitorEvent {
|
|
||||||
case changed
|
|
||||||
case unreachable
|
|
||||||
}
|
|
||||||
|
|
||||||
init() {
|
|
||||||
self.monitor = NWPathMonitor()
|
|
||||||
(self.eventStream , self.eventContinuation) = AsyncStream.makeStream(of: MonitorEvent.self, bufferingPolicy: .unbounded)
|
|
||||||
}
|
|
||||||
|
|
||||||
func start() {
|
|
||||||
self.monitor.pathUpdateHandler = {path in
|
|
||||||
if path.status == .satisfied {
|
|
||||||
if path.usesInterfaceType(.wifi) {
|
|
||||||
self.publisher.send(.wifi)
|
|
||||||
} else if path.usesInterfaceType(.cellular) {
|
|
||||||
self.publisher.send(.cellular)
|
|
||||||
} else if path.usesInterfaceType(.wiredEthernet) {
|
|
||||||
self.publisher.send(.wiredEthernet)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.eventContinuation.yield(.unreachable)
|
|
||||||
self.interfaceType = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.monitor.start(queue: DispatchQueue.global())
|
|
||||||
|
|
||||||
self.cancel = publisher.throttle(for: 5.0, scheduler: DispatchQueue.global(), latest: true)
|
|
||||||
.sink { type in
|
|
||||||
if self.interfaceType != nil && self.interfaceType != type {
|
|
||||||
self.eventContinuation.yield(.changed)
|
|
||||||
}
|
|
||||||
self.interfaceType = type
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stop() {
|
|
||||||
guard !self.isStopped else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.isStopped = true
|
|
||||||
self.monitor.cancel()
|
|
||||||
self.cancel?.cancel()
|
|
||||||
self.eventContinuation.finish()
|
|
||||||
}
|
|
||||||
|
|
||||||
deinit {
|
|
||||||
self.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -99,14 +99,7 @@ final class SDLSuperSession: @unchecked Sendable {
|
|||||||
|
|
||||||
func run() async throws {
|
func run() async throws {
|
||||||
do {
|
do {
|
||||||
try await withTaskCancellationHandler {
|
try await self.runLoops()
|
||||||
try await self.runLoops()
|
|
||||||
} onCancel: {
|
|
||||||
Task {
|
|
||||||
await self.client.stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await self.stop()
|
await self.stop()
|
||||||
} catch {
|
} catch {
|
||||||
await self.stop()
|
await self.stop()
|
||||||
|
|||||||
@ -199,26 +199,20 @@ actor SDLUDPHoleSession {
|
|||||||
await self.onEvent(.ready(localAddress))
|
await self.onEvent(.ready(localAddress))
|
||||||
|
|
||||||
do {
|
do {
|
||||||
try await withTaskCancellationHandler {
|
try await withThrowingTaskGroup(of: Void.self) { group in
|
||||||
try await withThrowingTaskGroup(of: Void.self) { group in
|
defer {
|
||||||
defer {
|
group.cancelAll()
|
||||||
group.cancelAll()
|
|
||||||
}
|
|
||||||
|
|
||||||
group.addTask {
|
|
||||||
try await self.readV4Loop(udpHole: udpHole)
|
|
||||||
}
|
|
||||||
|
|
||||||
group.addTask {
|
|
||||||
await self.probeNatType(udpHole: udpHole)
|
|
||||||
}
|
|
||||||
|
|
||||||
try await group.waitForAll()
|
|
||||||
}
|
}
|
||||||
} onCancel: {
|
|
||||||
Task {
|
group.addTask {
|
||||||
await udpHole.stop()
|
try await self.readV4Loop(udpHole: udpHole)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group.addTask {
|
||||||
|
await self.probeNatType(udpHole: udpHole)
|
||||||
|
}
|
||||||
|
|
||||||
|
try await group.waitForAll()
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
await udpHole.stop()
|
await udpHole.stop()
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user