import Foundation actor SDLSuperService { typealias MessageHandler = @Sendable (SDLQUICInboundMessage) async -> Void private let serverName: String private let serverAddress: String private let port: UInt16 private let onMessage: MessageHandler private var superClient: SDLSuperClient? private var monitorTask: Task? init(serverName: String, serverAddress: String, port: UInt16 = 1443, onMessage: @escaping MessageHandler) { self.serverName = serverName self.serverAddress = serverAddress self.port = port self.onMessage = onMessage } func start() { guard self.monitorTask == nil else { return } self.monitorTask = startMonitorTask(name: "superServiceMonitor") { [weak self] in guard let self else { throw CancellationError() } try await self.runOnce() } } func stop() async { let monitorTask = self.monitorTask self.monitorTask = nil let superClient = self.superClient self.superClient = nil monitorTask?.cancel() await superClient?.stop() if let monitorTask { await monitorTask.value } } func send(type: SDLPacketType, data: Data) async { await self.superClient?.send(type: type, data: data) } private func runOnce() async throws { let superClient = SDLSuperClient(serverName: self.serverName, serverAddress: self.serverAddress, port: self.port) self.superClient = superClient await superClient.start() do { try await withTaskCancellationHandler { try await self.run(superClient) } onCancel: { Task { await superClient.stop() } } await self.cleanup(superClient) } catch { await self.cleanup(superClient) throw error } } private func run(_ superClient: SDLSuperClient) async throws { try await Task.sleep(for: .seconds(0.5)) try Task.checkCancellation() SDLLogger.log("[SDLSuperService] start super client: \(self.serverAddress)") try await withThrowingTaskGroup(of: Void.self) { group in defer { group.cancelAll() } let onMessage = self.onMessage group.addTask { for try await message in await superClient.messageStream { try Task.checkCancellation() await onMessage(message) } } group.addTask { while true { try await Task.sleep(for: .seconds(5)) try Task.checkCancellation() await superClient.send(type: .ping, data: Data()) } } _ = try await group.next() } } private func cleanup(_ superClient: SDLSuperClient) async { await superClient.stop() if self.superClient === superClient { self.superClient = nil } SDLLogger.log("[SDLSuperService] cleanup") } } actor SDLSuperServiceProxy { private var superService: SDLSuperService? private var generation: UInt64 = 0 func replace(_ superService: SDLSuperService?) async { self.generation &+= 1 let oldSuperService = self.superService self.superService = superService if oldSuperService !== superService { await oldSuperService?.stop() } } func stop() async { self.generation &+= 1 let superService = self.superService self.superService = nil await superService?.stop() } func send(type: SDLPacketType, data: Data) async { await self.superService?.send(type: type, data: data) } }