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