fix(core,android): networking-audit small follow-ups — bounds, oversized AUs, probe flag
Networking-audit deferred plan §6: - 6.1 client reassembler ceiling derived from the negotiated rate: Welcome::session_config (client role) now sets max_frame_bytes to clamp(4 × bitrate_kbps×125 / refresh_hz, 8 MiB, 64 MiB) instead of the blanket 64 MiB p1_defaults bound — the hostile-header memory ceiling was ~10× larger than any real access unit. Local only (the host never reassembles video; the wire is self-describing); a bitrate-0 (older) host keeps the old bound. Unit-tested floor/derived/host/old-host cases. - 6.2 ProbeState.active is cleared when the host's ProbeResult lands, so the pump stops mirroring receive counters once the burst is over. - 6.3 Android: an AU larger than the codec input buffer is DROPPED with a recovery-keyframe request and a counter, on both the sync (feed) and async (feed_ready) paths — a truncated AU is corrupt input the decoder chews on silently, poisoning the reference chain until the next IDR. The async path recycles the never-queued input slot; the sync path returns the dequeued slot with zero valid bytes. - 6.4 bounded uplink channels: mic_tx at 64 (~320 ms of 5 ms frames; overflow sheds the fresh frame with a debug log — a tokio mpsc can't shed from the head, and past 320 ms of backlog the mic is broken either way; the bound is about memory) and ctrl_tx at 32 (sparse requests; a full queue means a wedged control task, reported as Closed). input_tx stays unbounded per the plan: keyboard/mouse events must never silently drop, and gamepad state is snapshot-healed. - 6.5 (wire version byte says P1 while streaming Gf16): record-only, resolves with the P2 packet revision. include/punktfunk_core.h: cbindgen re-emitted in the new module order after the quic/ split (item 3) — no semantic change beyond the reorder. cargo ndk check (arm64-v8a), workspace clippy, core+host tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
use super::*;
|
||||
use crate::config::{CompositorPref, FecConfig, FecScheme, GamepadPref, Mode};
|
||||
use crate::config::{CompositorPref, FecConfig, FecScheme, GamepadPref, Mode, Role};
|
||||
|
||||
#[test]
|
||||
fn welcome_roundtrip() {
|
||||
@@ -32,6 +32,35 @@ fn welcome_roundtrip() {
|
||||
host_caps: HOST_CAP_GAMEPAD_STATE,
|
||||
};
|
||||
assert_eq!(Welcome::decode(&w.encode()).unwrap(), w);
|
||||
|
||||
// Client-side reassembler ceiling derives from the negotiated rate: 4x the average frame at
|
||||
// 50 Mbps/240 Hz is ~104 KB, so the 8 MiB floor governs. The host keeps the p1_defaults
|
||||
// bound (it never reassembles video), as does a client of a bitrate-0 (older) host.
|
||||
let cc = w.session_config(Role::Client);
|
||||
assert_eq!(cc.max_frame_bytes, 8 << 20);
|
||||
cc.validate().expect("derived client config validates");
|
||||
assert_eq!(w.session_config(Role::Host).max_frame_bytes, 64 << 20);
|
||||
let old_host = Welcome {
|
||||
bitrate_kbps: 0,
|
||||
..w.clone()
|
||||
};
|
||||
assert_eq!(
|
||||
old_host.session_config(Role::Client).max_frame_bytes,
|
||||
64 << 20
|
||||
);
|
||||
// A high-rate mode scales past the floor: 1.5 Gbps at 60 Hz = 4 x 3.125 MB = 12.5 MB.
|
||||
let fat = Welcome {
|
||||
bitrate_kbps: 1_500_000,
|
||||
mode: Mode {
|
||||
width: 5120,
|
||||
height: 1440,
|
||||
refresh_hz: 60,
|
||||
},
|
||||
..w.clone()
|
||||
};
|
||||
let derived = fat.session_config(Role::Client).max_frame_bytes;
|
||||
assert_eq!(derived, 4 * 1_500_000 * 125 / 60);
|
||||
assert!(derived > (8 << 20) && derived < (64 << 20));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user