From 971fa64685f2f2571acc8f722cc00792b3880fa1 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Wed, 29 Apr 2026 17:22:51 +0800 Subject: [PATCH] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E7=BD=91=E7=BB=9C=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E5=8F=98=E5=8C=96=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Tun/PacketTunnelProvider.swift | 36 ++++--- Tun/Punchnet/Actors/SDLContextActor.swift | 126 ++++------------------ 2 files changed, 42 insertions(+), 120 deletions(-) diff --git a/Tun/PacketTunnelProvider.swift b/Tun/PacketTunnelProvider.swift index 3e0b55f..e184396 100644 --- a/Tun/PacketTunnelProvider.swift +++ b/Tun/PacketTunnelProvider.swift @@ -29,25 +29,29 @@ class PacketTunnelProvider: NEPacketTunnelProvider { // 加密算法 let rsaCipher = try! CCRSACipher(keySize: 1024) self.rootTask = Task { - do { - // host: "192.168.0.101", port: 1265 - guard let options, let config = await SDLConfiguration.parse(options: options) else { - completionHandler(TunnelError.invalidConfiguration) - return + // host: "192.168.0.101", port: 1265 + guard let options, let config = await SDLConfiguration.parse(options: options) else { + completionHandler(TunnelError.invalidConfiguration) + return + } + + let contextActor = SDLContextActor(provider: self, config: config, rsaCipher: rsaCipher) + self.contextActor = contextActor + await contextActor.start() + + // 这里的事件,只有启动相关的事件 + for await event in await contextActor.events() { + switch event { + case .ready: + completionHandler(nil) + case .failed(let err): + await self.contextActor?.stop() + self.contextActor = nil + completionHandler(err) } - - let contextActor = SDLContextActor(provider: self, config: config, rsaCipher: rsaCipher) - self.contextActor = contextActor - await contextActor.start() - try await contextActor.waitForReady(timeout: .seconds(30)) - - completionHandler(nil) - } catch { - await self.contextActor?.stop() - self.contextActor = nil - completionHandler(error) } } + } override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { diff --git a/Tun/Punchnet/Actors/SDLContextActor.swift b/Tun/Punchnet/Actors/SDLContextActor.swift index 7901426..ae6859e 100644 --- a/Tun/Punchnet/Actors/SDLContextActor.swift +++ b/Tun/Punchnet/Actors/SDLContextActor.swift @@ -9,6 +9,11 @@ import Foundation import NetworkExtension import NIOCore +public enum SDLContextEvent: Sendable { + case ready + case failed(Error) +} + // 上下文环境变量,全局共享 /* 1. 处理rsa的加解密逻辑 @@ -35,9 +40,12 @@ actor SDLContextActor { } } } + + // 内部事件 + private let eventStream: AsyncStream + private let eventContinuation: AsyncStream.Continuation private var readyState: ReadyState = .idle - private var readyWaiters: [CheckedContinuation] = [] var config: SDLConfiguration // nat的网络类型 @@ -120,6 +128,11 @@ actor SDLContextActor { self.provider = provider self.config = config self.rsaCipher = rsaCipher + + // 事件通知器 + let pair = AsyncStream.makeStream(bufferingPolicy: .bufferingNewest(32)) + self.eventStream = pair.stream + self.eventContinuation = pair.continuation self.puncherActor = SDLPuncherActor() self.proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray) @@ -140,6 +153,10 @@ actor SDLContextActor { self.readyState = .starting await self.startRuntime(resetNotifier: true) } + + public func events() -> AsyncStream { + return eventStream + } private func startRuntime(resetNotifier: Bool) async { if resetNotifier { @@ -186,37 +203,6 @@ actor SDLContextActor { await self.startRuntime(resetNotifier: false) } - public func waitForReady() async throws { - switch self.readyState { - case .ready: - return - case .failed(let error): - throw error - case .stopped: - throw CancellationError() - case .idle, .starting: - try await withCheckedThrowingContinuation { continuation in - self.readyWaiters.append(continuation) - } - } - } - - public func waitForReady(timeout: Duration) async throws { - let timeoutTask = Task { - try? await Task.sleep(for: timeout) - if Task.isCancelled { - return - } - - self.handleReadyTimeout() - } - defer { - timeoutTask.cancel() - } - - try await self.waitForReady() - } - // 取消出口节点的时候,ip地址为: 0.0.0.0 public func updateExitNode(exitNodeIp: String) async throws { if let ip = SDLUtil.ipv4StrToInt32(exitNodeIp), ip > 0 { @@ -457,7 +443,6 @@ actor SDLContextActor { // 处理context的停止问题 public func stop() async { - self.resumeReadyWaiters(.failure(CancellationError())) self.readyState = .stopped await self.stopRuntime() } @@ -701,20 +686,6 @@ actor SDLContextActor { } } - private func spawnLoop(_ body: @escaping () async throws -> Void) -> Task { - return Task.detached { - while !Task.isCancelled { - do { - try await body() - } catch is CancellationError { - break - } catch { - try? await Task.sleep(nanoseconds: 2_000_000_000) - } - } - } - } - private func getIpv4ExcludeRoutes() -> [NEIPv4Route] { // 要排除的路由表 let dnsServers = SDLUtil.getMacOSSystemDnsServers() @@ -737,57 +708,6 @@ actor SDLContextActor { return ipv4DnsServers.map { NEIPv4Route(destinationAddress: $0, subnetMask: "255.255.255.255") } } - private func markReady() { - guard case .starting = self.readyState else { - return - } - - self.readyState = .ready - self.resumeReadyWaiters(.success(())) - } - - private func handleReadyTimeout() { - switch self.readyState { - case .idle, .starting: - break - case .ready, .failed, .stopped: - return - } - - let error = NSError( - domain: "com.jihe.punchnet.tun", - code: -3, - userInfo: [NSLocalizedDescriptionKey: "Tunnel startup timed out"] - ) - SDLLogger.log("[SDLContext] wait ready timeout") - self.failReady(error) - self.provider.cancelTunnelWithError(error) - } - - private func failReady(_ error: any Error) { - switch self.readyState { - case .ready, .failed, .stopped: - return - case .idle, .starting: - self.readyState = .failed(error) - self.resumeReadyWaiters(.failure(error)) - } - } - - private func resumeReadyWaiters(_ result: Result) { - let waiters = self.readyWaiters - self.readyWaiters.removeAll() - - waiters.forEach { continuation in - switch result { - case .success: - continuation.resume() - case .failure(let error): - continuation.resume(throwing: error) - } - } - } - deinit { self.udpHole = nil self.udpHoleLocalAddress = nil @@ -843,7 +763,6 @@ extension SDLContextActor { self.superRegistrationStateMachine.handleFailure() SDLLogger.log("[SDLContext] registerSuperAck invalid key") let error = SDLError.invalidKey - self.failReady(error) self.provider.cancelTunnelWithError(error) return } @@ -861,7 +780,6 @@ extension SDLContextActor { self.superRegistrationStateMachine.handleFailure() SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)") let error = SDLError.unsupportedAlgorithm(algorithm: algorithm) - self.failReady(error) self.provider.cancelTunnelWithError(error) return } @@ -873,12 +791,14 @@ extension SDLContextActor { SDLLogger.log("[SDLContext] setNetworkSettings successed") self.superRegistrationStateMachine.handleRegisterSuperAck() self.startReader() - self.markReady() + self.eventContinuation.yield(.ready) + self.eventContinuation.finish() } catch let err { self.superRegistrationStateMachine.handleFailure() SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)") - self.failReady(err) self.provider.cancelTunnelWithError(err) + self.eventContinuation.yield(.failed(err)) + self.eventContinuation.finish() } } @@ -894,7 +814,6 @@ extension SDLContextActor { self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage) // 报告错误并退出 let error = NSError(domain: "com.jihe.punchnet.tun", code: -1) - self.failReady(error) self.provider.cancelTunnelWithError(error) case .noIpAddress, .networkFault, .internalFault: @@ -924,7 +843,6 @@ extension SDLContextActor { // 报告错误并退出 let error = NSError(domain: "com.jihe.punchnet.tun", code: -2) - self.failReady(error) self.provider.cancelTunnelWithError(error) case .none: ()