From 5bb39c8564c35ab081b5a32f9dd87efbc66b73d6 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Wed, 15 Apr 2026 10:16:13 +0800 Subject: [PATCH] fix register fsm --- Tun/Punchnet/Actors/SDLContextActor.swift | 49 +++++++----- .../SDLSuperRegistrationStateMachine.swift | 76 +++++++++++++++++++ 2 files changed, 107 insertions(+), 18 deletions(-) create mode 100644 Tun/Punchnet/Actors/SDLSuperRegistrationStateMachine.swift diff --git a/Tun/Punchnet/Actors/SDLContextActor.swift b/Tun/Punchnet/Actors/SDLContextActor.swift index af70d7f..43261cc 100644 --- a/Tun/Punchnet/Actors/SDLContextActor.swift +++ b/Tun/Punchnet/Actors/SDLContextActor.swift @@ -14,11 +14,6 @@ import NIOCore 1. 处理rsa的加解密逻辑 */ actor SDLContextActor { - enum State { - case unregistered - case registered - } - enum ReadyState { case idle case starting @@ -27,7 +22,6 @@ actor SDLContextActor { case stopped } - private var state: State = .unregistered private var readyState: ReadyState = .idle private var readyWaiters: [CheckedContinuation] = [] @@ -96,6 +90,7 @@ actor SDLContextActor { // 注册任务 private var registerTask: Task? + private let superRegistrationStateMachine = SDLSuperRegistrationStateMachine() public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher) { self.provider = provider @@ -347,7 +342,7 @@ actor SDLContextActor { public func stop() async { self.resumeReadyWaiters(.failure(CancellationError())) self.readyState = .stopped - self.state = .unregistered + self.superRegistrationStateMachine.reset() await self.supervisor.stop() await self.puncherActor.stop() @@ -631,27 +626,41 @@ extension SDLContextActor { // 开启注册任务 private func startRegisterLoop() { - guard self.registerTask == nil else { + guard self.registerTask == nil, + self.superRegistrationStateMachine.beginLoop() else { return } self.registerTask = Task { - while !Task.isCancelled { - self.doRegisterSuper() - try? await Task.sleep(for: .seconds(5)) - if self.state == .registered { - await self.whenRegistedSuper() - break - } - SDLLogger.log("[SDLContext] register super failed, retry") + defer { + self.registerTask = nil + } + + while !Task.isCancelled { + switch self.superRegistrationStateMachine.makeLoopAction() { + case .sendRegister: + self.doRegisterSuper() + case .stop: + return + } + try? await Task.sleep(for: .seconds(5)) + switch self.superRegistrationStateMachine.makeWaitDecision() { + case .registered: + await self.whenRegistedSuper() + return + case .retry: + SDLLogger.log("[SDLContext] register super failed, retry") + case .stop: + return + } } - self.registerTask = nil } } private func handleRegisterSuperAck(registerSuperAck: SDLRegisterSuperAck) async { // 需要对数据通过rsa的私钥解码 guard let key = try? self.rsaCipher.decode(data: Data(registerSuperAck.key)) else { + self.superRegistrationStateMachine.handleFailure() SDLLogger.log("[SDLContext] registerSuperAck invalid key") let error = SDLError.invalidKey self.failReady(error) @@ -669,6 +678,7 @@ extension SDLContextActor { case "chacha20": self.dataCipher = CCChaCha20Cipher(regionId: regionId, keyData: key) default: + self.superRegistrationStateMachine.handleFailure() SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)") let error = SDLError.unsupportedAlgorithm(algorithm: algorithm) self.failReady(error) @@ -681,10 +691,11 @@ extension SDLContextActor { do { try await self.setNetworkSettings(config: self.config, dnsServer: DNSHelper.dnsServer) SDLLogger.log("[SDLContext] setNetworkSettings successed") - self.state = .registered + self.superRegistrationStateMachine.handleRegisterSuperAck() self.startReader() self.markReady() } catch let err { + self.superRegistrationStateMachine.handleFailure() SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)") self.failReady(err) self.provider.cancelTunnelWithError(err) @@ -699,6 +710,7 @@ extension SDLContextActor { switch errorCode { case .invalidToken, .nodeDisabled: + self.superRegistrationStateMachine.handleFailure() let alertNotice = NoticeMessage.alert(alert: errorMessage) self.noticeClient?.send(data: alertNotice) // 报告错误并退出 @@ -707,6 +719,7 @@ extension SDLContextActor { self.provider.cancelTunnelWithError(error) case .noIpAddress, .networkFault, .internalFault: + self.superRegistrationStateMachine.handleRetryableNak() let alertNotice = NoticeMessage.alert(alert: errorMessage) self.noticeClient?.send(data: alertNotice) } diff --git a/Tun/Punchnet/Actors/SDLSuperRegistrationStateMachine.swift b/Tun/Punchnet/Actors/SDLSuperRegistrationStateMachine.swift new file mode 100644 index 0000000..efbc548 --- /dev/null +++ b/Tun/Punchnet/Actors/SDLSuperRegistrationStateMachine.swift @@ -0,0 +1,76 @@ +// +// SDLSuperRegistrationStateMachine.swift +// Tun +// +// Created by 安礼成 on 2026/4/15. +// + +import Foundation + +final class SDLSuperRegistrationStateMachine { + enum State: Equatable { + case idle + case registering + case registered + case failed + } + + enum LoopAction { + case sendRegister + case stop + } + + enum WaitDecision { + case retry + case registered + case stop + } + + private(set) var state: State = .idle + + func beginLoop() -> Bool { + guard self.state != .registering else { + return false + } + + self.state = .registering + return true + } + + func makeLoopAction() -> LoopAction { + switch self.state { + case .registering: + return .sendRegister + case .idle, .registered, .failed: + return .stop + } + } + + func makeWaitDecision() -> WaitDecision { + switch self.state { + case .registering: + return .retry + case .registered: + return .registered + case .idle, .failed: + return .stop + } + } + + func handleRegisterSuperAck() { + self.state = .registered + } + + func handleRetryableNak() { + self.state = .failed + } + + func handleFailure() { + self.state = .failed + } + + func reset() { + self.state = .idle + } + +}