fix(audit): address C2, C3, M4, M5 from 2026-05-25 audit
C2: Add EncryptingTransport wrapper — all media I/O now goes through ChaChaSession encrypt/decrypt before hitting the QUIC datagram path. cli.rs run_live/run_silence/run_file_mode accept Arc<dyn MediaTransport> and receive a wrapped transport after the handshake. C3: Wire VideoScorer::observe() into both plain and trunked forwarding loops in room.rs. Packets from participants with Abusive verdict are dropped before forwarding. last_bwe_kbps tracked from quality reports. M4: Widen FEC repair symbol index from u8 to u16 throughout (FecEncoder::generate_repair, FecDecoder::add_symbol, all call sites in call.rs, bench.rs, pipeline.rs, wzp-android). Eliminates theoretical wrapping when num_source + repair_count > 255. M5: Track last_encrypt_timestamp in ChaChaSession. debug_assert in encrypt() that timestamp is non-decreasing across calls (including post- rekey). complete_rekey() explicitly preserves last_encrypt_timestamp to prevent accidental timestamp reset regressions. 583 tests passing. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -111,7 +111,7 @@ impl RelayPipeline {
|
||||
let header = &packet.header;
|
||||
let _ = self.fec_decoder.add_symbol(
|
||||
(header.fec_block & 0xFF) as u8,
|
||||
(header.fec_block >> 8) as u8,
|
||||
header.fec_block >> 8,
|
||||
header.is_repair(),
|
||||
&packet.payload,
|
||||
);
|
||||
|
||||
@@ -21,6 +21,8 @@ use wzp_proto::{MediaTransport, default_signal_version};
|
||||
use crate::conformance::ConformanceMeter;
|
||||
use crate::metrics::RelayMetrics;
|
||||
use crate::trunk::TrunkBatcher;
|
||||
use crate::verdict::Verdict;
|
||||
use crate::video_scorer::VideoScorer;
|
||||
|
||||
/// Debug tap: logs packet metadata for matching rooms.
|
||||
#[derive(Clone)]
|
||||
@@ -1194,6 +1196,9 @@ async fn run_participant_plain(
|
||||
None
|
||||
};
|
||||
|
||||
let mut video_scorer = VideoScorer::new();
|
||||
let mut last_bwe_kbps: Option<u32> = None;
|
||||
|
||||
info!(
|
||||
room = %room_name,
|
||||
participant = participant_id,
|
||||
@@ -1261,10 +1266,20 @@ async fn run_participant_plain(
|
||||
);
|
||||
}
|
||||
|
||||
// TODO(T6.2-follow-up): feed video packets to VideoScorer here.
|
||||
// if pkt.header.media_type == MediaType::Video {
|
||||
// video_scorer.observe(&pkt.header, pkt.payload.len(), now, bwe_kbps);
|
||||
// }
|
||||
// Feed video packets to VideoScorer; drop if verdict is Abusive.
|
||||
if pkt.header.media_type == wzp_proto::MediaType::Video {
|
||||
let now = std::time::Instant::now();
|
||||
video_scorer.observe(&pkt.header, pkt.payload.len(), now, last_bwe_kbps);
|
||||
if let Some(Verdict::Abusive) = video_scorer.verdict() {
|
||||
warn!(
|
||||
room = %room_name,
|
||||
participant = participant_id,
|
||||
seq = pkt.header.seq,
|
||||
"VideoScorer: Abusive verdict — dropping packet"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Update per-session quality metrics if a quality report is present
|
||||
if let Some(ref report) = pkt.quality_report {
|
||||
@@ -1274,6 +1289,7 @@ async fn run_participant_plain(
|
||||
// Update receiver state from this participant's quality report (if present).
|
||||
if let Some(ref report) = pkt.quality_report {
|
||||
let bwe_kbps = report.bitrate_cap_kbps as u32;
|
||||
last_bwe_kbps = Some(bwe_kbps);
|
||||
room_mgr.update_receiver_state(&room_name, participant_id, bwe_kbps, report.loss_pct);
|
||||
}
|
||||
|
||||
@@ -1454,6 +1470,8 @@ async fn run_participant_trunked(
|
||||
let mut last_log_instant = std::time::Instant::now();
|
||||
let mut conformance =
|
||||
ConformanceMeter::with_token_bucket(crate::conformance::TokenBucket::for_audio_session());
|
||||
let mut video_scorer_trunked = VideoScorer::new();
|
||||
let mut last_bwe_kbps_trunked: Option<u32> = None;
|
||||
|
||||
info!(
|
||||
room = %room_name,
|
||||
@@ -1533,9 +1551,25 @@ async fn run_participant_trunked(
|
||||
);
|
||||
}
|
||||
|
||||
// Feed video packets to VideoScorer; drop if verdict is Abusive.
|
||||
if pkt.header.media_type == wzp_proto::MediaType::Video {
|
||||
let now = std::time::Instant::now();
|
||||
video_scorer_trunked.observe(&pkt.header, pkt.payload.len(), now, last_bwe_kbps_trunked);
|
||||
if let Some(Verdict::Abusive) = video_scorer_trunked.verdict() {
|
||||
warn!(
|
||||
room = %room_name,
|
||||
participant = participant_id,
|
||||
seq = pkt.header.seq,
|
||||
"VideoScorer: Abusive verdict — dropping packet (trunked)"
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Update receiver state from this participant's quality report.
|
||||
if let Some(ref report) = pkt.quality_report {
|
||||
let bwe_kbps = report.bitrate_cap_kbps as u32;
|
||||
last_bwe_kbps_trunked = Some(bwe_kbps);
|
||||
room_mgr.update_receiver_state(&room_name, participant_id, bwe_kbps, report.loss_pct);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user