diff --git a/client/macos/Runner/StatsClient.swift b/client/macos/Runner/StatsClient.swift index fa4e069..c9ab11a 100644 --- a/client/macos/Runner/StatsClient.swift +++ b/client/macos/Runner/StatsClient.swift @@ -47,6 +47,14 @@ final class StatsClient: NSObject { NSLog("[pangolin/stats] LibboxNewCommandClient returned nil") return } + // 打点:command.sock 由 sysext 的 LibboxCommandServer 在 group 容器内创建。 + // 若此处 sock 不存在 → 跑的是没起 CommandServer 的旧 sysext(版本没换上)。 + if let base = FileManager.default + .containerURL(forSecurityApplicationGroupIdentifier: self.appGroup) { + let sock = base.appendingPathComponent("command.sock").path + let exists = FileManager.default.fileExists(atPath: sock) + NSLog("[pangolin/stats] command.sock=%@ exists=%@", sock, exists ? "YES" : "NO(sysext 未起 CommandServer/旧版)") + } for attempt in 0..<10 { do { try c.connect() diff --git a/client/macos/Runner/VpnChannel.swift b/client/macos/Runner/VpnChannel.swift index 9171a08..e03c34c 100644 --- a/client/macos/Runner/VpnChannel.swift +++ b/client/macos/Runner/VpnChannel.swift @@ -46,6 +46,26 @@ final class VpnChannel: NSObject { .setStreamHandler(StatsStreamHandler(owner: instance)) instance.observeStatus() + // 启动即请求激活 System Extension。关键:隧道可能已被旧 sysext(on-demand/常驻) + // 拉起并自动重连,此时 app 只走 primeExistingConnection、永不调 start() → + // 永不提交激活请求 → 新版 sysext 永远不被装上(旧版一直跑,command.sock 不更新, + // 实时统计断流)。在 register 阶段主动激活一次:同开发者签名的高版本会静默 replace, + // 把运行中的旧扩展换成 bundle 里的新版。 + instance.activateOnLaunch() + } + + /// 启动时主动激活/更新 sysext(幂等):让 bundle 内的新版替换运行中的旧版。 + private func activateOnLaunch() { + Task { + do { + vpnLog("launch: 主动激活 System Extension(确保运行的是 bundle 内最新版)…") + try await activateSystemExtensionIfNeeded() + vpnLog("launch: System Extension 激活/更新完成 ✓") + } catch { + let ns = error as NSError + vpnLog("launch: System Extension 激活失败 ✗ code=\(ns.code) desc=\(ns.localizedDescription)") + } + } } // ── MethodChannel ───────────────────────────────────────────────