rtc_interceptor/rtpfb/acknowledgement.rs
1//! What a feedback report says happened to one packet.
2
3use rtcp::transport_feedbacks::cc_feedback_report::Ecn;
4use std::time::{Duration, Instant};
5
6/// One packet's fate, as reported by the receiver.
7///
8/// `arrival` is a [`Duration`] rather than an [`Instant`] because it is measured on the
9/// **receiver's** clock, which this endpoint has no way to align with its own. Only differences
10/// between arrivals are meaningful, and those are what congestion control actually reads: the
11/// spread between send spacing and arrival spacing is the delay the path is imposing.
12///
13/// Each feedback format supplies its own epoch — TWCC's 24-bit reference time, RFC 8888's report
14/// timestamp — and both advance monotonically, so arrivals stay comparable across successive
15/// reports of the same format. They are *not* comparable between formats.
16#[derive(Debug, Clone, Copy, PartialEq, Eq)]
17pub struct Acknowledgement {
18 /// The sequence number this refers to. TWCC numbers packets itself; RFC 8888 uses the RTP
19 /// sequence number of the stream it names.
20 pub sequence_number: u16,
21 /// Whether the receiver got it.
22 pub arrived: bool,
23 /// When it arrived, on the receiver's clock. `None` for a packet that did not arrive, or one
24 /// reported as received without a usable arrival time.
25 pub arrival: Option<Duration>,
26 /// The ECN marking the receiver observed. TWCC cannot carry this and always reports `NotEct`.
27 pub ecn: Ecn,
28}
29
30impl Acknowledgement {
31 /// A packet the receiver did not get.
32 pub fn lost(sequence_number: u16) -> Self {
33 Self {
34 sequence_number,
35 arrived: false,
36 arrival: None,
37 ecn: Ecn::NotEct,
38 }
39 }
40
41 /// A packet the receiver got at `arrival` on its own clock.
42 pub fn received(sequence_number: u16, arrival: Option<Duration>, ecn: Ecn) -> Self {
43 Self {
44 sequence_number,
45 arrived: true,
46 arrival,
47 ecn,
48 }
49 }
50}
51
52/// One outgoing packet, joined with whatever the receiver later said about it.
53///
54/// This is the record congestion control consumes: what was sent, when it left here, and when it
55/// turned up there.
56#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct PacketReport {
58 /// SSRC of the stream the packet belongs to.
59 pub ssrc: u32,
60 /// Monotonic identifier assigned when the packet was recorded, so reports stay in send order
61 /// however the sequence numbers wrap.
62 pub id: u64,
63 /// The RTP sequence number the packet carried.
64 pub rtp_sequence_number: u16,
65 /// Whether this packet is tracked by its transport-wide sequence number rather than its RTP
66 /// one — the two feedback formats identify packets differently.
67 pub is_twcc: bool,
68 /// The transport-wide sequence number, when `is_twcc`.
69 pub twcc_sequence_number: u16,
70 /// Size on the wire, in bytes.
71 pub size: usize,
72 /// Whether the receiver reported it as arrived.
73 pub arrived: bool,
74 /// When it left this endpoint. **The release instant**, not the instant the application
75 /// enqueued it — see the chain contract's rule 3, since a pacer's queueing delay counted as
76 /// network delay is exactly what corrupts a bandwidth estimate.
77 pub departure: Instant,
78 /// When it arrived, on the receiver's clock. See [`Acknowledgement::arrival`].
79 pub arrival: Option<Duration>,
80 /// The ECN marking the receiver observed.
81 pub ecn: Ecn,
82}
83
84/// A batch of packet reports, with the round trip time they imply.
85#[derive(Debug, Clone, PartialEq, Eq)]
86pub struct Report {
87 /// When the feedback that produced this batch was received here.
88 pub arrival: Instant,
89 /// Round trip time derived from the newest packet this feedback acknowledged.
90 pub rtt: Option<Duration>,
91 /// The packets being reported on, in send order.
92 pub packet_reports: Vec<PacketReport>,
93}