fix sleep and wakeup

This commit is contained in:
anlicheng 2026-04-28 10:39:17 +08:00
parent 7ce880f3dc
commit 337fa37b05
5 changed files with 92 additions and 12 deletions

View File

@ -83,11 +83,17 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
override func sleep(completionHandler: @escaping () -> Void) {
// Add code here to get ready to sleep.
completionHandler()
Task {
await self.contextActor?.sleep()
completionHandler()
}
}
override func wake() {
// Add code here to wake up.
Task {
await self.contextActor?.wake()
}
}
private func handleAppRequest(message: AppRequest) async throws -> Data? {

View File

@ -67,6 +67,7 @@ actor ArpServer {
func clear() {
self.known_macs = [:]
self.coolingDown = [:]
}
func arpRequest(targetIp: UInt32, use quicClient: SDLQUICClient?) throws {

View File

@ -22,6 +22,14 @@ actor SDLContextActor {
case stopped
}
private enum RuntimeState {
case idle
case running
case sleeping
case waking
case stopped
}
private enum UDPHoleKind: Equatable {
case v4
case v6
@ -37,6 +45,7 @@ actor SDLContextActor {
}
private var readyState: ReadyState = .idle
private var runtimeState: RuntimeState = .idle
private var readyWaiters: [CheckedContinuation<Void, Error>] = []
var config: SDLConfiguration
@ -139,7 +148,14 @@ actor SDLContextActor {
}
self.readyState = .starting
self.prepareTunnelNotifier()
self.runtimeState = .running
await self.startRuntime(resetNotifier: true)
}
private func startRuntime(resetNotifier: Bool) async {
if resetNotifier {
self.prepareTunnelNotifier()
}
self.startMonitor()
// arp
@ -171,6 +187,38 @@ actor SDLContextActor {
// }
}
public func sleep() async {
guard self.runtimeState != .stopped else {
return
}
SDLLogger.log("[SDLContext] sleep")
self.runtimeState = .sleeping
await self.stopRuntime(clearCaches: true)
}
public func wake() async {
switch self.runtimeState {
case .stopped, .waking:
return
case .running:
await self.stopRuntime(clearCaches: true)
guard case .running = self.runtimeState else {
return
}
case .idle, .sleeping:
break
}
SDLLogger.log("[SDLContext] wake")
self.runtimeState = .waking
await self.startRuntime(resetNotifier: false)
guard case .waking = self.runtimeState else {
return
}
self.runtimeState = .running
}
public func waitForReady() async throws {
switch self.readyState {
case .ready:
@ -391,10 +439,21 @@ actor SDLContextActor {
public func stop() async {
self.resumeReadyWaiters(.failure(CancellationError()))
self.readyState = .stopped
self.runtimeState = .stopped
await self.stopRuntime(clearCaches: true)
}
private func stopRuntime(clearCaches: Bool) async {
self.superRegistrationStateMachine.reset()
await self.supervisor.stop()
await self.puncherActor.stop()
await self.arpServer.clear()
await self.sessionManager.clear()
if clearCaches {
self.flowSessionManager.clear()
}
self.udpHoleWorkers?.forEach { $0.cancel() }
self.udpHoleWorkers = nil
@ -442,6 +501,7 @@ actor SDLContextActor {
self.sessionToken = nil
self.dataCipher = nil
self.natType = .blocked
await self.ipv6AssistClient?.stop()
self.ipv6AssistClient = nil

View File

@ -89,6 +89,15 @@ final class SDLFlowSessionManager {
sessions.removeValue(forKey: key)
}
func clear() {
lock.lock()
defer {
lock.unlock()
}
sessions.removeAll()
}
//
func cleanupExpiredSessions() {
lock.lock()

View File

@ -84,6 +84,10 @@ actor SessionManager {
self.sessions.removeValue(forKey: dstMac)
}
func clear() {
self.sessions.removeAll()
}
private func selectSession(in sessions: [Session.AddressType: Session]) -> Session? {
return sessions.values.max(by: { $0.lastTimestamp < $1.lastTimestamp })
}