修复休眠恢复的问题

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.
//
import Foundation
import NetworkExtension
enum TunnelError: Error {
@ -22,12 +23,13 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
return
}
guard let options else {
guard let options, let config = SDLConfiguration.parse(options: options) else {
completionHandler(TunnelError.invalidConfiguration)
return
}
self.runtimeEnv = SDLRuntimeEnvironment(options: options)
let rsaCipher = try! CCRSACipher(keySize: 1024)
self.runtimeEnv = SDLRuntimeEnvironment(config: config, rsaCipher: rsaCipher)
Task {
do {
try await self.runtimeEnv?.start(provider: self)
@ -130,35 +132,144 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
}
private class SDLRuntimeEnvironment {
var contextActor: SDLContextActor?
private var options: [String: NSObject]
init(options: [String: NSObject]) {
self.options = options
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()
guard let config = await SDLConfiguration.parse(options: options) else {
throw TunnelError.invalidConfiguration
}
//
let rsaCipher = try! CCRSACipher(keySize: 1024)
let contextActor = SDLContextActor(provider: provider, config: config, rsaCipher: rsaCipher)
self.contextActor = contextActor
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.contextActor
return self.withStateLock {
self.contextActor
}
}
func stop() async {
await self.contextActor?.stop()
self.contextActor = nil
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

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

View File

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

View File

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