feat(common): 协议 v2——版本号 + 帧头 seq/keyframe + 长度下界校验

为接入安卓主控做准备,先把三端共享契约改到能承载多客户端。改动集中在
common/src/lib.rs,三端适配在同一提交内完成以保证可编译。

协议版本(PROTO_VERSION=2)
- ControlMsg::Auth/AuthOk 增加 proto_version 字段;认证顺序改为「先版本后验证码」:
  版本不一致时字段布局可能不同,验证码的解析结果不可信
- 任一端版本不符即 AuthFail 并明确报错,把「连上了但行为诡异」变成「连不上且提示升级」

视频帧头(VideoFrameHeader)
- 新增 seq: u64(每次实际发送递增,含静止桌面重发)与 keyframe: bool
- keyframe 由新增的 common::h264_contains_idr() 从实际 Annex-B 码流判定,
  不依赖编码器 API 推断——NVENC 与 openh264 规则不同,实际输出才是唯一可信来源
- 该字段是 MediaCodec 判断解码器重置时机的必要条件,避免客户端自己写 NAL 扫描

不可信输入防护
- read_video_frame 补齐长度下界:total 必须 >= 4,hlen 必须落在 [1, total-4]
- 旧实现只校验上界,构造 total<4 的帧会让接收端在 buf[0..4] 处 panic(进程级DoS)
- 测试从 0 增至 11 个,覆盖序列化往返与 6 类越界/损坏输入

顺带修复(与上述契约直接相关)
- 新增 common::split_video_frame():静止桌面重发时复用载荷但重建帧头,
  否则 seq/ts_ms 会停在上次发送时刻,破坏 seq 单调递增契约
- agent-core 与 agent 两端的静止重发路径均改用该函数

验证:cargo test -p common → 20 passed(9 signaling + 11 新增)
This commit is contained in:
郑博文 committed 2026-10-28 16:05:41 +08:00
1 parent 703eb64fc0
commit 9e50bc6237
6 files changed
+560 -55

No files matched your search

+8 -1
View File
@@ -289,11 +289,17 @@ async fn end_to_end_capture_encode_transport_input() -> Result<()> {
&mut send,
&ControlMsg::Auth {
code: "smoke-code".into(),
proto_version: common::PROTO_VERSION,
},
)
.await?;
match read_control(&mut recv).await? {
ControlMsg::AuthOk { width, height } => {
ControlMsg::AuthOk {
width,
height,
proto_version,
} => {
assert_eq!(proto_version, common::PROTO_VERSION, "被控端协议版本不符");
assert_eq!(
(width, height),
(sw, sh),
@@ -429,6 +435,7 @@ async fn rejects_wrong_verification_code() -> Result<()> {
&mut send,
&ControlMsg::Auth {
code: "wrong-code".into(),
proto_version: common::PROTO_VERSION,
},
)
.await?;