fix(client/macos): 实时统计改走 sendProviderMessage,根治容器路径死局
上一版试图让 root 扩展把 command.sock 建到用户容器,反而让 startTunnel 抛错、隧道连不上
(root 在用户 home 建 socket、属主/路径与无 root 的 app 对不上,且方向本就错)。回退该路子。
正解:用 NetworkExtension 官方跨进程通道,绕开「root 扩展容器 vs 用户 app 容器」死局——
- 扩展内新增 StatsCollector:连本进程自己的 command.sock(同容器、root 可达),订阅
status/group 缓存最新上下行 + urltest;handleAppMessage 收到 "stats" 即回最新 JSON。
- 主 app StatsClient 改为每秒 NETunnelProviderSession.sendProviderMessage("stats") 拉取、
解析后推 onStats(不再直连 socket);VpnChannel 三处启动点改传 session。
- 扩展代码变更 → CURRENT_PROJECT_VERSION 44→45,让 sysextd 重装。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -171,10 +171,12 @@ final class VpnChannel: NSObject {
|
||||
let s = Self.statusString(conn.status)
|
||||
vpnLog("NEVPNStatus 变化 → \(s) (raw=\(conn.status.rawValue))")
|
||||
self.statusSink?(s)
|
||||
// 实时统计 CommandClient 跟随连接状态启停。
|
||||
// 实时统计跟随连接状态启停(经 sendProviderMessage 向扩展拉取)。
|
||||
switch conn.status {
|
||||
case .connected:
|
||||
self.statsClient.start()
|
||||
if let s = conn as? NETunnelProviderSession {
|
||||
self.statsClient.start(session: s)
|
||||
}
|
||||
case .disconnected, .invalid:
|
||||
self.statsClient.stop()
|
||||
default:
|
||||
@@ -193,10 +195,10 @@ final class VpnChannel: NSObject {
|
||||
let mgr = all.first else { return }
|
||||
await MainActor.run {
|
||||
self.manager = mgr
|
||||
if mgr.connection.status == .connected {
|
||||
if mgr.connection.status == .connected, let s = mgr.connection as? NETunnelProviderSession {
|
||||
vpnLog("启动时检测到隧道已连接(raw=\(mgr.connection.status.rawValue)),主动启动实时统计")
|
||||
self.statusSink?(Self.statusString(mgr.connection.status))
|
||||
self.statsClient.start()
|
||||
self.statsClient.start(session: s)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -209,9 +211,12 @@ final class VpnChannel: NSObject {
|
||||
|
||||
fileprivate func onStatsListen(_ sink: @escaping FlutterEventSink) {
|
||||
statsSink = sink
|
||||
// 实时速率由 StatsClient(libbox CommandClient)在隧道 connected 时产出并经
|
||||
// onStats 回调推送;此处仅登记 sink。若已连接则补一次拉起。
|
||||
if manager?.connection.status == .connected { statsClient.start() }
|
||||
// 实时速率由 StatsClient(经 sendProviderMessage 向扩展拉取)在隧道 connected 时
|
||||
// 产出并经 onStats 回调推送;此处仅登记 sink。若已连接则补一次拉起。
|
||||
if manager?.connection.status == .connected,
|
||||
let s = manager?.connection as? NETunnelProviderSession {
|
||||
statsClient.start(session: s)
|
||||
}
|
||||
}
|
||||
fileprivate func onStatsCancel() { statsSink = nil }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user