修复休眠恢复的问题
This commit is contained in:
parent
d3f5d7388f
commit
e10329ba2a
@ -29,23 +29,20 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let rsaCipher = try! CCRSACipher(keySize: 1024)
|
let rsaCipher = try! CCRSACipher(keySize: 1024)
|
||||||
self.runtimeEnv = SDLRuntimeEnvironment(config: config, rsaCipher: rsaCipher)
|
self.runtimeEnv = SDLRuntimeEnvironment(config: config, rsaCipher: rsaCipher, provider: self)
|
||||||
Task {
|
Task {
|
||||||
do {
|
await self.runtimeEnv?.submitCommand(command: .start(completion: { err in
|
||||||
try await self.runtimeEnv?.start(provider: self)
|
|
||||||
completionHandler(nil)
|
|
||||||
} catch let err {
|
|
||||||
completionHandler(err)
|
completionHandler(err)
|
||||||
}
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||||
// Add code here to start the process of stopping the tunnel.
|
// Add code here to start the process of stopping the tunnel.
|
||||||
Task {
|
Task {
|
||||||
await self.runtimeEnv?.stop()
|
await self.runtimeEnv?.submitCommand(command: .stop(completion: {
|
||||||
completionHandler()
|
completionHandler()
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,37 +67,26 @@ 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.
|
||||||
Task {
|
Task {
|
||||||
await self.runtimeEnv?.stop()
|
await self.runtimeEnv?.submitCommand(command: .stop(completion: {
|
||||||
completionHandler()
|
SDLLogger.log("[PacketTunnelProvider] sleep")
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
completionHandler()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func wake() {
|
override func wake() {
|
||||||
SDLLogger.log("[PacketTunnelProvider] wake up!!!!!!!")
|
SDLLogger.log("[PacketTunnelProvider] wake up!!!!!!!")
|
||||||
// 启动monitor
|
|
||||||
let monitor = SDLPathMonitor()
|
|
||||||
// 启动监视器,允许重入
|
|
||||||
monitor.start()
|
|
||||||
SDLLogger.log("[PacketTunnelProvider] monitor started")
|
|
||||||
|
|
||||||
// Add code here to wake up.
|
// Add code here to wake up.
|
||||||
Task {
|
Task {
|
||||||
|
|
||||||
defer {
|
|
||||||
monitor.stop()
|
|
||||||
}
|
|
||||||
|
|
||||||
// 等待网络可达
|
|
||||||
_ = await monitor.statusStream().first {$0 == .satisfied}
|
|
||||||
SDLLogger.log("[PacketTunnelProvider] network is satisfied")
|
|
||||||
// 重新启动
|
// 重新启动
|
||||||
try await self.runtimeEnv?.start(provider: self)
|
await self.runtimeEnv?.submitCommand(command: .start(completion: { err in
|
||||||
|
SDLLogger.log("[PacketTunnelProvider] wakeup and try start")
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private func handleAppRequest(message: AppRequest) async throws -> Data? {
|
private func handleAppRequest(message: AppRequest) async throws -> Data? {
|
||||||
guard let contextActor = self.runtimeEnv?.getContextActor() else {
|
guard let contextActor = await self.runtimeEnv?.getContextActor() else {
|
||||||
throw TunnelError.invalidContext
|
throw TunnelError.invalidContext
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,146 +116,3 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private class SDLRuntimeEnvironment {
|
|
||||||
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()
|
|
||||||
|
|
||||||
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.withStateLock {
|
|
||||||
self.contextActor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func stop() async {
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|||||||
@ -14,13 +14,6 @@ import NIOCore
|
|||||||
1. 处理rsa的加解密逻辑
|
1. 处理rsa的加解密逻辑
|
||||||
*/
|
*/
|
||||||
actor SDLContextActor {
|
actor SDLContextActor {
|
||||||
enum ReadyState {
|
|
||||||
case idle
|
|
||||||
case starting
|
|
||||||
case ready
|
|
||||||
case failed(any Error)
|
|
||||||
case stopped
|
|
||||||
}
|
|
||||||
|
|
||||||
private enum UDPHoleKind: Equatable {
|
private enum UDPHoleKind: Equatable {
|
||||||
case v4
|
case v4
|
||||||
@ -36,8 +29,6 @@ actor SDLContextActor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private var readyState: ReadyState = .idle
|
|
||||||
|
|
||||||
var config: SDLConfiguration
|
var config: SDLConfiguration
|
||||||
// nat的网络类型
|
// nat的网络类型
|
||||||
var natType: SDLNATProberActor.NatType = .blocked
|
var natType: SDLNATProberActor.NatType = .blocked
|
||||||
@ -126,11 +117,6 @@ actor SDLContextActor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public func start() async {
|
public func start() async {
|
||||||
guard case .idle = self.readyState else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
self.readyState = .starting
|
|
||||||
await self.startRuntime(resetNotifier: true)
|
await self.startRuntime(resetNotifier: true)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,20 +150,6 @@ actor SDLContextActor {
|
|||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
public func sleep() async {
|
|
||||||
SDLLogger.log("[SDLContext] sleep")
|
|
||||||
await self.stopRuntime()
|
|
||||||
}
|
|
||||||
|
|
||||||
public func wake() async {
|
|
||||||
SDLLogger.log("[SDLContext] wakeup")
|
|
||||||
|
|
||||||
// 先尝试停止
|
|
||||||
await self.stopRuntime()
|
|
||||||
// 重新启动
|
|
||||||
await self.startRuntime(resetNotifier: false)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 取消出口节点的时候,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 {
|
||||||
@ -211,6 +183,7 @@ actor SDLContextActor {
|
|||||||
|
|
||||||
group.addTask {
|
group.addTask {
|
||||||
for await event in quicClient.eventStream {
|
for await event in quicClient.eventStream {
|
||||||
|
try Task.checkCancellation()
|
||||||
switch event {
|
switch event {
|
||||||
case .ready:
|
case .ready:
|
||||||
readyContinuation.yield()
|
readyContinuation.yield()
|
||||||
@ -262,6 +235,7 @@ actor SDLContextActor {
|
|||||||
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
|
SDLLogger.log("[SDLContext] quic welcome: \(welcome)")
|
||||||
// 注册
|
// 注册
|
||||||
await self.doRegisterSuper()
|
await self.doRegisterSuper()
|
||||||
|
SDLLogger.log("[SDLContext] quic doRegisterSuper")
|
||||||
|
|
||||||
// 任务取消机制
|
// 任务取消机制
|
||||||
self.registerTask = Task {
|
self.registerTask = Task {
|
||||||
@ -297,7 +271,7 @@ actor SDLContextActor {
|
|||||||
|
|
||||||
self.handleRegisterSuperNak(nakPacket: registerSuperNak)
|
self.handleRegisterSuperNak(nakPacket: registerSuperNak)
|
||||||
case .peerInfo(let peerInfo):
|
case .peerInfo(let peerInfo):
|
||||||
//SDLLogger.shared.log("[SDLContext] peer message: \(peerInfo)")
|
SDLLogger.log("[SDLContext] peer message: \(peerInfo)")
|
||||||
await self.puncherActor.handlePeerInfo(using: self.udpHole, udpHoleV6: self.udpHoleV6, peerInfo: peerInfo)
|
await self.puncherActor.handlePeerInfo(using: self.udpHole, udpHoleV6: self.udpHoleV6, peerInfo: peerInfo)
|
||||||
case .event(let event):
|
case .event(let event):
|
||||||
await self.handleEvent(event: event)
|
await self.handleEvent(event: event)
|
||||||
@ -305,7 +279,7 @@ actor SDLContextActor {
|
|||||||
// 处理权限的请求问题
|
// 处理权限的请求问题
|
||||||
await self.identifyStore.applyPolicyResponse(policyResponse)
|
await self.identifyStore.applyPolicyResponse(policyResponse)
|
||||||
case .arpResponse(let arpResponse):
|
case .arpResponse(let arpResponse):
|
||||||
//SDLLogger.shared.log("[SDLContext] get arp response: \(arpResponse)")
|
SDLLogger.log("[SDLContext] get arp response: \(arpResponse)")
|
||||||
await self.arpServer.handleArpResponse(arpResponse: arpResponse)
|
await self.arpServer.handleArpResponse(arpResponse: arpResponse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -384,7 +358,9 @@ actor SDLContextActor {
|
|||||||
self.udpHoleWorkers = [messageTask]
|
self.udpHoleWorkers = [messageTask]
|
||||||
|
|
||||||
// 开始探测nat的类型
|
// 开始探测nat的类型
|
||||||
await self.probeNatType()
|
Task {
|
||||||
|
await self.probeNatType()
|
||||||
|
}
|
||||||
|
|
||||||
return udpHole
|
return udpHole
|
||||||
}
|
}
|
||||||
@ -413,7 +389,6 @@ actor SDLContextActor {
|
|||||||
|
|
||||||
// 处理context的停止问题
|
// 处理context的停止问题
|
||||||
public func stop() async {
|
public func stop() async {
|
||||||
self.readyState = .stopped
|
|
||||||
await self.stopRuntime()
|
await self.stopRuntime()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
117
Tun/SDLRuntimeEnvironment.swift
Normal file
117
Tun/SDLRuntimeEnvironment.swift
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
import Foundation
|
||||||
|
|
||||||
|
enum SDLRuntimeEnvironmentCommand {
|
||||||
|
case start(completion: @Sendable (Error?) -> Void)
|
||||||
|
case stop(completion: @Sendable () -> Void)
|
||||||
|
}
|
||||||
|
|
||||||
|
actor SDLRuntimeEnvironment {
|
||||||
|
private enum State {
|
||||||
|
case idle
|
||||||
|
case running
|
||||||
|
}
|
||||||
|
|
||||||
|
private var state: State = .idle
|
||||||
|
private var contextActor: SDLContextActor?
|
||||||
|
|
||||||
|
private var config: SDLConfiguration
|
||||||
|
private let rsaCipher: CCRSACipher
|
||||||
|
private let provider: PacketTunnelProvider
|
||||||
|
|
||||||
|
private let commandStream: AsyncStream<SDLRuntimeEnvironmentCommand>
|
||||||
|
private let commandCont: AsyncStream<SDLRuntimeEnvironmentCommand>.Continuation
|
||||||
|
|
||||||
|
private var commandTask: Task<Void, Never>?
|
||||||
|
|
||||||
|
init(config: SDLConfiguration, rsaCipher: CCRSACipher, provider: PacketTunnelProvider) {
|
||||||
|
self.config = config
|
||||||
|
self.rsaCipher = rsaCipher
|
||||||
|
self.provider = provider
|
||||||
|
|
||||||
|
let pair = AsyncStream.makeStream(of: SDLRuntimeEnvironmentCommand.self)
|
||||||
|
self.commandStream = pair.stream
|
||||||
|
self.commandCont = pair.continuation
|
||||||
|
}
|
||||||
|
|
||||||
|
func submitCommand(command: SDLRuntimeEnvironmentCommand) {
|
||||||
|
self.commandCont.yield(command)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getContextActor() -> SDLContextActor? {
|
||||||
|
self.contextActor
|
||||||
|
}
|
||||||
|
|
||||||
|
func run() {
|
||||||
|
let stream = self.commandStream
|
||||||
|
|
||||||
|
self.commandTask = Task { [weak self] in
|
||||||
|
for await command in stream {
|
||||||
|
guard let self else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
await self.handle(command)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handle(_ command: SDLRuntimeEnvironmentCommand) async {
|
||||||
|
switch command {
|
||||||
|
case .start(let handler):
|
||||||
|
do {
|
||||||
|
try await self.startCommand()
|
||||||
|
handler(nil)
|
||||||
|
} catch {
|
||||||
|
handler(error)
|
||||||
|
}
|
||||||
|
|
||||||
|
case .stop(let handler):
|
||||||
|
await self.stopCommand()
|
||||||
|
handler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func startCommand() async throws {
|
||||||
|
switch self.state {
|
||||||
|
case .idle:
|
||||||
|
SDLTunnelAppNotifier.shared.clear()
|
||||||
|
|
||||||
|
let contextActor = SDLContextActor(
|
||||||
|
provider: provider,
|
||||||
|
config: config,
|
||||||
|
rsaCipher: self.rsaCipher
|
||||||
|
)
|
||||||
|
|
||||||
|
self.contextActor = contextActor
|
||||||
|
await contextActor.start()
|
||||||
|
self.state = .running
|
||||||
|
case .running:
|
||||||
|
SDLLogger.log("[SDLRuntimeEnvironment] is running, ignore start command")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func stopCommand() async {
|
||||||
|
switch self.state {
|
||||||
|
case .idle:
|
||||||
|
SDLLogger.log("[SDLRuntimeEnvironment] is idle, ignore stop command")
|
||||||
|
|
||||||
|
case .running:
|
||||||
|
let contextActor = self.contextActor
|
||||||
|
self.contextActor = nil
|
||||||
|
self.state = .idle
|
||||||
|
|
||||||
|
await contextActor?.stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func shutdown() {
|
||||||
|
self.commandCont.finish()
|
||||||
|
self.commandTask?.cancel()
|
||||||
|
self.commandTask = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
self.commandCont.finish()
|
||||||
|
self.commandTask?.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user