feat: M3 mosh 挂起→恢复<3s(唤醒脉冲 + 会话状态机三相)

- SessionMachine 加 mosh 三相(moshActive/moshParked/moshResuming)+看门狗兜底,
  mosh 接管即拆 SSH、后台冻结不重建、前台唤醒脉冲等 SSP 续(+5 单测)
- bridge.go: Node.WakeUp()(tsnet InjectEvent+MagicSock.Rebind/ReSTUN) +
  MoshRelay.Rebind()(同端口重开 loopback、泵按 socket 生成容错)
- iosclient.cc: g_mosh_last_heard 探针(导出 mosh_last_heard_ms) + SIGCONT 全屏重绘
- MoshSession: nudge()(SIGCONT) + lastHeardMs();SSHTerminalModel 前台脉冲三连
  + healthy 轮询 + beginBackgroundTask;URL scheme 供无头前台唤醒
- 验证(vohive-vm over tsnet):15s 冻结→前台 wake pulse→1.3s recovered,<3s

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
kid
2026-07-24 17:04:33 +08:00
parent 32520f09e0
commit 866df1a323
23 changed files with 489 additions and 96 deletions

View File

@@ -4,6 +4,20 @@
<dict>
<key>AvailableLibraries</key>
<array>
<dict>
<key>BinaryPath</key>
<string>TsnetBridge.framework/TsnetBridge</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>TsnetBridge.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>TsnetBridge.framework/TsnetBridge</string>
@@ -21,20 +35,6 @@
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>TsnetBridge.framework/TsnetBridge</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>TsnetBridge.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>

View File

@@ -27,13 +27,18 @@ tailnet 内 host:moshPort回包再转回"最近一次上行的 client 源地
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (nonnull instancetype)init;
/**
* Close 关闭中继(两条泵 goroutine 随即因 conn 关闭而退出)。
* Close 关闭中继(两条泵 conn 关闭而退出)。
*/
- (BOOL)close:(NSError* _Nullable* _Nullable)error;
/**
* LocalPort 返回 loopback relay 监听的端口mosh_main 的 port 参数)。
* LocalPort 返回固定的 loopback relay 端口mosh_main 的 port 参数,跨 Rebind 不变)。
*/
- (long)localPort;
/**
* Rebind 在同端口重开 loopback socketiOS 前台恢复用:挂起后旧 socket 可能被系统回收为 defunct
关旧 socket → 旧上行泵退出 → 新泵接管;下行泵绑定稳定 tsConn 无需重启。端口被占等返回 error由上层升级为全量重建
*/
- (BOOL)rebind:(NSError* _Nullable* _Nullable)error;
@end
/**
@@ -77,6 +82,11 @@ Swift 侧 close(fd) 会触发泵结束并关闭 tsConn。返回 -1 + error 表
gomobile 友好签名基本类型入参、error 出参。
*/
- (BOOL)upWithAuthKey:(NSString* _Nullable)authKey timeoutMs:(long)timeoutMs error:(NSError* _Nullable* _Nullable)error;
/**
* WakeUp 在 iOS 前台恢复时主动唤醒 tsnet 网络层:注入链路变化事件 + Rebind/重新 STUN
把"等首次写失败才发现 DERP/路径已死"变成"立刻重建",配合 mosh SSP 实现秒级恢复。
*/
- (void)wakeUp;
@end
/**

View File

@@ -9,9 +9,9 @@
<key>MinimumOSVersion</key>
<string>100.0</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1784861278</string>
<string>0.0.1784882284</string>
<key>CFBundleVersion</key>
<string>0.0.1784861278</string>
<string>0.0.1784882284</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
</dict>

View File

@@ -27,13 +27,18 @@ tailnet 内 host:moshPort回包再转回"最近一次上行的 client 源地
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (nonnull instancetype)init;
/**
* Close 关闭中继(两条泵 goroutine 随即因 conn 关闭而退出)。
* Close 关闭中继(两条泵 conn 关闭而退出)。
*/
- (BOOL)close:(NSError* _Nullable* _Nullable)error;
/**
* LocalPort 返回 loopback relay 监听的端口mosh_main 的 port 参数)。
* LocalPort 返回固定的 loopback relay 端口mosh_main 的 port 参数,跨 Rebind 不变)。
*/
- (long)localPort;
/**
* Rebind 在同端口重开 loopback socketiOS 前台恢复用:挂起后旧 socket 可能被系统回收为 defunct
关旧 socket → 旧上行泵退出 → 新泵接管;下行泵绑定稳定 tsConn 无需重启。端口被占等返回 error由上层升级为全量重建
*/
- (BOOL)rebind:(NSError* _Nullable* _Nullable)error;
@end
/**
@@ -77,6 +82,11 @@ Swift 侧 close(fd) 会触发泵结束并关闭 tsConn。返回 -1 + error 表
gomobile 友好签名基本类型入参、error 出参。
*/
- (BOOL)upWithAuthKey:(NSString* _Nullable)authKey timeoutMs:(long)timeoutMs error:(NSError* _Nullable* _Nullable)error;
/**
* WakeUp 在 iOS 前台恢复时主动唤醒 tsnet 网络层:注入链路变化事件 + Rebind/重新 STUN
把"等首次写失败才发现 DERP/路径已死"变成"立刻重建",配合 mosh SSP 实现秒级恢复。
*/
- (void)wakeUp;
@end
/**

View File

@@ -9,9 +9,9 @@
<key>MinimumOSVersion</key>
<string>100.0</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1784861278</string>
<string>0.0.1784882284</string>
<key>CFBundleVersion</key>
<string>0.0.1784861278</string>
<string>0.0.1784882284</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
</dict>