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) { override func sleep(completionHandler: @escaping () -> Void) {
// Add code here to get ready to sleep. // Add code here to get ready to sleep.
completionHandler() Task {
await self.contextActor?.sleep()
completionHandler()
}
} }
override func wake() { override func wake() {
// Add code here to wake up. // Add code here to wake up.
Task {
await self.contextActor?.wake()
}
} }
private func handleAppRequest(message: AppRequest) async throws -> Data? { private func handleAppRequest(message: AppRequest) async throws -> Data? {

View File

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

View File

@ -22,6 +22,14 @@ actor SDLContextActor {
case stopped case stopped
} }
private enum RuntimeState {
case idle
case running
case sleeping
case waking
case stopped
}
private enum UDPHoleKind: Equatable { private enum UDPHoleKind: Equatable {
case v4 case v4
case v6 case v6
@ -35,8 +43,9 @@ actor SDLContextActor {
} }
} }
} }
private var readyState: ReadyState = .idle private var readyState: ReadyState = .idle
private var runtimeState: RuntimeState = .idle
private var readyWaiters: [CheckedContinuation<Void, Error>] = [] private var readyWaiters: [CheckedContinuation<Void, Error>] = []
var config: SDLConfiguration var config: SDLConfiguration
@ -139,7 +148,14 @@ actor SDLContextActor {
} }
self.readyState = .starting 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() self.startMonitor()
// arp // 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 { public func waitForReady() async throws {
switch self.readyState { switch self.readyState {
case .ready: case .ready:
@ -201,7 +249,7 @@ actor SDLContextActor {
try await self.waitForReady() 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 {
@ -391,10 +439,21 @@ actor SDLContextActor {
public func stop() async { public func stop() async {
self.resumeReadyWaiters(.failure(CancellationError())) self.resumeReadyWaiters(.failure(CancellationError()))
self.readyState = .stopped self.readyState = .stopped
self.runtimeState = .stopped
await self.stopRuntime(clearCaches: true)
}
private func stopRuntime(clearCaches: Bool) async {
self.superRegistrationStateMachine.reset() self.superRegistrationStateMachine.reset()
await self.supervisor.stop() await self.supervisor.stop()
await self.puncherActor.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?.forEach { $0.cancel() }
self.udpHoleWorkers = nil self.udpHoleWorkers = nil
@ -442,6 +501,7 @@ actor SDLContextActor {
self.sessionToken = nil self.sessionToken = nil
self.dataCipher = nil self.dataCipher = nil
self.natType = .blocked
await self.ipv6AssistClient?.stop() await self.ipv6AssistClient?.stop()
self.ipv6AssistClient = nil self.ipv6AssistClient = nil

View File

@ -29,7 +29,7 @@ struct FlowSession: Hashable {
lhs.dstPort == rhs.dstPort && lhs.dstPort == rhs.dstPort &&
lhs.proto == rhs.proto lhs.proto == rhs.proto
} }
func reverse() -> FlowSession { func reverse() -> FlowSession {
return FlowSession( return FlowSession(
srcIP: dstIP, srcIP: dstIP,
@ -39,7 +39,7 @@ struct FlowSession: Hashable {
proto: proto proto: proto
) )
} }
} }
// MARK: - // MARK: -
@ -68,14 +68,14 @@ final class SDLFlowSessionManager {
defer { defer {
lock.unlock() lock.unlock()
} }
if let expireTs = sessions[key] { if let expireTs = sessions[key] {
if expireTs >= Date().timeIntervalSince1970 { if expireTs >= Date().timeIntervalSince1970 {
return true return true
} }
self.sessions.removeValue(forKey: key) self.sessions.removeValue(forKey: key)
} }
return false return false
} }
@ -89,6 +89,15 @@ final class SDLFlowSessionManager {
sessions.removeValue(forKey: key) sessions.removeValue(forKey: key)
} }
func clear() {
lock.lock()
defer {
lock.unlock()
}
sessions.removeAll()
}
// //
func cleanupExpiredSessions() { func cleanupExpiredSessions() {
lock.lock() lock.lock()

View File

@ -13,7 +13,7 @@ struct Session {
case v4 case v4
case v6 case v6
} }
// ip地址, // ip地址,
let dstMac: Data let dstMac: Data
// nat // nat
@ -30,7 +30,7 @@ struct Session {
self.addressType = addressType self.addressType = addressType
self.lastTimestamp = Int32(Date().timeIntervalSince1970) self.lastTimestamp = Int32(Date().timeIntervalSince1970)
} }
mutating func updateLastTimestamp(_ lastTimestamp: Int32) { mutating func updateLastTimestamp(_ lastTimestamp: Int32) {
self.lastTimestamp = lastTimestamp self.lastTimestamp = lastTimestamp
} }
@ -67,7 +67,7 @@ actor SessionManager {
return session return session
} }
func addSession(session: Session) { func addSession(session: Session) {
let timestamp = Int32(Date().timeIntervalSince1970) let timestamp = Int32(Date().timeIntervalSince1970)
@ -84,6 +84,10 @@ actor SessionManager {
self.sessions.removeValue(forKey: dstMac) self.sessions.removeValue(forKey: dstMac)
} }
func clear() {
self.sessions.removeAll()
}
private func selectSession(in sessions: [Session.AddressType: Session]) -> Session? { private func selectSession(in sessions: [Session.AddressType: Session]) -> Session? {
return sessions.values.max(by: { $0.lastTimestamp < $1.lastTimestamp }) return sessions.values.max(by: { $0.lastTimestamp < $1.lastTimestamp })
} }