解决网络状态变化的问题
This commit is contained in:
parent
e68bf7e106
commit
971fa64685
@ -29,7 +29,6 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
// 加密算法
|
||||
let rsaCipher = try! CCRSACipher(keySize: 1024)
|
||||
self.rootTask = Task {
|
||||
do {
|
||||
// host: "192.168.0.101", port: 1265
|
||||
guard let options, let config = await SDLConfiguration.parse(options: options) else {
|
||||
completionHandler(TunnelError.invalidConfiguration)
|
||||
@ -39,17 +38,22 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
let contextActor = SDLContextActor(provider: self, config: config, rsaCipher: rsaCipher)
|
||||
self.contextActor = contextActor
|
||||
await contextActor.start()
|
||||
try await contextActor.waitForReady(timeout: .seconds(30))
|
||||
|
||||
// 这里的事件,只有启动相关的事件
|
||||
for await event in await contextActor.events() {
|
||||
switch event {
|
||||
case .ready:
|
||||
completionHandler(nil)
|
||||
} catch {
|
||||
case .failed(let err):
|
||||
await self.contextActor?.stop()
|
||||
self.contextActor = nil
|
||||
completionHandler(error)
|
||||
completionHandler(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
// Add code here to start the process of stopping the tunnel.
|
||||
Task {
|
||||
|
||||
@ -9,6 +9,11 @@ import Foundation
|
||||
import NetworkExtension
|
||||
import NIOCore
|
||||
|
||||
public enum SDLContextEvent: Sendable {
|
||||
case ready
|
||||
case failed(Error)
|
||||
}
|
||||
|
||||
// 上下文环境变量,全局共享
|
||||
/*
|
||||
1. 处理rsa的加解密逻辑
|
||||
@ -36,8 +41,11 @@ actor SDLContextActor {
|
||||
}
|
||||
}
|
||||
|
||||
// 内部事件
|
||||
private let eventStream: AsyncStream<SDLContextEvent>
|
||||
private let eventContinuation: AsyncStream<SDLContextEvent>.Continuation
|
||||
|
||||
private var readyState: ReadyState = .idle
|
||||
private var readyWaiters: [CheckedContinuation<Void, Error>] = []
|
||||
|
||||
var config: SDLConfiguration
|
||||
// nat的网络类型
|
||||
@ -121,6 +129,11 @@ actor SDLContextActor {
|
||||
self.config = config
|
||||
self.rsaCipher = rsaCipher
|
||||
|
||||
// 事件通知器
|
||||
let pair = AsyncStream<SDLContextEvent>.makeStream(bufferingPolicy: .bufferingNewest(32))
|
||||
self.eventStream = pair.stream
|
||||
self.eventContinuation = pair.continuation
|
||||
|
||||
self.puncherActor = SDLPuncherActor()
|
||||
self.proberActor = SDLNATProberActor(addressArray: config.stunProbeSocketAddressArray)
|
||||
|
||||
@ -141,6 +154,10 @@ actor SDLContextActor {
|
||||
await self.startRuntime(resetNotifier: true)
|
||||
}
|
||||
|
||||
public func events() -> AsyncStream<SDLContextEvent> {
|
||||
return eventStream
|
||||
}
|
||||
|
||||
private func startRuntime(resetNotifier: Bool) async {
|
||||
if resetNotifier {
|
||||
self.prepareTunnelNotifier()
|
||||
@ -186,37 +203,6 @@ actor SDLContextActor {
|
||||
await self.startRuntime(resetNotifier: false)
|
||||
}
|
||||
|
||||
public func waitForReady() async throws {
|
||||
switch self.readyState {
|
||||
case .ready:
|
||||
return
|
||||
case .failed(let error):
|
||||
throw error
|
||||
case .stopped:
|
||||
throw CancellationError()
|
||||
case .idle, .starting:
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
self.readyWaiters.append(continuation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public func waitForReady(timeout: Duration) async throws {
|
||||
let timeoutTask = Task {
|
||||
try? await Task.sleep(for: timeout)
|
||||
if Task.isCancelled {
|
||||
return
|
||||
}
|
||||
|
||||
self.handleReadyTimeout()
|
||||
}
|
||||
defer {
|
||||
timeoutTask.cancel()
|
||||
}
|
||||
|
||||
try await self.waitForReady()
|
||||
}
|
||||
|
||||
// 取消出口节点的时候,ip地址为: 0.0.0.0
|
||||
public func updateExitNode(exitNodeIp: String) async throws {
|
||||
if let ip = SDLUtil.ipv4StrToInt32(exitNodeIp), ip > 0 {
|
||||
@ -457,7 +443,6 @@ actor SDLContextActor {
|
||||
|
||||
// 处理context的停止问题
|
||||
public func stop() async {
|
||||
self.resumeReadyWaiters(.failure(CancellationError()))
|
||||
self.readyState = .stopped
|
||||
await self.stopRuntime()
|
||||
}
|
||||
@ -701,20 +686,6 @@ actor SDLContextActor {
|
||||
}
|
||||
}
|
||||
|
||||
private func spawnLoop(_ body: @escaping () async throws -> Void) -> Task<Void, Never> {
|
||||
return Task.detached {
|
||||
while !Task.isCancelled {
|
||||
do {
|
||||
try await body()
|
||||
} catch is CancellationError {
|
||||
break
|
||||
} catch {
|
||||
try? await Task.sleep(nanoseconds: 2_000_000_000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func getIpv4ExcludeRoutes() -> [NEIPv4Route] {
|
||||
// 要排除的路由表
|
||||
let dnsServers = SDLUtil.getMacOSSystemDnsServers()
|
||||
@ -737,57 +708,6 @@ actor SDLContextActor {
|
||||
return ipv4DnsServers.map { NEIPv4Route(destinationAddress: $0, subnetMask: "255.255.255.255") }
|
||||
}
|
||||
|
||||
private func markReady() {
|
||||
guard case .starting = self.readyState else {
|
||||
return
|
||||
}
|
||||
|
||||
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 {
|
||||
case .ready, .failed, .stopped:
|
||||
return
|
||||
case .idle, .starting:
|
||||
self.readyState = .failed(error)
|
||||
self.resumeReadyWaiters(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
private func resumeReadyWaiters(_ result: Result<Void, any Error>) {
|
||||
let waiters = self.readyWaiters
|
||||
self.readyWaiters.removeAll()
|
||||
|
||||
waiters.forEach { continuation in
|
||||
switch result {
|
||||
case .success:
|
||||
continuation.resume()
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.udpHole = nil
|
||||
self.udpHoleLocalAddress = nil
|
||||
@ -843,7 +763,6 @@ extension SDLContextActor {
|
||||
self.superRegistrationStateMachine.handleFailure()
|
||||
SDLLogger.log("[SDLContext] registerSuperAck invalid key")
|
||||
let error = SDLError.invalidKey
|
||||
self.failReady(error)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
return
|
||||
}
|
||||
@ -861,7 +780,6 @@ extension SDLContextActor {
|
||||
self.superRegistrationStateMachine.handleFailure()
|
||||
SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)")
|
||||
let error = SDLError.unsupportedAlgorithm(algorithm: algorithm)
|
||||
self.failReady(error)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
return
|
||||
}
|
||||
@ -873,12 +791,14 @@ extension SDLContextActor {
|
||||
SDLLogger.log("[SDLContext] setNetworkSettings successed")
|
||||
self.superRegistrationStateMachine.handleRegisterSuperAck()
|
||||
self.startReader()
|
||||
self.markReady()
|
||||
self.eventContinuation.yield(.ready)
|
||||
self.eventContinuation.finish()
|
||||
} catch let err {
|
||||
self.superRegistrationStateMachine.handleFailure()
|
||||
SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)")
|
||||
self.failReady(err)
|
||||
self.provider.cancelTunnelWithError(err)
|
||||
self.eventContinuation.yield(.failed(err))
|
||||
self.eventContinuation.finish()
|
||||
}
|
||||
}
|
||||
|
||||
@ -894,7 +814,6 @@ extension SDLContextActor {
|
||||
self.publishTunnelEvent(code: Int(errorCode.rawValue), message: errorMessage)
|
||||
// 报告错误并退出
|
||||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
|
||||
self.failReady(error)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
|
||||
case .noIpAddress, .networkFault, .internalFault:
|
||||
@ -924,7 +843,6 @@ extension SDLContextActor {
|
||||
|
||||
// 报告错误并退出
|
||||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -2)
|
||||
self.failReady(error)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
case .none:
|
||||
()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user