修复休眠恢复的问题
This commit is contained in:
parent
d3f5d7388f
commit
e10329ba2a
@ -29,23 +29,20 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
}
|
||||
|
||||
let rsaCipher = try! CCRSACipher(keySize: 1024)
|
||||
self.runtimeEnv = SDLRuntimeEnvironment(config: config, rsaCipher: rsaCipher)
|
||||
self.runtimeEnv = SDLRuntimeEnvironment(config: config, rsaCipher: rsaCipher, provider: self)
|
||||
Task {
|
||||
do {
|
||||
try await self.runtimeEnv?.start(provider: self)
|
||||
completionHandler(nil)
|
||||
} catch let err {
|
||||
await self.runtimeEnv?.submitCommand(command: .start(completion: { err in
|
||||
completionHandler(err)
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
// Add code here to start the process of stopping the tunnel.
|
||||
Task {
|
||||
await self.runtimeEnv?.stop()
|
||||
completionHandler()
|
||||
await self.runtimeEnv?.submitCommand(command: .stop(completion: {
|
||||
completionHandler()
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,37 +67,26 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
override func sleep(completionHandler: @escaping () -> Void) {
|
||||
// Add code here to get ready to sleep.
|
||||
Task {
|
||||
await self.runtimeEnv?.stop()
|
||||
completionHandler()
|
||||
await self.runtimeEnv?.submitCommand(command: .stop(completion: {
|
||||
SDLLogger.log("[PacketTunnelProvider] sleep")
|
||||
}))
|
||||
}
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
override func wake() {
|
||||
SDLLogger.log("[PacketTunnelProvider] wake up!!!!!!!")
|
||||
// 启动monitor
|
||||
let monitor = SDLPathMonitor()
|
||||
// 启动监视器,允许重入
|
||||
monitor.start()
|
||||
SDLLogger.log("[PacketTunnelProvider] monitor started")
|
||||
|
||||
// Add code here to wake up.
|
||||
Task {
|
||||
|
||||
defer {
|
||||
monitor.stop()
|
||||
}
|
||||
|
||||
// 等待网络可达
|
||||
_ = await monitor.statusStream().first {$0 == .satisfied}
|
||||
SDLLogger.log("[PacketTunnelProvider] network is satisfied")
|
||||
// 重新启动
|
||||
try await self.runtimeEnv?.start(provider: self)
|
||||
await self.runtimeEnv?.submitCommand(command: .start(completion: { err in
|
||||
SDLLogger.log("[PacketTunnelProvider] wakeup and try start")
|
||||
}))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private func handleAppRequest(message: AppRequest) async throws -> Data? {
|
||||
guard let contextActor = self.runtimeEnv?.getContextActor() else {
|
||||
guard let contextActor = await self.runtimeEnv?.getContextActor() else {
|
||||
throw TunnelError.invalidContext
|
||||
}
|
||||
|
||||
@ -130,146 +116,3 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class SDLRuntimeEnvironment {
|
||||
private enum State {
|
||||
case idle
|
||||
case starting
|
||||
case running
|
||||
case stopping
|
||||
}
|
||||
|
||||
private let stateLock = NSLock()
|
||||
private var state: State = .idle
|
||||
private var pendingStop = false
|
||||
private weak var pendingStartProvider: PacketTunnelProvider?
|
||||
private var contextActor: SDLContextActor?
|
||||
private var config: SDLConfiguration
|
||||
private let rsaCipher: CCRSACipher
|
||||
|
||||
init(config: SDLConfiguration, rsaCipher: CCRSACipher) {
|
||||
self.config = config
|
||||
self.rsaCipher = rsaCipher
|
||||
}
|
||||
|
||||
func start(provider: PacketTunnelProvider) async throws {
|
||||
guard self.markStarting(provider: provider) else {
|
||||
return
|
||||
}
|
||||
|
||||
// 重置通知中心
|
||||
SDLTunnelAppNotifier.shared.clear()
|
||||
|
||||
let contextActor = SDLContextActor(provider: provider, config: config, rsaCipher: self.rsaCipher)
|
||||
await contextActor.start()
|
||||
|
||||
let shouldStop = self.markStarted(contextActor: contextActor)
|
||||
if shouldStop {
|
||||
await self.stop()
|
||||
}
|
||||
}
|
||||
|
||||
func getContextActor() -> SDLContextActor? {
|
||||
return self.withStateLock {
|
||||
self.contextActor
|
||||
}
|
||||
}
|
||||
|
||||
func stop() async {
|
||||
guard let contextActor = self.markStopping() else {
|
||||
return
|
||||
}
|
||||
|
||||
await contextActor.stop()
|
||||
|
||||
if let provider = self.markStopped() {
|
||||
try? await self.start(provider: provider)
|
||||
}
|
||||
}
|
||||
|
||||
private func markStarting(provider: PacketTunnelProvider) -> Bool {
|
||||
return self.withStateLock {
|
||||
switch self.state {
|
||||
case .idle:
|
||||
self.pendingStop = false
|
||||
self.pendingStartProvider = nil
|
||||
self.state = .starting
|
||||
return true
|
||||
|
||||
case .starting, .running:
|
||||
SDLLogger.log("[SDLRuntimeEnvironment] skip duplicated start: \(self.state)", for: .debug)
|
||||
return false
|
||||
|
||||
case .stopping:
|
||||
self.pendingStartProvider = provider
|
||||
SDLLogger.log("[SDLRuntimeEnvironment] delay start until stop finishes", for: .debug)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func markStarted(contextActor: SDLContextActor) -> Bool {
|
||||
return self.withStateLock {
|
||||
self.contextActor = contextActor
|
||||
self.state = .running
|
||||
|
||||
let shouldStop = self.pendingStop
|
||||
self.pendingStop = false
|
||||
return shouldStop
|
||||
}
|
||||
}
|
||||
|
||||
private func markStartFailed() {
|
||||
self.withStateLock {
|
||||
self.contextActor = nil
|
||||
self.pendingStop = false
|
||||
self.pendingStartProvider = nil
|
||||
self.state = .idle
|
||||
}
|
||||
}
|
||||
|
||||
private func markStopping() -> SDLContextActor? {
|
||||
return self.withStateLock {
|
||||
switch self.state {
|
||||
case .idle:
|
||||
self.contextActor = nil
|
||||
self.pendingStop = false
|
||||
return nil
|
||||
|
||||
case .starting:
|
||||
self.pendingStop = true
|
||||
SDLLogger.log("[SDLRuntimeEnvironment] delay stop until start finishes", for: .debug)
|
||||
return nil
|
||||
|
||||
case .stopping:
|
||||
SDLLogger.log("[SDLRuntimeEnvironment] skip duplicated stop", for: .debug)
|
||||
return nil
|
||||
|
||||
case .running:
|
||||
self.state = .stopping
|
||||
let contextActor = self.contextActor
|
||||
self.contextActor = nil
|
||||
self.pendingStop = false
|
||||
return contextActor
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func markStopped() -> PacketTunnelProvider? {
|
||||
return self.withStateLock {
|
||||
self.state = .idle
|
||||
let provider = self.pendingStartProvider
|
||||
self.pendingStartProvider = nil
|
||||
return provider
|
||||
}
|
||||
}
|
||||
|
||||
private func withStateLock<T>(_ body: () -> T) -> T {
|
||||
self.stateLock.lock()
|
||||
defer {
|
||||
self.stateLock.unlock()
|
||||
}
|
||||
return body()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -14,13 +14,6 @@ import NIOCore
|
||||
1. 处理rsa的加解密逻辑
|
||||
*/
|
||||
actor SDLContextActor {
|
||||
enum ReadyState {
|
||||
case idle
|
||||
case starting
|
||||
case ready
|
||||
case failed(any Error)
|
||||
case stopped
|
||||
}
|
||||
|
||||
private enum UDPHoleKind: Equatable {
|
||||
case v4
|
||||
@ -36,8 +29,6 @@ actor SDLContextActor {
|
||||
}
|
||||
}
|
||||
|
||||
private var readyState: ReadyState = .idle
|
||||
|
||||
var config: SDLConfiguration
|
||||
// nat的网络类型
|
||||
var natType: SDLNATProberActor.NatType = .blocked
|
||||
@ -126,11 +117,6 @@ actor SDLContextActor {
|
||||
}
|
||||
|
||||
public func start() async {
|
||||
guard case .idle = self.readyState else {
|
||||
return
|
||||
}
|
||||
|
||||
self.readyState = .starting
|
||||
await self.startRuntime(resetNotifier: true)
|
||||
}
|
||||
|
||||
@ -164,20 +150,6 @@ actor SDLContextActor {
|
||||
// }
|
||||
}
|
||||
|
||||
public func sleep() async {
|
||||
SDLLogger.log("[SDLContext] sleep")
|
||||
await self.stopRuntime()
|
||||
}
|
||||
|
||||
public func wake() async {
|
||||
SDLLogger.log("[SDLContext] wakeup")
|
||||
|
||||
// 先尝试停止
|
||||
await self.stopRuntime()
|
||||
// 重新启动
|
||||
await self.startRuntime(resetNotifier: false)
|
||||
}
|
||||
|
||||
// 取消出口节点的时候,ip地址为: 0.0.0.0
|
||||
public func updateExitNode(exitNodeIp: String) async throws {
|
||||
if let ip = SDLUtil.ipv4StrToInt32(exitNodeIp), ip > 0 {
|
||||
@ -211,6 +183,7 @@ actor SDLContextActor {
|
||||
|
||||
group.addTask {
|
||||
for await event in quicClient.eventStream {
|
||||
try Task.checkCancellation()
|
||||
switch event {
|
||||
case .ready:
|
||||
readyContinuation.yield()
|
||||
@ -262,6 +235,7 @@ actor SDLContextActor {
|
||||
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
|
||||
// 注册
|
||||
await self.doRegisterSuper()
|
||||
SDLLogger.log("[SDLContext] quic doRegisterSuper")
|
||||
|
||||
// 任务取消机制
|
||||
self.registerTask = Task {
|
||||
@ -297,7 +271,7 @@ actor SDLContextActor {
|
||||
|
||||
self.handleRegisterSuperNak(nakPacket: registerSuperNak)
|
||||
case .peerInfo(let peerInfo):
|
||||
//SDLLogger.shared.log("[SDLContext] peer message: \(peerInfo)")
|
||||
SDLLogger.log("[SDLContext] peer message: \(peerInfo)")
|
||||
await self.puncherActor.handlePeerInfo(using: self.udpHole, udpHoleV6: self.udpHoleV6, peerInfo: peerInfo)
|
||||
case .event(let event):
|
||||
await self.handleEvent(event: event)
|
||||
@ -305,7 +279,7 @@ actor SDLContextActor {
|
||||
// 处理权限的请求问题
|
||||
await self.identifyStore.applyPolicyResponse(policyResponse)
|
||||
case .arpResponse(let arpResponse):
|
||||
//SDLLogger.shared.log("[SDLContext] get arp response: \(arpResponse)")
|
||||
SDLLogger.log("[SDLContext] get arp response: \(arpResponse)")
|
||||
await self.arpServer.handleArpResponse(arpResponse: arpResponse)
|
||||
}
|
||||
}
|
||||
@ -384,7 +358,9 @@ actor SDLContextActor {
|
||||
self.udpHoleWorkers = [messageTask]
|
||||
|
||||
// 开始探测nat的类型
|
||||
await self.probeNatType()
|
||||
Task {
|
||||
await self.probeNatType()
|
||||
}
|
||||
|
||||
return udpHole
|
||||
}
|
||||
@ -413,7 +389,6 @@ actor SDLContextActor {
|
||||
|
||||
// 处理context的停止问题
|
||||
public func stop() async {
|
||||
self.readyState = .stopped
|
||||
await self.stopRuntime()
|
||||
}
|
||||
|
||||
|
||||
117
Tun/SDLRuntimeEnvironment.swift
Normal file
117
Tun/SDLRuntimeEnvironment.swift
Normal file
@ -0,0 +1,117 @@
|
||||
import Foundation
|
||||
|
||||
enum SDLRuntimeEnvironmentCommand {
|
||||
case start(completion: @Sendable (Error?) -> Void)
|
||||
case stop(completion: @Sendable () -> Void)
|
||||
}
|
||||
|
||||
actor SDLRuntimeEnvironment {
|
||||
private enum State {
|
||||
case idle
|
||||
case running
|
||||
}
|
||||
|
||||
private var state: State = .idle
|
||||
private var contextActor: SDLContextActor?
|
||||
|
||||
private var config: SDLConfiguration
|
||||
private let rsaCipher: CCRSACipher
|
||||
private let provider: PacketTunnelProvider
|
||||
|
||||
private let commandStream: AsyncStream<SDLRuntimeEnvironmentCommand>
|
||||
private let commandCont: AsyncStream<SDLRuntimeEnvironmentCommand>.Continuation
|
||||
|
||||
private var commandTask: Task<Void, Never>?
|
||||
|
||||
init(config: SDLConfiguration, rsaCipher: CCRSACipher, provider: PacketTunnelProvider) {
|
||||
self.config = config
|
||||
self.rsaCipher = rsaCipher
|
||||
self.provider = provider
|
||||
|
||||
let pair = AsyncStream.makeStream(of: SDLRuntimeEnvironmentCommand.self)
|
||||
self.commandStream = pair.stream
|
||||
self.commandCont = pair.continuation
|
||||
}
|
||||
|
||||
func submitCommand(command: SDLRuntimeEnvironmentCommand) {
|
||||
self.commandCont.yield(command)
|
||||
}
|
||||
|
||||
func getContextActor() -> SDLContextActor? {
|
||||
self.contextActor
|
||||
}
|
||||
|
||||
func run() {
|
||||
let stream = self.commandStream
|
||||
|
||||
self.commandTask = Task { [weak self] in
|
||||
for await command in stream {
|
||||
guard let self else {
|
||||
break
|
||||
}
|
||||
|
||||
await self.handle(command)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func handle(_ command: SDLRuntimeEnvironmentCommand) async {
|
||||
switch command {
|
||||
case .start(let handler):
|
||||
do {
|
||||
try await self.startCommand()
|
||||
handler(nil)
|
||||
} catch {
|
||||
handler(error)
|
||||
}
|
||||
|
||||
case .stop(let handler):
|
||||
await self.stopCommand()
|
||||
handler()
|
||||
}
|
||||
}
|
||||
|
||||
private func startCommand() async throws {
|
||||
switch self.state {
|
||||
case .idle:
|
||||
SDLTunnelAppNotifier.shared.clear()
|
||||
|
||||
let contextActor = SDLContextActor(
|
||||
provider: provider,
|
||||
config: config,
|
||||
rsaCipher: self.rsaCipher
|
||||
)
|
||||
|
||||
self.contextActor = contextActor
|
||||
await contextActor.start()
|
||||
self.state = .running
|
||||
case .running:
|
||||
SDLLogger.log("[SDLRuntimeEnvironment] is running, ignore start command")
|
||||
}
|
||||
}
|
||||
|
||||
private func stopCommand() async {
|
||||
switch self.state {
|
||||
case .idle:
|
||||
SDLLogger.log("[SDLRuntimeEnvironment] is idle, ignore stop command")
|
||||
|
||||
case .running:
|
||||
let contextActor = self.contextActor
|
||||
self.contextActor = nil
|
||||
self.state = .idle
|
||||
|
||||
await contextActor?.stop()
|
||||
}
|
||||
}
|
||||
|
||||
func shutdown() {
|
||||
self.commandCont.finish()
|
||||
self.commandTask?.cancel()
|
||||
self.commandTask = nil
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.commandCont.finish()
|
||||
self.commandTask?.cancel()
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user