修复休眠恢复的问题

This commit is contained in:
anlicheng 2026-05-03 21:27:20 +08:00
parent 5b10f7de61
commit d3f5d7388f
4 changed files with 132 additions and 29 deletions

View File

@ -5,6 +5,7 @@
// Created by on 2025/8/3. // Created by on 2025/8/3.
// //
import Foundation
import NetworkExtension import NetworkExtension
enum TunnelError: Error { enum TunnelError: Error {
@ -22,12 +23,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
return return
} }
guard let options else { guard let options, let config = SDLConfiguration.parse(options: options) else {
completionHandler(TunnelError.invalidConfiguration) completionHandler(TunnelError.invalidConfiguration)
return return
} }
self.runtimeEnv = SDLRuntimeEnvironment(options: options) let rsaCipher = try! CCRSACipher(keySize: 1024)
self.runtimeEnv = SDLRuntimeEnvironment(config: config, rsaCipher: rsaCipher)
Task { Task {
do { do {
try await self.runtimeEnv?.start(provider: self) try await self.runtimeEnv?.start(provider: self)
@ -130,35 +132,144 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
} }
private class SDLRuntimeEnvironment { private class SDLRuntimeEnvironment {
var contextActor: SDLContextActor? private enum State {
private var options: [String: NSObject] case idle
case starting
init(options: [String: NSObject]) { case running
self.options = options 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 { func start(provider: PacketTunnelProvider) async throws {
guard self.markStarting(provider: provider) else {
return
}
// //
SDLTunnelAppNotifier.shared.clear() SDLTunnelAppNotifier.shared.clear()
guard let config = await SDLConfiguration.parse(options: options) else { let contextActor = SDLContextActor(provider: provider, config: config, rsaCipher: self.rsaCipher)
throw TunnelError.invalidConfiguration
}
//
let rsaCipher = try! CCRSACipher(keySize: 1024)
let contextActor = SDLContextActor(provider: provider, config: config, rsaCipher: rsaCipher)
self.contextActor = contextActor
await contextActor.start() await contextActor.start()
let shouldStop = self.markStarted(contextActor: contextActor)
if shouldStop {
await self.stop()
}
} }
func getContextActor() -> SDLContextActor? { func getContextActor() -> SDLContextActor? {
return self.contextActor return self.withStateLock {
self.contextActor
}
} }
func stop() async { func stop() async {
await self.contextActor?.stop() guard let contextActor = self.markStopping() else {
self.contextActor = nil 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

@ -323,7 +323,7 @@ actor SDLContextActor {
self.dnsWorker = nil self.dnsWorker = nil
// dns // dns
let dnsClient = DNSCloudClient(host: self.config.serverIp, port: 15353) let dnsClient = DNSCloudClient(host: self.config.serverHost, port: 15353)
await dnsClient.start() await dnsClient.start()
SDLLogger.log("[SDLContext] dnsClient started") SDLLogger.log("[SDLContext] dnsClient started")
self.dnsClient = dnsClient self.dnsClient = dnsClient

View File

@ -49,7 +49,6 @@ public class SDLConfiguration {
let version: Int let version: Int
let serverHost: String let serverHost: String
let serverIp: String
let stunServers: [String] let stunServers: [String]
lazy var stunSocketAddress: SocketAddress = { lazy var stunSocketAddress: SocketAddress = {
@ -77,7 +76,6 @@ public class SDLConfiguration {
public init(version: Int, public init(version: Int,
serverHost: String, serverHost: String,
serverIp: String,
stunServers: [String], stunServers: [String],
clientId: String, clientId: String,
networkAddress: NetworkAddress, networkAddress: NetworkAddress,
@ -87,7 +85,6 @@ public class SDLConfiguration {
exitNode: ExitNode?) { exitNode: ExitNode?) {
self.version = version self.version = version
self.serverHost = serverHost self.serverHost = serverHost
self.serverIp = serverIp
self.stunServers = stunServers self.stunServers = stunServers
self.clientId = clientId self.clientId = clientId
self.networkAddress = networkAddress self.networkAddress = networkAddress
@ -102,7 +99,7 @@ public class SDLConfiguration {
// //
extension SDLConfiguration { extension SDLConfiguration {
static func parse(options: [String: NSObject]) async -> SDLConfiguration? { static func parse(options: [String: NSObject]) -> SDLConfiguration? {
guard let version = options["version"] as? Int, guard let version = options["version"] as? Int,
let serverHost = options["server_host"] as? String, let serverHost = options["server_host"] as? String,
let stunAssistHost = options["stun_assist_host"] as? String, let stunAssistHost = options["stun_assist_host"] as? String,
@ -118,11 +115,6 @@ extension SDLConfiguration {
return nil return nil
} }
// dns
guard let serverIp = await SDLUtil.resolveHostname(host: serverHost) else {
return nil
}
// //
var exitNode: ExitNode? = nil var exitNode: ExitNode? = nil
if let exitNodeIpStr = options["exit_node_ip"] as? String, let exitNodeIp = SDLUtil.ipv4StrToInt32(exitNodeIpStr) { if let exitNodeIpStr = options["exit_node_ip"] as? String, let exitNodeIp = SDLUtil.ipv4StrToInt32(exitNodeIpStr) {
@ -131,7 +123,6 @@ extension SDLConfiguration {
return SDLConfiguration(version: version, return SDLConfiguration(version: version,
serverHost: serverHost, serverHost: serverHost,
serverIp: serverIp,
stunServers: [serverHost, stunAssistHost], stunServers: [serverHost, stunAssistHost],
clientId: clientId, clientId: clientId,
networkAddress: networkAddress, networkAddress: networkAddress,

View File

@ -7,6 +7,7 @@
import Foundation import Foundation
import Observation import Observation
@MainActor
@Observable @Observable
final class NetworkModel { final class NetworkModel {
@ObservationIgnored @ObservationIgnored