修复休眠恢复的问题

This commit is contained in:
anlicheng 2026-05-04 17:13:36 +08:00
parent d3f5d7388f
commit e10329ba2a
3 changed files with 140 additions and 205 deletions

View File

@ -29,23 +29,20 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
} }
let rsaCipher = try! CCRSACipher(keySize: 1024) let rsaCipher = try! CCRSACipher(keySize: 1024)
self.runtimeEnv = SDLRuntimeEnvironment(config: config, rsaCipher: rsaCipher) self.runtimeEnv = SDLRuntimeEnvironment(config: config, rsaCipher: rsaCipher, provider: self)
Task { Task {
do { await self.runtimeEnv?.submitCommand(command: .start(completion: { err in
try await self.runtimeEnv?.start(provider: self)
completionHandler(nil)
} catch let err {
completionHandler(err) completionHandler(err)
} }))
} }
} }
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) { override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
// Add code here to start the process of stopping the tunnel. // Add code here to start the process of stopping the tunnel.
Task { Task {
await self.runtimeEnv?.stop() await self.runtimeEnv?.submitCommand(command: .stop(completion: {
completionHandler() completionHandler()
}))
} }
} }
@ -70,37 +67,26 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
override func sleep(completionHandler: @escaping () -> Void) { override func sleep(completionHandler: @escaping () -> Void) {
// Add code here to get ready to sleep. // Add code here to get ready to sleep.
Task { Task {
await self.runtimeEnv?.stop() await self.runtimeEnv?.submitCommand(command: .stop(completion: {
completionHandler() SDLLogger.log("[PacketTunnelProvider] sleep")
}))
} }
completionHandler()
} }
override func wake() { override func wake() {
SDLLogger.log("[PacketTunnelProvider] wake up!!!!!!!") SDLLogger.log("[PacketTunnelProvider] wake up!!!!!!!")
// monitor
let monitor = SDLPathMonitor()
//
monitor.start()
SDLLogger.log("[PacketTunnelProvider] 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("[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? { 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 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()
}
}

View File

@ -14,13 +14,6 @@ import NIOCore
1. rsa的加解密逻辑 1. rsa的加解密逻辑
*/ */
actor SDLContextActor { actor SDLContextActor {
enum ReadyState {
case idle
case starting
case ready
case failed(any Error)
case stopped
}
private enum UDPHoleKind: Equatable { private enum UDPHoleKind: Equatable {
case v4 case v4
@ -36,8 +29,6 @@ actor SDLContextActor {
} }
} }
private var readyState: ReadyState = .idle
var config: SDLConfiguration var config: SDLConfiguration
// nat // nat
var natType: SDLNATProberActor.NatType = .blocked var natType: SDLNATProberActor.NatType = .blocked
@ -126,11 +117,6 @@ actor SDLContextActor {
} }
public func start() async { public func start() async {
guard case .idle = self.readyState else {
return
}
self.readyState = .starting
await self.startRuntime(resetNotifier: true) 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 // 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 {
@ -211,6 +183,7 @@ actor SDLContextActor {
group.addTask { group.addTask {
for await event in quicClient.eventStream { for await event in quicClient.eventStream {
try Task.checkCancellation()
switch event { switch event {
case .ready: case .ready:
readyContinuation.yield() readyContinuation.yield()
@ -262,13 +235,14 @@ actor SDLContextActor {
SDLLogger.log("[SDLContext] quic welcome: \(welcome)") SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
// //
await self.doRegisterSuper() await self.doRegisterSuper()
SDLLogger.log("[SDLContext] quic doRegisterSuper")
// //
self.registerTask = Task { self.registerTask = Task {
do { do {
try await Task.sleep(for: .seconds(5)) try await Task.sleep(for: .seconds(5))
try Task.checkCancellation() try Task.checkCancellation()
// Tunnel // Tunnel
self.publishTunnelEvent(message: "校验失败") self.publishTunnelEvent(message: "校验失败")
// 退 // 退
@ -297,7 +271,7 @@ actor SDLContextActor {
self.handleRegisterSuperNak(nakPacket: registerSuperNak) self.handleRegisterSuperNak(nakPacket: registerSuperNak)
case .peerInfo(let peerInfo): 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) await self.puncherActor.handlePeerInfo(using: self.udpHole, udpHoleV6: self.udpHoleV6, peerInfo: peerInfo)
case .event(let event): case .event(let event):
await self.handleEvent(event: event) await self.handleEvent(event: event)
@ -305,7 +279,7 @@ actor SDLContextActor {
// //
await self.identifyStore.applyPolicyResponse(policyResponse) await self.identifyStore.applyPolicyResponse(policyResponse)
case .arpResponse(let arpResponse): 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) await self.arpServer.handleArpResponse(arpResponse: arpResponse)
} }
} }
@ -384,7 +358,9 @@ actor SDLContextActor {
self.udpHoleWorkers = [messageTask] self.udpHoleWorkers = [messageTask]
// nat // nat
await self.probeNatType() Task {
await self.probeNatType()
}
return udpHole return udpHole
} }
@ -413,7 +389,6 @@ actor SDLContextActor {
// context // context
public func stop() async { public func stop() async {
self.readyState = .stopped
await self.stopRuntime() await self.stopRuntime()
} }

View 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()
}
}