From 7ce880f3dc6c6d5072c689645a41353c4a19cbd1 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Tue, 28 Apr 2026 10:22:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=83=A8=E5=88=86=E7=8A=B6?= =?UTF-8?q?=E6=80=81=E4=B8=8D=E4=B8=80=E8=87=B4=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 | 29 +++++++----- Tun/Punchnet/Actors/SDLContextActor.swift | 46 ++++++++++++++++++- .../SDLSuperRegistrationStateMachine.swift | 2 +- 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/Tun/PacketTunnelProvider.swift b/Tun/PacketTunnelProvider.swift index b1cf467..dd25d8c 100644 --- a/Tun/PacketTunnelProvider.swift +++ b/Tun/PacketTunnelProvider.swift @@ -14,7 +14,7 @@ enum TunnelError: Error { class PacketTunnelProvider: NEPacketTunnelProvider { var contextActor: SDLContextActor? - private var rootTask: Task? + private var rootTask: Task? override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) { // 重置通知中心 @@ -29,17 +29,24 @@ class PacketTunnelProvider: NEPacketTunnelProvider { // 加密算法 let rsaCipher = try! CCRSACipher(keySize: 1024) self.rootTask = Task { - // host: "192.168.0.101", port: 1265 - guard let options, let config = await SDLConfiguration.parse(options: options) else { - completionHandler(TunnelError.invalidConfiguration) - return + do { + // 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() + try await contextActor.waitForReady(timeout: .seconds(30)) + + completionHandler(nil) + } catch { + await self.contextActor?.stop() + self.contextActor = nil + completionHandler(error) } - - self.contextActor = SDLContextActor(provider: self, config: config, rsaCipher: rsaCipher) - await self.contextActor?.start() - try await self.contextActor?.waitForReady() - - completionHandler(nil) } } diff --git a/Tun/Punchnet/Actors/SDLContextActor.swift b/Tun/Punchnet/Actors/SDLContextActor.swift index f57607e..13c2c02 100644 --- a/Tun/Punchnet/Actors/SDLContextActor.swift +++ b/Tun/Punchnet/Actors/SDLContextActor.swift @@ -185,6 +185,22 @@ actor SDLContextActor { } } } + + public func waitForReady(timeout: Duration) async throws { + let timeoutTask = Task { + try? await Task.sleep(for: timeout) + if Task.isCancelled { + return + } + + await self.handleReadyTimeout() + } + defer { + timeoutTask.cancel() + } + + try await self.waitForReady() + } // 取消出口节点的时候,ip地址为: 0.0.0.0 public func updateExitNode(exitNodeIp: String) async throws { @@ -417,7 +433,10 @@ actor SDLContextActor { self.registerTask?.cancel() self.registerTask = nil - + + self.stunRequestTask?.cancel() + self.stunRequestTask = nil + self.updatePolicyTask?.cancel() self.updatePolicyTask = nil @@ -451,6 +470,9 @@ actor SDLContextActor { // MARK: -- StunRequestTask private func startStunRequestTask(welcome: SDLWelcome) async { + self.stunRequestTask?.cancel() + self.stunRequestTask = nil + await self.ipv6AssistClient?.stop() self.ipv6AssistClient = SDLIPV6AssistClient(assistServerInfo: welcome.ipv6Assist) await self.ipv6AssistClient?.start() @@ -462,6 +484,10 @@ actor SDLContextActor { timerStream.start(interval: .seconds(8)) for await _ in timerStream.stream { + if Task.isCancelled { + break + } + let probeReply = try? await self.ipv6AssistClient?.probe(requestTimeout: .seconds(3)) if let v6Info = probeReply?.v6Info, let v6Address = SDLUtil.ipv6DataToString(v6Info.v6) { SDLLogger.log("[SDLContext] probe ipv6 address: \(v6Address)") @@ -644,6 +670,24 @@ actor SDLContextActor { 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 { diff --git a/Tun/Punchnet/Actors/SDLSuperRegistrationStateMachine.swift b/Tun/Punchnet/Actors/SDLSuperRegistrationStateMachine.swift index efbc548..aeaf5f6 100644 --- a/Tun/Punchnet/Actors/SDLSuperRegistrationStateMachine.swift +++ b/Tun/Punchnet/Actors/SDLSuperRegistrationStateMachine.swift @@ -62,7 +62,7 @@ final class SDLSuperRegistrationStateMachine { } func handleRetryableNak() { - self.state = .failed + self.state = .registering } func handleFailure() {