fix superClient
This commit is contained in:
parent
3cdf1953bf
commit
1c0ed04fa2
@ -146,7 +146,7 @@ extension SDLConfiguration {
|
||||
guard let networkAddress = parseNetworkAddress(networkAddressDict) else {
|
||||
return nil
|
||||
}
|
||||
let acl = parseACL(options["acl"])
|
||||
let acl = parseACL(options["exposed_service"])
|
||||
|
||||
// 网络出口配置是可选的
|
||||
var exitNode: ExitNode? = nil
|
||||
|
||||
@ -8,20 +8,15 @@
|
||||
import Foundation
|
||||
import Network
|
||||
|
||||
actor SDLSuperClient {
|
||||
enum State {
|
||||
case idle
|
||||
case running
|
||||
case stopped
|
||||
}
|
||||
|
||||
private var state: State = .idle
|
||||
|
||||
final class SDLSuperClient: @unchecked Sendable {
|
||||
private let queue = DispatchQueue(label: "com.sdl.SuperClient.queue") // 专用队列保证线程安全
|
||||
|
||||
// 数据流
|
||||
public let messageStream: AsyncThrowingStream<SDLQUICInboundMessage, Error>
|
||||
private let messageCont: AsyncThrowingStream<SDLQUICInboundMessage, Error>.Continuation
|
||||
private let stateLock = NSLock()
|
||||
private var isStarted = false
|
||||
private var isStopped = false
|
||||
private var isMessageContinuationFinished = false
|
||||
|
||||
private let connection: NWConnection
|
||||
private let maxBufferSize: Int
|
||||
@ -62,7 +57,7 @@ actor SDLSuperClient {
|
||||
}
|
||||
|
||||
func run() async throws {
|
||||
guard self.state == .idle else {
|
||||
guard self.markStarted() else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -114,25 +109,32 @@ actor SDLSuperClient {
|
||||
}
|
||||
|
||||
private func runStateLoop(_ stateStream: AsyncThrowingStream<NWConnection.State, Error>) async throws {
|
||||
do {
|
||||
try await self.waitUntilReady(stateStream)
|
||||
self.connection.stateUpdateHandler = nil
|
||||
try await self.readLoop()
|
||||
} catch is CancellationError {
|
||||
throw CancellationError()
|
||||
} catch let error as SDLSuperError {
|
||||
self.finishMessageStream(throwing: error)
|
||||
throw error
|
||||
} catch {
|
||||
let wrappedError = SDLSuperError.internalError(error)
|
||||
self.finishMessageStream(throwing: wrappedError)
|
||||
throw wrappedError
|
||||
}
|
||||
}
|
||||
|
||||
private func waitUntilReady(_ stateStream: AsyncThrowingStream<NWConnection.State, Error>) async throws {
|
||||
for try await state in stateStream {
|
||||
try Task.checkCancellation()
|
||||
|
||||
switch state {
|
||||
case .ready:
|
||||
self.state = .running
|
||||
try await self.readLoop()
|
||||
if case .ready = state {
|
||||
return
|
||||
case .failed(let error):
|
||||
let wrappedError = SDLSuperError.connectionFailed(error)
|
||||
self.messageCont.finish(throwing: wrappedError)
|
||||
throw wrappedError
|
||||
case .cancelled:
|
||||
self.messageCont.finish(throwing: SDLSuperError.connectionCancelled)
|
||||
throw SDLSuperError.connectionCancelled
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
throw SDLSuperError.connectionCancelled
|
||||
}
|
||||
|
||||
private func readLoop() async throws {
|
||||
@ -154,18 +156,18 @@ actor SDLSuperClient {
|
||||
} catch is CancellationError {
|
||||
throw CancellationError()
|
||||
} catch let error as SDLSuperError {
|
||||
self.messageCont.finish(throwing: error)
|
||||
self.finishMessageStream(throwing: error)
|
||||
throw error
|
||||
} catch {
|
||||
let wrappedError = SDLSuperError.internalError(error)
|
||||
self.messageCont.finish(throwing: wrappedError)
|
||||
self.finishMessageStream(throwing: wrappedError)
|
||||
|
||||
throw wrappedError
|
||||
}
|
||||
}
|
||||
|
||||
func send(type: SDLPacketType, data: Data) {
|
||||
guard case .running = state, connection.state == .ready else {
|
||||
guard connection.state == .ready else {
|
||||
return
|
||||
}
|
||||
|
||||
@ -176,10 +178,8 @@ actor SDLSuperClient {
|
||||
|
||||
connection.send(content: packet, completion: .contentProcessed { [weak self] error in
|
||||
if let error {
|
||||
Task {
|
||||
SDLLogger.log("[SDLSuperClient] send data get error: \(error)", for: .debug)
|
||||
self?.messageCont.finish(throwing: SDLSuperError.writeFailed(error))
|
||||
}
|
||||
SDLLogger.log("[SDLSuperClient] send data get error: \(error)", for: .debug)
|
||||
self?.finishMessageStream(throwing: SDLSuperError.writeFailed(error))
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -213,20 +213,65 @@ actor SDLSuperClient {
|
||||
}
|
||||
|
||||
func stop() {
|
||||
guard self.state != .stopped else {
|
||||
guard self.markStopped() else {
|
||||
return
|
||||
}
|
||||
|
||||
self.state = .stopped
|
||||
|
||||
let connection = self.connection
|
||||
connection.stateUpdateHandler = nil
|
||||
connection.cancel()
|
||||
self.messageCont.finish()
|
||||
self.finishMessageStream()
|
||||
|
||||
SDLLogger.log("[SDLSuperClient] stopped")
|
||||
}
|
||||
|
||||
private func markStarted() -> Bool {
|
||||
self.stateLock.lock()
|
||||
defer {
|
||||
self.stateLock.unlock()
|
||||
}
|
||||
|
||||
guard !self.isStarted, !self.isStopped else {
|
||||
return false
|
||||
}
|
||||
|
||||
self.isStarted = true
|
||||
return true
|
||||
}
|
||||
|
||||
private func markStopped() -> Bool {
|
||||
self.stateLock.lock()
|
||||
defer {
|
||||
self.stateLock.unlock()
|
||||
}
|
||||
|
||||
guard !self.isStopped else {
|
||||
return false
|
||||
}
|
||||
|
||||
self.isStopped = true
|
||||
return true
|
||||
}
|
||||
|
||||
private func finishMessageStream(throwing error: Error? = nil) {
|
||||
self.stateLock.lock()
|
||||
let shouldFinish = !self.isMessageContinuationFinished
|
||||
if shouldFinish {
|
||||
self.isMessageContinuationFinished = true
|
||||
}
|
||||
self.stateLock.unlock()
|
||||
|
||||
guard shouldFinish else {
|
||||
return
|
||||
}
|
||||
|
||||
if let error {
|
||||
self.messageCont.finish(throwing: error)
|
||||
} else {
|
||||
self.messageCont.finish()
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
SDLLogger.log("[SDLSuperClient] deinit")
|
||||
}
|
||||
|
||||
@ -32,11 +32,11 @@ final class SDLSuperSession: @unchecked Sendable {
|
||||
}
|
||||
|
||||
func stop() async {
|
||||
await self.client.stop()
|
||||
self.client.stop()
|
||||
}
|
||||
|
||||
func send(type: SDLPacketType, data: Data) async {
|
||||
await self.client.send(type: type, data: data)
|
||||
self.client.send(type: type, data: data)
|
||||
}
|
||||
|
||||
private func runLoops() async throws {
|
||||
@ -74,7 +74,7 @@ final class SDLSuperSession: @unchecked Sendable {
|
||||
while true {
|
||||
try await Task.sleep(for: .seconds(5))
|
||||
try Task.checkCancellation()
|
||||
await self.client.send(type: .ping, data: Data())
|
||||
self.client.send(type: .ping, data: Data())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ class AppContext {
|
||||
accessToken: session.accessToken,
|
||||
identityId: context.identityId,
|
||||
hostname: context.hostname,
|
||||
acl: context.acl,
|
||||
exposedService: context.exposedService,
|
||||
exitNodeIp: self.selectedExitNodeIp
|
||||
)
|
||||
try await self.vpnManager.enableVpn(options: options)
|
||||
|
||||
@ -21,7 +21,7 @@ struct SystemConfig {
|
||||
case prod = "prod"
|
||||
}
|
||||
|
||||
static let env: Env = .dev
|
||||
static let env: Env = .prod
|
||||
|
||||
// 版本设置
|
||||
static let version: Int = 1
|
||||
@ -65,7 +65,7 @@ struct SystemConfig {
|
||||
accessToken: String,
|
||||
identityId: UInt32,
|
||||
hostname: String,
|
||||
acl: NetworkContext.ACL,
|
||||
exposedService: NetworkContext.ExposedService?,
|
||||
exitNodeIp: String?) -> [String: NSObject] {
|
||||
|
||||
let envConfig = getCurrentEnvConfig()
|
||||
@ -81,9 +81,9 @@ struct SystemConfig {
|
||||
"stun_assist_host": envConfig.stunAssistHost as NSObject,
|
||||
"hostname": hostname as NSObject,
|
||||
"env": Self.env.rawValue as NSObject,
|
||||
"acl": [
|
||||
"tcp": acl.tcp as NSObject,
|
||||
"udp": acl.udp as NSObject
|
||||
"exposed_service": [
|
||||
"tcp": (exposedService?.tcp ?? []) as NSObject,
|
||||
"udp": (exposedService?.udp ?? []) as NSObject
|
||||
] as NSObject,
|
||||
"network_address": [
|
||||
"network_id": networkId as NSObject,
|
||||
|
||||
@ -15,7 +15,7 @@ struct NetworkContext: Codable {
|
||||
let identityId: UInt32
|
||||
let resourceList: [Resource]
|
||||
let nodeList: [Node]
|
||||
let acl: ACL
|
||||
let exposedService: ExposedService?
|
||||
let exitNodeList: [ExitNode]
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
@ -25,7 +25,7 @@ struct NetworkContext: Codable {
|
||||
case identityId = "identity_id"
|
||||
case resourceList = "resource_list"
|
||||
case nodeList = "node_list"
|
||||
case acl = "acl"
|
||||
case exposedService = "exposed_service"
|
||||
case exitNodeList = "exit_node"
|
||||
}
|
||||
|
||||
@ -40,7 +40,7 @@ struct NetworkContext: Codable {
|
||||
|
||||
extension NetworkContext {
|
||||
|
||||
struct ACL: Codable {
|
||||
struct ExposedService: Codable {
|
||||
let tcp: [UInt32]
|
||||
let udp: [UInt32]
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user