fix register fsm

This commit is contained in:
anlicheng 2026-04-15 10:16:13 +08:00
parent a8f0bc7804
commit 5bb39c8564
2 changed files with 107 additions and 18 deletions

View File

@ -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<Void, Error>] = []
@ -96,6 +90,7 @@ actor SDLContextActor {
//
private var registerTask: Task<Void, Never>?
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)
}

View File

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