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