9.3 KiB
CMVR QUIC test Gateway
cmvr_quic_test_gateway 是开发和验收工具,不是平台端生产 Gateway。它在本机
监听真实的 MsQuic/TLS/UDP 连接,用来验证 cmvr_es 的 QUIC edge v1 客户端。
测试链路:
output/bin/cmvr_es
├── reliable QUIC stream ──> cmvr_quic_test_gateway
│ register / heartbeat / media metadata
└── QUIC DATAGRAM ─────────> bounded media reassembler
Gateway 使用生产代码中的:
EdgeControlEnvelopeprotobuf;ControlFrameEncoder/ControlFrameDecoder;DatagramPacketizer::decodeHeader;CMQDv1 常量和类型。
它不会实现 WebTransport、WebRTC、HTTP API、节点数据库或浏览器播放。
构建
该目录的 CMakeLists.txt 由项目测试目录加入。MsQuic 通过根目录
request.txt 提供。依赖为:
msquiccmvr_es::protocmvr_es::quic_edge_serviceThreads::Threads
示例:
cmake -S . -B build \
-DCMAKE_BUILD_TYPE=Release \
-DCMVR_ARCH=x86 \
-DBUILD_TESTING=ON
cmake --build build --target cmvr_quic_test_gateway -j2
默认只生成 build-tree 测试程序,不污染部署目录。如确实希望一同安装:
cmake -S . -B build \
-DCMVR_INSTALL_QUIC_TEST_GATEWAY=ON
cmake --build build --target cmvr_quic_test_gateway -j2
cmake --install build
安装位置是 output/bin/cmvr_quic_test_gateway,可复用
output/lib/libmsquic.so 和现有相对 RUNPATH。
生成本地测试证书
QUIC 即使使用“不校验证书”的 client 模式,Server 仍必须提供 TLS 证书。 不要提交真实私钥。下面命令只在 build 目录生成 loopback 测试证书:
mkdir -p build/test/quic_gateway/certs
openssl req -x509 -newkey rsa:2048 -nodes \
-keyout build/test/quic_gateway/certs/server.key \
-out build/test/quic_gateway/certs/server.crt \
-days 7 \
-subj "/CN=127.0.0.1" \
-addext "subjectAltName=IP:127.0.0.1"
MsQuic/OpenSSL 当前要求这里的 PEM 私钥不带密码。
启动
固定端口适合人工联调。构建树中请使用 CMake 生成的启动包装器;它会补齐 仓库内 gRPC 等传递动态库的搜索路径:
build/test/quic_gateway/run_cmvr_quic_test_gateway \
--bind 127.0.0.1 \
--port 4433 \
--cert build/test/quic_gateway/certs/server.crt \
--key build/test/quic_gateway/certs/server.key \
--scenario normal \
--summary-file build/test/quic_gateway/summary.json
自动化测试应使用 --port 0 避免端口冲突。Gateway 会查询 Listener 实际端口,
在 stdout 和 --ready-file 写入一个 JSON 对象:
build/test/quic_gateway/run_cmvr_quic_test_gateway \
--bind 127.0.0.1 \
--port 0 \
--cert build/test/quic_gateway/certs/server.crt \
--key build/test/quic_gateway/certs/server.key \
--ready-file build/test/quic_gateway/ready.json \
--summary-file build/test/quic_gateway/summary.json \
--exit-after-heartbeats 3
Ready 文件示例:
{"event":"ready","bind":"127.0.0.1:52319","port":52319,"alpn":"cmvr-quic-edge/1","scenario":"normal","datagram_enabled":true}
自动 runner 读取 port,将它写入临时 quic_edge_task.pb.txt 后再启动
cmvr_es。不要直接改唯一一份 output/bin/config/;普通安装默认会覆盖它。
只更新程序与运行库时,应在配置构建目录时设置
-DCMVR_INSTALL_DEFAULT_RUNTIME_ASSETS=OFF。
cmvr_es 本机配置
第一轮只测试注册、IP 上报和心跳,保持设备和 tracks 关闭:
quic_edge {
id: "quic_edge"
server_host: "127.0.0.1"
server_port: 4433
alpn: "cmvr-quic-edge/1"
node_id: "local-quic-test"
software_version: "test"
grpc_endpoint_host: "127.0.0.1"
grpc_endpoint_port: 50052
grpc_endpoint_tls: false
include_loopback_interfaces: true
heartbeat_interval_ms: 1000
control_response_timeout_ms: 1000
tls {
allow_insecure: true
}
reconnect {
initial_delay_ms: 100
maximum_delay_ms: 1000
multiplier: 2.0
jitter_percent: 0
connect_timeout_ms: 3000
}
maximum_datagram_bytes: 1200
maximum_control_frame_bytes: 1048576
maximum_frame_bytes: 524288
datagram_send_queue_depth: 512
media_poll_interval_ms: 2
}
在 TaskManager 中将 quic_edge entry 设为 enable: true。然后运行一份独立的
临时配置树:
output/bin/cmvr_es /tmp/cmvr-quic-e2e/config/cmvr_es.pb.txt
场景
--scenario 支持:
当前 CTest 自动回归仅运行 normal 场景;其余场景保留为手工故障注入和验收入口,
尚未纳入自动回归。
| 名称 | 行为 | 预期 Edge 行为 |
|---|---|---|
normal |
接受注册并精确 ACK 心跳 | 保持同一连接 |
reject-registration |
返回 accepted=false |
退避后重新注册 |
drop-heartbeat-ack |
接收但不回复心跳 | response timeout 后重连 |
wrong-ack-session |
ACK 使用错误 session ID | 判定协议错误并重连 |
fatal-protocol-error |
注册成功后发送 fatal ProtocolError |
重连 |
nonfatal-protocol-error |
注册成功后发送 nonfatal ProtocolError |
保持连接并继续心跳 |
datagram-disabled |
不协商 QUIC DATAGRAM | 注册和心跳正常,媒体不发送 |
可以用以下条件让程序自动成功退出:
--exit-after-registrations N--exit-after-heartbeats N--run-for-ms N
收到 SIGINT 或 SIGTERM 时,Gateway 会停止 Listener、关闭活动连接、排空工作
队列并写 summary。
协议验证
每个连接独立维护:
- control framing buffer;
- Edge 和 Gateway 各自的严格递增
message_sequence; - node、boot、registration session;
- media session epoch;
- track descriptor generation token;
- DATAGRAM 重组缓存。
Gateway 要求:
NodeRegisterRequest是第一条应用消息;- protocol version 为 1;
- 后续 envelope sequence 严格增加;
- heartbeat 的 node、boot 和 session 与注册一致;
- media session 先于 descriptor;
- DATAGRAM 的 epoch、track、kind 和 generation token 与可靠元数据一致。
observed_source_ip 从 MsQuic peer address 获取,不从 Edge 上报字段复制。
Heartbeat 中存在 device_manager 时,Gateway 会记录 Manager 元数据以及设备
总数、启用数、禁用数、确认异常数和未知健康数;该字段是 v1 的兼容性追加项,
并在最终 summary 的 heartbeat_devices 数组中保留最近一次完整设备行。测试
Gateway 仍接受没有该字段的旧 Edge。当前 Edge 只发送已启用设备,因此正常情况
下禁用数为 0;该统计仍用于兼容旧发送端和发现协议违规。
summary 还会保留每类媒体最近一次 descriptor,以及已完成帧中的最大
frame_sequence、长度、flags、采集时间戳和 FNV-1a 64 位载荷哈希。这里的哈希
只用于测试中精确比对字节,不用于安全认证。真实 E2E 会先发送 discovery 帧并等
descriptor 到达,再发送 priming/validation 帧,从而避免 reliable stream 与
DATAGRAM 跨通道乱序造成偶发误判。
DATAGRAM 安全边界
MsQuic callback 只复制收到的数据并进入有界队列;控制消息使用高优先级队列, 不会被媒体洪峰长期阻塞。后台线程完成 protobuf 处理和媒体重组。
重组 key 是:
(session_epoch, track_id, frame_sequence)
接收器限制:
- 总缓存字节;
- 在途帧数;
- 单帧大小;
- 单帧最多 8192 个分片;
- 不完整帧超时;
- fragment index 冲突;
- byte range 重叠;
- 新 session epoch 清理旧分片。
相关 CLI:
--max-reassembly-bytes
--max-reassembly-frames
--max-frame-bytes
--max-work-queue-bytes
--reassembly-timeout-ms
输出与判定
stdout 每行都是一个 JSON 对象或 JSON-compatible 单行事件。最终 summary 包含:
- connection/register/heartbeat 计数;
- 注册和最近一次心跳上报的网卡数量、gRPC endpoint 与对端源 IP;
- 最近一次 DeviceManager 名称/版本/描述,以及已上报设备总数、启用数、兼容性
禁用数、确认异常数、未知健康数和
heartbeat_devices完整设备行; - ACK、故障场景和协议错误计数;
- media session/descriptor/DATAGRAM 计数;
- 完整帧(含视频/音频分项)、无效包、队列丢包;
- 超时、容量淘汰和 session 清理的不完整帧。
自动化脚本至少应检查:
runtime_failed == false
registrations_accepted >= 1 # normal 场景
heartbeats_received >= 1
heartbeat_acks_sent >= 1
protocol_violations == 0
媒体场景还应检查:
media_sessions_opened >= 1
track_descriptors_received >= 1
datagrams_received >= 1
frames_completed >= 1
无设备主机的限制
关闭全部设备时,实际 output/bin/cmvr_es 可以完整验证 TLS、ALPN、控制 stream、
注册、IP 上报、心跳和重连,但不会产生音视频。
要在无硬件环境验证媒体 DATAGRAM,测试侧还需要 synthetic MediaSourceHub producer 或测试专用 fake camera/microphone。该 Gateway 已具备媒体接收和重组能力,但不会 伪造 Edge 发出的媒体。
安全说明
- 仅监听 loopback 是默认值;
allow_insecure仅限本机开发;- 不要将测试 Gateway 暴露到不受信任网络;
- 不要复用或提交生产证书、生产私钥;
- 该工具没有生产级认证、授权、持久化和多租户隔离。