fix superClient

This commit is contained in:
anlicheng 2026-05-27 18:22:22 +08:00
parent 3cdf1953bf
commit 1c0ed04fa2
6 changed files with 93 additions and 48 deletions

View File

@ -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

View File

@ -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")
}

View File

@ -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())
}
}
}

View File

@ -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)

View File

@ -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,

View File

@ -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]
}