fix Context
This commit is contained in:
parent
af140f7da6
commit
3a6b04aa9b
@ -41,6 +41,8 @@ class PacketTunnelProvider: NEPacketTunnelProvider {
|
||||
|
||||
self.contextActor = SDLContextActor(provider: self, config: config, rsaCipher: rsaCipher)
|
||||
await self.contextActor?.start()
|
||||
try await self.contextActor?.waitForReady()
|
||||
|
||||
completionHandler(nil)
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,7 +19,17 @@ actor SDLContextActor {
|
||||
case registered
|
||||
}
|
||||
|
||||
enum ReadyState {
|
||||
case idle
|
||||
case starting
|
||||
case ready
|
||||
case failed(any Error)
|
||||
case stopped
|
||||
}
|
||||
|
||||
private var state: State = .unregistered
|
||||
private var readyState: ReadyState = .idle
|
||||
private var readyWaiters: [CheckedContinuation<Void, Error>] = []
|
||||
|
||||
var config: SDLConfiguration
|
||||
// nat的网络类型
|
||||
@ -103,6 +113,11 @@ actor SDLContextActor {
|
||||
}
|
||||
|
||||
public func start() async {
|
||||
guard case .idle = self.readyState else {
|
||||
return
|
||||
}
|
||||
|
||||
self.readyState = .starting
|
||||
self.startMonitor()
|
||||
|
||||
// 启动arp的定时清理任务
|
||||
@ -133,6 +148,21 @@ actor SDLContextActor {
|
||||
}
|
||||
}
|
||||
|
||||
public func waitForReady() async throws {
|
||||
switch self.readyState {
|
||||
case .ready:
|
||||
return
|
||||
case .failed(let error):
|
||||
throw error
|
||||
case .stopped:
|
||||
throw CancellationError()
|
||||
case .idle, .starting:
|
||||
try await withCheckedThrowingContinuation { continuation in
|
||||
self.readyWaiters.append(continuation)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 取消出口节点的时候,ip地址为: 0.0.0.0
|
||||
public func updateExitNode(exitNodeIp: String) async throws {
|
||||
if let ip = SDLUtil.ipv4StrToInt32(exitNodeIp), ip > 0 {
|
||||
@ -338,6 +368,9 @@ actor SDLContextActor {
|
||||
|
||||
// 处理context的停止问题
|
||||
public func stop() async {
|
||||
self.resumeReadyWaiters(.failure(CancellationError()))
|
||||
self.readyState = .stopped
|
||||
|
||||
await self.supervisor.stop()
|
||||
|
||||
self.udpHoleWorkers?.forEach { $0.cancel() }
|
||||
@ -427,7 +460,9 @@ actor SDLContextActor {
|
||||
// 需要对数据通过rsa的私钥解码
|
||||
guard let key = try? self.rsaCipher.decode(data: Data(registerSuperAck.key)) else {
|
||||
SDLLogger.log("[SDLContext] registerSuperAck invalid key")
|
||||
self.provider.cancelTunnelWithError(SDLError.invalidKey)
|
||||
let error = SDLError.invalidKey
|
||||
self.failReady(error)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
return
|
||||
}
|
||||
|
||||
@ -442,7 +477,9 @@ actor SDLContextActor {
|
||||
self.dataCipher = CCChaCha20Cipher(regionId: regionId, keyData: key)
|
||||
default:
|
||||
SDLLogger.log("[SDLContext] registerSuperAck invalid algorithm \(algorithm)")
|
||||
self.provider.cancelTunnelWithError(SDLError.unsupportedAlgorithm(algorithm: algorithm))
|
||||
let error = SDLError.unsupportedAlgorithm(algorithm: algorithm)
|
||||
self.failReady(error)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
return
|
||||
}
|
||||
|
||||
@ -453,8 +490,10 @@ actor SDLContextActor {
|
||||
SDLLogger.log("[SDLContext] setNetworkSettings successed")
|
||||
self.state = .registered
|
||||
self.startReader()
|
||||
self.markReady()
|
||||
} catch let err {
|
||||
SDLLogger.log("[SDLContext] setTunnelNetworkSettings get error: \(err)")
|
||||
self.failReady(err)
|
||||
self.provider.cancelTunnelWithError(err)
|
||||
}
|
||||
}
|
||||
@ -471,6 +510,7 @@ actor SDLContextActor {
|
||||
self.noticeClient?.send(data: alertNotice)
|
||||
// 报告错误并退出
|
||||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -1)
|
||||
self.failReady(error)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
|
||||
case .noIpAddress, .networkFault, .internalFault:
|
||||
@ -504,6 +544,7 @@ actor SDLContextActor {
|
||||
|
||||
// 报告错误并退出
|
||||
let error = NSError(domain: "com.jihe.punchnet.tun", code: -2)
|
||||
self.failReady(error)
|
||||
self.provider.cancelTunnelWithError(error)
|
||||
case .none:
|
||||
()
|
||||
@ -911,6 +952,39 @@ actor SDLContextActor {
|
||||
return ipv4DnsServers.map { NEIPv4Route(destinationAddress: $0, subnetMask: "255.255.255.255") }
|
||||
}
|
||||
|
||||
private func markReady() {
|
||||
guard case .starting = self.readyState else {
|
||||
return
|
||||
}
|
||||
|
||||
self.readyState = .ready
|
||||
self.resumeReadyWaiters(.success(()))
|
||||
}
|
||||
|
||||
private func failReady(_ error: any Error) {
|
||||
switch self.readyState {
|
||||
case .ready, .failed, .stopped:
|
||||
return
|
||||
case .idle, .starting:
|
||||
self.readyState = .failed(error)
|
||||
self.resumeReadyWaiters(.failure(error))
|
||||
}
|
||||
}
|
||||
|
||||
private func resumeReadyWaiters(_ result: Result<Void, any Error>) {
|
||||
let waiters = self.readyWaiters
|
||||
self.readyWaiters.removeAll()
|
||||
|
||||
waiters.forEach { continuation in
|
||||
switch result {
|
||||
case .success:
|
||||
continuation.resume()
|
||||
case .failure(let error):
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
self.udpHole = nil
|
||||
self.dnsClient = nil
|
||||
|
||||
@ -17,6 +17,18 @@ extension SDLAPIClient {
|
||||
let identityId: UInt32
|
||||
let resourceList: [Resource]
|
||||
let nodeList: [Node]
|
||||
let exitNodeList: [ExitNode]
|
||||
|
||||
struct ExitNode: Codable {
|
||||
let uuid = UUID().uuidString
|
||||
let nnid: Int
|
||||
let nodeName: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case nnid = "node_id"
|
||||
case nodeName = "node_name"
|
||||
}
|
||||
}
|
||||
|
||||
// 资源列表
|
||||
struct Resource: Codable {
|
||||
@ -85,6 +97,7 @@ extension SDLAPIClient {
|
||||
case identityId = "identity_id"
|
||||
case resourceList = "resource_list"
|
||||
case nodeList = "node_list"
|
||||
case exitNodeList = "exit_node"
|
||||
}
|
||||
|
||||
func getNode(id: Int?) -> Node? {
|
||||
|
||||
@ -10,17 +10,6 @@ extension SDLAPIClient {
|
||||
|
||||
// 登陆后的网络会话信息
|
||||
struct NetworkSession: Codable {
|
||||
struct ExitNode: Codable {
|
||||
let uuid = UUID().uuidString
|
||||
let nnid: Int
|
||||
let nodeName: String
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case nnid = "node_id"
|
||||
case nodeName = "node_name"
|
||||
}
|
||||
}
|
||||
|
||||
let accessToken: String
|
||||
let username: String
|
||||
let userType: String
|
||||
@ -28,7 +17,6 @@ extension SDLAPIClient {
|
||||
let networkId: Int
|
||||
let networkName: String
|
||||
let networkDomain: String
|
||||
let exitNodes: [ExitNode]
|
||||
|
||||
// TODO
|
||||
var networkUrl: String {
|
||||
@ -43,7 +31,6 @@ extension SDLAPIClient {
|
||||
case networkId = "network_id"
|
||||
case networkName = "network_name"
|
||||
case networkDomain = "network_domain"
|
||||
case exitNodes = "exit_node"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -10,7 +10,7 @@ struct SettingsNetworkView: View {
|
||||
@Environment(AppContext.self) var appContext: AppContext
|
||||
@Environment(\.openURL) var openURL
|
||||
|
||||
@State private var selectedExitNode: SDLAPIClient.NetworkSession.ExitNode?
|
||||
@State private var selectedExitNode: SDLAPIClient.NetworkContext.ExitNode?
|
||||
|
||||
var body: some View {
|
||||
ScrollView(.vertical, showsIndicators: false) {
|
||||
@ -73,7 +73,7 @@ struct SettingsNetworkView: View {
|
||||
Spacer()
|
||||
|
||||
Menu {
|
||||
ForEach(networkSession.exitNodes, id: \.uuid) { node in
|
||||
ForEach(appContext.networkContext?.exitNodeList ?? [], id: \.uuid) { node in
|
||||
Button {
|
||||
self.selectedExitNode = node
|
||||
} label: {
|
||||
@ -113,7 +113,7 @@ struct SettingsNetworkView: View {
|
||||
.frame(maxWidth: 600, alignment: .leading)
|
||||
}
|
||||
.onAppear {
|
||||
self.selectedExitNode = self.appContext.networkSession?.exitNodes.first
|
||||
self.selectedExitNode = self.appContext.networkContext?.exitNodeList.first
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user