不尝试重复注册,失败报错
This commit is contained in:
parent
136c73ccd1
commit
9817e5a5ca
@ -15,6 +15,8 @@ enum TunnelError: Error {
|
||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
private var runtimeEnv: SDLRuntimeEnvironment?
|
||||
|
||||
|
||||
|
||||
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
|
||||
// 如果当前在运行状态,不允许重复请求
|
||||
guard self.runtimeEnv == nil else {
|
||||
@ -27,6 +29,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
|
||||
self.runtimeEnv = SDLRuntimeEnvironment(options: options)
|
||||
Task {
|
||||
do {
|
||||
@ -74,10 +78,26 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
}
|
||||
|
||||
override func wake() {
|
||||
// 启动monitor
|
||||
let monitor = SDLPathMonitor()
|
||||
// 启动监视器,允许重入
|
||||
monitor.start()
|
||||
SDLLogger.log("[SDLContext] monitor started")
|
||||
|
||||
// Add code here to wake up.
|
||||
Task {
|
||||
|
||||
defer {
|
||||
monitor.stop()
|
||||
}
|
||||
|
||||
// 等待网络可达
|
||||
_ = await monitor.statusStream().first {$0 == .satisfied}
|
||||
SDLLogger.log("[SDLContext] network is satisfied")
|
||||
// 重新启动
|
||||
try await self.runtimeEnv?.start(provider: self)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func handleAppRequest(message: AppRequest) async throws -> Data? {
|
||||
|
||||
@ -84,10 +84,6 @@ actor SDLContextActor {
|
||||
private let sessionManager = SessionManager()
|
||||
nonisolated private let arpServer: ArpServer
|
||||
|
||||
// 网络状态变化的健康
|
||||
private var monitor: SDLPathMonitor?
|
||||
private var monitorWorker: Task<Void, Never>?
|
||||
|
||||
// 内部socket通讯
|
||||
// 改为基于 App Group + Darwin Notification 的通知
|
||||
|
||||
@ -113,8 +109,6 @@ actor SDLContextActor {
|
||||
// stunRequest任务
|
||||
private var stunRequestTask: Task<Void, Never>?
|
||||
|
||||
private let superRegistrationStateMachine = SDLSuperRegistrationStateMachine()
|
||||
|
||||
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher) {
|
||||
self.provider = provider
|
||||
self.config = config
|
||||
@ -144,7 +138,6 @@ actor SDLContextActor {
|
||||
if resetNotifier {
|
||||
self.prepareTunnelNotifier()
|
||||
}
|
||||
self.startMonitor()
|
||||
|
||||
// 启动arp的定时清理任务
|
||||
await self.puncherActor.start()
|
||||
@ -268,7 +261,24 @@ actor SDLContextActor {
|
||||
case .welcome(let welcome):
|
||||
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
|
||||
// 注册
|
||||
self.startRegisterLoop()
|
||||
await self.doRegisterSuper()
|
||||
|
||||
// 任务取消机制
|
||||
self.registerTask = Task {
|
||||
do {
|
||||
try await Task.sleep(for: .seconds(5))
|
||||
try Task.checkCancellation()
|
||||
|
||||
// 关闭掉当前Tunnel
|
||||
self.publishTunnelEvent(message: "校验失败")
|
||||
// 报告错误并退出
|
||||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -3)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
} catch {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 启动stun任务
|
||||
await self.startStunRequestTask(welcome: welcome)
|
||||
|
||||
@ -276,8 +286,14 @@ actor SDLContextActor {
|
||||
//SDLLogger.shared.log("[SDLContext] quic pong")
|
||||
()
|
||||
case .registerSuperAck(let registerSuperAck):
|
||||
self.registerTask?.cancel()
|
||||
self.registerTask = nil
|
||||
|
||||
await self.handleRegisterSuperAck(registerSuperAck: registerSuperAck)
|
||||
case .registerSuperNak(let registerSuperNak):
|
||||
self.registerTask?.cancel()
|
||||
self.registerTask = nil
|
||||
|
||||
self.handleRegisterSuperNak(nakPacket: registerSuperNak)
|
||||
case .peerInfo(let peerInfo):
|
||||
//SDLLogger.shared.log("[SDLContext] peer message: \(peerInfo)")
|
||||
@ -301,35 +317,6 @@ actor SDLContextActor {
|
||||
SDLLogger.log("[SDLContext] tunnelAppNotifier ready")
|
||||
}
|
||||
|
||||
private func startMonitor() {
|
||||
self.monitorWorker?.cancel()
|
||||
self.monitorWorker = nil
|
||||
|
||||
// 启动monitor
|
||||
let monitor = SDLPathMonitor()
|
||||
monitor.start()
|
||||
SDLLogger.log("[SDLContext] monitor started")
|
||||
self.monitor = monitor
|
||||
|
||||
self.monitorWorker = Task {
|
||||
for await status in monitor.statusStream() {
|
||||
switch status {
|
||||
case .satisfied:
|
||||
SDLLogger.log("[Path] stable satisfied", for: .debug)
|
||||
// await contextActor.networkPathDidBecomeSatisfied(snapshot)
|
||||
case .unsatisfied:
|
||||
SDLLogger.log("[Path] stable unsatisfied", for: .debug)
|
||||
// await contextActor.networkPathDidBecomeUnsatisfied(snapshot)
|
||||
case .requiresConnection:
|
||||
SDLLogger.log("[Path] stable requiresConnection", for: .debug)
|
||||
|
||||
@unknown default:
|
||||
SDLLogger.log("[Path] stable unknown", for: .debug)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func startDnsClient() async {
|
||||
self.dnsWorker?.cancel()
|
||||
self.dnsWorker = nil
|
||||
@ -430,7 +417,6 @@ actor SDLContextActor {
|
||||
}
|
||||
|
||||
private func stopRuntime() async {
|
||||
self.superRegistrationStateMachine.reset()
|
||||
|
||||
await self.supervisor.stop()
|
||||
await self.puncherActor.stop()
|
||||
@ -463,12 +449,7 @@ actor SDLContextActor {
|
||||
self.dnsLocalWorker?.cancel()
|
||||
self.dnsLocalWorker = nil
|
||||
self.dnsLocalClient = nil
|
||||
|
||||
self.monitor?.stop()
|
||||
self.monitorWorker?.cancel()
|
||||
self.monitorWorker = nil
|
||||
self.monitor = nil
|
||||
|
||||
|
||||
self.readTask?.cancel()
|
||||
self.readTask = nil
|
||||
|
||||
@ -706,43 +687,9 @@ extension SDLContextActor {
|
||||
return .init(networkAddress: self.config.networkAddress)
|
||||
}
|
||||
|
||||
// 开启注册任务
|
||||
private func startRegisterLoop() {
|
||||
guard self.registerTask == nil,
|
||||
self.superRegistrationStateMachine.beginLoop() else {
|
||||
return
|
||||
}
|
||||
|
||||
self.registerTask = Task {
|
||||
defer {
|
||||
self.registerTask = nil
|
||||
}
|
||||
|
||||
while !Task.isCancelled {
|
||||
switch self.superRegistrationStateMachine.makeLoopAction() {
|
||||
case .sendRegister:
|
||||
await 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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.provider.cancelTunnelWithError(error)
|
||||
@ -759,7 +706,6 @@ 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.provider.cancelTunnelWithError(error)
|
||||
@ -771,10 +717,10 @@ extension SDLContextActor {
|
||||
do {
|
||||
try await self.setNetworkSettings(config: self.config, dnsServer: DNSHelper.dnsServer)
|
||||
SDLLogger.log("[SDLContext] setNetworkSettings successed")
|
||||
self.superRegistrationStateMachine.handleRegisterSuperAck()
|
||||
self.startReader()
|
||||
// 开启权限的定时更新
|
||||
await self.whenRegistedSuper()
|
||||
} catch let err {
|
||||
self.superRegistrationStateMachine.handleFailure()
|
||||
SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)")
|
||||
self.provider.cancelTunnelWithError(err)
|
||||
}
|
||||
@ -788,18 +734,15 @@ extension SDLContextActor {
|
||||
|
||||
switch errorCode {
|
||||
case .invalidToken, .nodeDisabled:
|
||||
self.superRegistrationStateMachine.handleFailure()
|
||||
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
||||
// 报告错误并退出
|
||||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
|
||||
case .noIpAddress, .networkFault, .internalFault:
|
||||
self.superRegistrationStateMachine.handleRetryableNak()
|
||||
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
||||
}
|
||||
SDLLogger.log("[SDLContext] Get a SuperNak message exit")
|
||||
|
||||
}
|
||||
|
||||
private func handleEvent(event: SDLEvent) async {
|
||||
|
||||
@ -1,76 +0,0 @@
|
||||
//
|
||||
// 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 = .registering
|
||||
}
|
||||
|
||||
func handleFailure() {
|
||||
self.state = .failed
|
||||
}
|
||||
|
||||
func reset() {
|
||||
self.state = .idle
|
||||
}
|
||||
|
||||
}
|
||||
@ -12,7 +12,14 @@ final class SDLPathMonitor {
|
||||
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)
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user