From 3cdf1953bf26183d615461435e4e68e8c38e3b14 Mon Sep 17 00:00:00 2001 From: anlicheng <244108715@qq.com> Date: Wed, 27 May 2026 17:46:30 +0800 Subject: [PATCH] fix superClient --- Tun/Super/SDLSuperClient.swift | 76 ++++++++++++++++++---------------- 1 file changed, 40 insertions(+), 36 deletions(-) diff --git a/Tun/Super/SDLSuperClient.swift b/Tun/Super/SDLSuperClient.swift index f4cbe1e..bfb9b1d 100644 --- a/Tun/Super/SDLSuperClient.swift +++ b/Tun/Super/SDLSuperClient.swift @@ -22,9 +22,7 @@ actor SDLSuperClient { // 数据流 public let messageStream: AsyncThrowingStream private let messageCont: AsyncThrowingStream.Continuation - - private var pendingConnectionError: Error? - + private let connection: NWConnection private let maxBufferSize: Int @@ -68,21 +66,14 @@ actor SDLSuperClient { return } - self.connection.stateUpdateHandler = { [weak self] state in - SDLLogger.log("[SDLSuperClient] new state: \(state)", for: .debug) - Task { - await self?.handleConnectionState(state: state) - } - } - self.connection.start(queue: queue) - + let stateStream = Self.makeStateStream(for: self.connection) defer { self.stop() } try await withTaskCancellationHandler { - try await self.waitUntilReady() - try await self.readLoop() + self.connection.start(queue: self.queue) + try await self.runStateLoop(stateStream) } onCancel: { self.connection.cancel() } @@ -99,35 +90,48 @@ actor SDLSuperClient { preconditionFailure("invalid super server IP: \(ip)") } - - private func handleConnectionState(state: NWConnection.State) { - switch state { - case .ready: - self.state = .running - case .failed(let error): - self.pendingConnectionError = SDLSuperError.connectionFailed(error) - self.messageCont.finish(throwing: SDLSuperError.connectionFailed(error)) - case .cancelled: - self.pendingConnectionError = SDLSuperError.connectionCancelled - self.messageCont.finish(throwing: SDLSuperError.connectionCancelled) - default: - () + + private static func makeStateStream(for connection: NWConnection) -> AsyncThrowingStream { + return AsyncThrowingStream(bufferingPolicy: .bufferingNewest(16)) { continuation in + connection.stateUpdateHandler = { state in + SDLLogger.log("[SDLSuperClient] new state: \(state)", for: .debug) + continuation.yield(state) + + switch state { + case .failed(let error): + continuation.finish(throwing: SDLSuperError.connectionFailed(error)) + case .cancelled: + continuation.finish(throwing: SDLSuperError.connectionCancelled) + default: + break + } + } + + continuation.onTermination = { _ in + connection.stateUpdateHandler = nil + } } } - - private func waitUntilReady() async throws { - while true { + + private func runStateLoop(_ stateStream: AsyncThrowingStream) async throws { + for try await state in stateStream { try Task.checkCancellation() - if case .running = self.state { + switch state { + case .ready: + self.state = .running + try await self.readLoop() 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 } - - if let pendingConnectionError { - throw pendingConnectionError - } - - try await Task.sleep(for: .milliseconds(100)) } }