修复休眠恢复的问题
This commit is contained in:
parent
5b10f7de61
commit
d3f5d7388f
@ -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
|
||||||
|
case running
|
||||||
|
case stopping
|
||||||
|
}
|
||||||
|
|
||||||
init(options: [String: NSObject]) {
|
private let stateLock = NSLock()
|
||||||
self.options = options
|
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()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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,
|
||||||
|
|||||||
@ -7,6 +7,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import Observation
|
import Observation
|
||||||
|
|
||||||
|
@MainActor
|
||||||
@Observable
|
@Observable
|
||||||
final class NetworkModel {
|
final class NetworkModel {
|
||||||
@ObservationIgnored
|
@ObservationIgnored
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user