不尝试重复注册,失败报错
This commit is contained in:
parent
136c73ccd1
commit
9817e5a5ca
@ -15,6 +15,8 @@ enum TunnelError: Error {
|
|||||||
class PacketTunnelProvider: NEPacketTunnelProvider {
|
class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||||
private var runtimeEnv: SDLRuntimeEnvironment?
|
private var runtimeEnv: SDLRuntimeEnvironment?
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
|
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
|
||||||
// 如果当前在运行状态,不允许重复请求
|
// 如果当前在运行状态,不允许重复请求
|
||||||
guard self.runtimeEnv == nil else {
|
guard self.runtimeEnv == nil else {
|
||||||
@ -27,6 +29,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.runtimeEnv = SDLRuntimeEnvironment(options: options)
|
self.runtimeEnv = SDLRuntimeEnvironment(options: options)
|
||||||
Task {
|
Task {
|
||||||
do {
|
do {
|
||||||
@ -74,10 +78,26 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override func wake() {
|
override func wake() {
|
||||||
|
// 启动monitor
|
||||||
|
let monitor = SDLPathMonitor()
|
||||||
|
// 启动监视器,允许重入
|
||||||
|
monitor.start()
|
||||||
|
SDLLogger.log("[SDLContext] monitor started")
|
||||||
|
|
||||||
// Add code here to wake up.
|
// Add code here to wake up.
|
||||||
Task {
|
Task {
|
||||||
|
|
||||||
|
defer {
|
||||||
|
monitor.stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 等待网络可达
|
||||||
|
_ = await monitor.statusStream().first {$0 == .satisfied}
|
||||||
|
SDLLogger.log("[SDLContext] network is satisfied")
|
||||||
|
// 重新启动
|
||||||
try await self.runtimeEnv?.start(provider: self)
|
try await self.runtimeEnv?.start(provider: self)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleAppRequest(message: AppRequest) async throws -> Data? {
|
private func handleAppRequest(message: AppRequest) async throws -> Data? {
|
||||||
|
|||||||
@ -84,10 +84,6 @@ actor SDLContextActor {
|
|||||||
private let sessionManager = SessionManager()
|
private let sessionManager = SessionManager()
|
||||||
nonisolated private let arpServer: ArpServer
|
nonisolated private let arpServer: ArpServer
|
||||||
|
|
||||||
// 网络状态变化的健康
|
|
||||||
private var monitor: SDLPathMonitor?
|
|
||||||
private var monitorWorker: Task<Void, Never>?
|
|
||||||
|
|
||||||
// 内部socket通讯
|
// 内部socket通讯
|
||||||
// 改为基于 App Group + Darwin Notification 的通知
|
// 改为基于 App Group + Darwin Notification 的通知
|
||||||
|
|
||||||
@ -113,8 +109,6 @@ actor SDLContextActor {
|
|||||||
// stunRequest任务
|
// stunRequest任务
|
||||||
private var stunRequestTask: Task<Void, Never>?
|
private var stunRequestTask: Task<Void, Never>?
|
||||||
|
|
||||||
private let superRegistrationStateMachine = SDLSuperRegistrationStateMachine()
|
|
||||||
|
|
||||||
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher) {
|
public init(provider: NEPacketTunnelProvider, config: SDLConfiguration, rsaCipher: RSACipher) {
|
||||||
self.provider = provider
|
self.provider = provider
|
||||||
self.config = config
|
self.config = config
|
||||||
@ -144,7 +138,6 @@ actor SDLContextActor {
|
|||||||
if resetNotifier {
|
if resetNotifier {
|
||||||
self.prepareTunnelNotifier()
|
self.prepareTunnelNotifier()
|
||||||
}
|
}
|
||||||
self.startMonitor()
|
|
||||||
|
|
||||||
// 启动arp的定时清理任务
|
// 启动arp的定时清理任务
|
||||||
await self.puncherActor.start()
|
await self.puncherActor.start()
|
||||||
@ -268,7 +261,24 @@ actor SDLContextActor {
|
|||||||
case .welcome(let welcome):
|
case .welcome(let welcome):
|
||||||
SDLLogger.log("[SDLContext] quic welcome: \(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任务
|
// 启动stun任务
|
||||||
await self.startStunRequestTask(welcome: welcome)
|
await self.startStunRequestTask(welcome: welcome)
|
||||||
|
|
||||||
@ -276,8 +286,14 @@ actor SDLContextActor {
|
|||||||
//SDLLogger.shared.log("[SDLContext] quic pong")
|
//SDLLogger.shared.log("[SDLContext] quic pong")
|
||||||
()
|
()
|
||||||
case .registerSuperAck(let registerSuperAck):
|
case .registerSuperAck(let registerSuperAck):
|
||||||
|
self.registerTask?.cancel()
|
||||||
|
self.registerTask = nil
|
||||||
|
|
||||||
await self.handleRegisterSuperAck(registerSuperAck: registerSuperAck)
|
await self.handleRegisterSuperAck(registerSuperAck: registerSuperAck)
|
||||||
case .registerSuperNak(let registerSuperNak):
|
case .registerSuperNak(let registerSuperNak):
|
||||||
|
self.registerTask?.cancel()
|
||||||
|
self.registerTask = nil
|
||||||
|
|
||||||
self.handleRegisterSuperNak(nakPacket: registerSuperNak)
|
self.handleRegisterSuperNak(nakPacket: registerSuperNak)
|
||||||
case .peerInfo(let peerInfo):
|
case .peerInfo(let peerInfo):
|
||||||
//SDLLogger.shared.log("[SDLContext] peer message: \(peerInfo)")
|
//SDLLogger.shared.log("[SDLContext] peer message: \(peerInfo)")
|
||||||
@ -301,35 +317,6 @@ actor SDLContextActor {
|
|||||||
SDLLogger.log("[SDLContext] tunnelAppNotifier ready")
|
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 {
|
private func startDnsClient() async {
|
||||||
self.dnsWorker?.cancel()
|
self.dnsWorker?.cancel()
|
||||||
self.dnsWorker = nil
|
self.dnsWorker = nil
|
||||||
@ -430,7 +417,6 @@ actor SDLContextActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func stopRuntime() async {
|
private func stopRuntime() async {
|
||||||
self.superRegistrationStateMachine.reset()
|
|
||||||
|
|
||||||
await self.supervisor.stop()
|
await self.supervisor.stop()
|
||||||
await self.puncherActor.stop()
|
await self.puncherActor.stop()
|
||||||
@ -463,12 +449,7 @@ actor SDLContextActor {
|
|||||||
self.dnsLocalWorker?.cancel()
|
self.dnsLocalWorker?.cancel()
|
||||||
self.dnsLocalWorker = nil
|
self.dnsLocalWorker = nil
|
||||||
self.dnsLocalClient = nil
|
self.dnsLocalClient = nil
|
||||||
|
|
||||||
self.monitor?.stop()
|
|
||||||
self.monitorWorker?.cancel()
|
|
||||||
self.monitorWorker = nil
|
|
||||||
self.monitor = nil
|
|
||||||
|
|
||||||
self.readTask?.cancel()
|
self.readTask?.cancel()
|
||||||
self.readTask = nil
|
self.readTask = nil
|
||||||
|
|
||||||
@ -706,43 +687,9 @@ extension SDLContextActor {
|
|||||||
return .init(networkAddress: self.config.networkAddress)
|
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 {
|
private func handleRegisterSuperAck(registerSuperAck: SDLRegisterSuperAck) async {
|
||||||
// 需要对数据通过rsa的私钥解码
|
// 需要对数据通过rsa的私钥解码
|
||||||
guard let key = try? self.rsaCipher.decode(data: Data(registerSuperAck.key)) else {
|
guard let key = try? self.rsaCipher.decode(data: Data(registerSuperAck.key)) else {
|
||||||
self.superRegistrationStateMachine.handleFailure()
|
|
||||||
SDLLogger.log("[SDLContext] registerSuperAck invalid key")
|
SDLLogger.log("[SDLContext] registerSuperAck invalid key")
|
||||||
let error = SDLError.invalidKey
|
let error = SDLError.invalidKey
|
||||||
self.provider.cancelTunnelWithError(error)
|
self.provider.cancelTunnelWithError(error)
|
||||||
@ -759,7 +706,6 @@ extension SDLContextActor {
|
|||||||
case "chacha20":
|
case "chacha20":
|
||||||
self.dataCipher = CCChaCha20Cipher(regionId: regionId, keyData: key)
|
self.dataCipher = CCChaCha20Cipher(regionId: regionId, keyData: key)
|
||||||
default:
|
default:
|
||||||
self.superRegistrationStateMachine.handleFailure()
|
|
||||||
SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)")
|
SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)")
|
||||||
let error = SDLError.unsupportedAlgorithm(algorithm: algorithm)
|
let error = SDLError.unsupportedAlgorithm(algorithm: algorithm)
|
||||||
self.provider.cancelTunnelWithError(error)
|
self.provider.cancelTunnelWithError(error)
|
||||||
@ -771,10 +717,10 @@ extension SDLContextActor {
|
|||||||
do {
|
do {
|
||||||
try await self.setNetworkSettings(config: self.config, dnsServer: DNSHelper.dnsServer)
|
try await self.setNetworkSettings(config: self.config, dnsServer: DNSHelper.dnsServer)
|
||||||
SDLLogger.log("[SDLContext] setNetworkSettings successed")
|
SDLLogger.log("[SDLContext] setNetworkSettings successed")
|
||||||
self.superRegistrationStateMachine.handleRegisterSuperAck()
|
|
||||||
self.startReader()
|
self.startReader()
|
||||||
|
// 开启权限的定时更新
|
||||||
|
await self.whenRegistedSuper()
|
||||||
} catch let err {
|
} catch let err {
|
||||||
self.superRegistrationStateMachine.handleFailure()
|
|
||||||
SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)")
|
SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)")
|
||||||
self.provider.cancelTunnelWithError(err)
|
self.provider.cancelTunnelWithError(err)
|
||||||
}
|
}
|
||||||
@ -788,18 +734,15 @@ extension SDLContextActor {
|
|||||||
|
|
||||||
switch errorCode {
|
switch errorCode {
|
||||||
case .invalidToken, .nodeDisabled:
|
case .invalidToken, .nodeDisabled:
|
||||||
self.superRegistrationStateMachine.handleFailure()
|
|
||||||
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
||||||
// 报告错误并退出
|
// 报告错误并退出
|
||||||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
|
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
|
||||||
self.provider.cancelTunnelWithError(error)
|
self.provider.cancelTunnelWithError(error)
|
||||||
|
|
||||||
case .noIpAddress, .networkFault, .internalFault:
|
case .noIpAddress, .networkFault, .internalFault:
|
||||||
self.superRegistrationStateMachine.handleRetryableNak()
|
|
||||||
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
||||||
}
|
}
|
||||||
SDLLogger.log("[SDLContext] Get a SuperNak message exit")
|
SDLLogger.log("[SDLContext] Get a SuperNak message exit")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleEvent(event: SDLEvent) async {
|
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 queue = DispatchQueue(label: "com.sdlan.path-monitor")
|
||||||
private let debouncer = SDLPathDebounceActor(delay: .seconds(2))
|
private let debouncer = SDLPathDebounceActor(delay: .seconds(2))
|
||||||
|
|
||||||
|
private var isStarted: Bool = false
|
||||||
|
|
||||||
func start() {
|
func start() {
|
||||||
|
guard !isStarted else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.isStarted = true
|
||||||
monitor.pathUpdateHandler = { path in
|
monitor.pathUpdateHandler = { path in
|
||||||
let snapshot = SDLPathSnapshot(path)
|
let snapshot = SDLPathSnapshot(path)
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user