Skip to main content

rtc_rtcp/extended_report/
prt.rs

1use super::*;
2
3const PRT_REPORT_BLOCK_MIN_LENGTH: u16 = 8;
4
5/// PacketReceiptTimesReportBlock represents a Packet Receipt Times
6/// report block, as described in RFC 3611 section 4.3.
7///
8///  0                   1                   2                   3
9///  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
10/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
11/// |     BT=3      | rsvd. |   t   |         block length          |
12/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13/// |                        ssrc of source                         |
14/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15/// |          begin_seq            |             end_seq           |
16/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17/// |       Receipt time of packet begin_seq                        |
18/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19/// |       Receipt time of packet (begin_seq + 1) mod 65536        |
20/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21/// :                              ...                              :
22/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23/// |       Receipt time of packet (end_seq - 1) mod 65536          |
24/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25#[derive(Debug, Default, PartialEq, Eq, Clone)]
26pub struct PacketReceiptTimesReportBlock {
27    //not included in marshal/unmarshal
28    /// The block's `T` field, which scales the receipt-time values.
29    pub t: u8,
30
31    //marshal/unmarshal
32    /// The SSRC whose packets are reported on.
33    pub ssrc: u32,
34    /// The first sequence number covered by this block.
35    pub begin_seq: u16,
36    /// One past the last sequence number covered.
37    pub end_seq: u16,
38    /// Receipt time for each packet in the range, in the block's timestamp units.
39    pub receipt_time: Vec<u32>,
40}
41
42impl fmt::Display for PacketReceiptTimesReportBlock {
43    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44        write!(f, "{self:?}")
45    }
46}
47
48impl PacketReceiptTimesReportBlock {
49    /// The XR block header describing this block's type and length.
50    pub fn xr_header(&self) -> XRHeader {
51        XRHeader {
52            block_type: BlockType::PacketReceiptTimes,
53            type_specific: self.t & 0x0F,
54            block_length: (self.raw_size() / 4 - 1) as u16,
55        }
56    }
57}
58
59impl Packet for PacketReceiptTimesReportBlock {
60    fn header(&self) -> Header {
61        Header::default()
62    }
63
64    /// destination_ssrc returns an array of ssrc values that this report block refers to.
65    fn destination_ssrc(&self) -> Vec<u32> {
66        vec![self.ssrc]
67    }
68
69    fn raw_size(&self) -> usize {
70        XR_HEADER_LENGTH + PRT_REPORT_BLOCK_MIN_LENGTH as usize + self.receipt_time.len() * 4
71    }
72
73    fn as_any(&self) -> &dyn Any {
74        self
75    }
76    fn equal(&self, other: &dyn Packet) -> bool {
77        other
78            .as_any()
79            .downcast_ref::<PacketReceiptTimesReportBlock>()
80            == Some(self)
81    }
82    fn cloned(&self) -> Box<dyn Packet> {
83        Box::new(self.clone())
84    }
85}
86
87impl MarshalSize for PacketReceiptTimesReportBlock {
88    fn marshal_size(&self) -> usize {
89        self.raw_size()
90    }
91}
92
93impl Marshal for PacketReceiptTimesReportBlock {
94    /// marshal_to encodes the PacketReceiptTimesReportBlock in binary
95    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
96        if buf.remaining_mut() < self.marshal_size() {
97            return Err(Error::BufferTooShort);
98        }
99
100        let h = self.xr_header();
101        let n = h.marshal_to(buf)?;
102        buf = &mut buf[n..];
103
104        buf.put_u32(self.ssrc);
105        buf.put_u16(self.begin_seq);
106        buf.put_u16(self.end_seq);
107        for rt in &self.receipt_time {
108            buf.put_u32(*rt);
109        }
110
111        Ok(self.marshal_size())
112    }
113}
114
115impl Unmarshal for PacketReceiptTimesReportBlock {
116    /// Unmarshal decodes the PacketReceiptTimesReportBlock from binary
117    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
118    where
119        Self: Sized,
120        B: Buf,
121    {
122        if raw_packet.remaining() < XR_HEADER_LENGTH {
123            return Err(Error::PacketTooShort);
124        }
125
126        let xr_header = XRHeader::unmarshal(raw_packet)?;
127        let block_length = match xr_header.block_length.checked_mul(4) {
128            Some(length) => length,
129            None => return Err(Error::InvalidBlockSize),
130        };
131        if block_length < PRT_REPORT_BLOCK_MIN_LENGTH
132            || !(block_length - PRT_REPORT_BLOCK_MIN_LENGTH).is_multiple_of(4)
133            || raw_packet.remaining() < block_length as usize
134        {
135            return Err(Error::PacketTooShort);
136        }
137
138        let t = xr_header.type_specific & 0x0F;
139
140        let ssrc = raw_packet.get_u32();
141        let begin_seq = raw_packet.get_u16();
142        let end_seq = raw_packet.get_u16();
143
144        let remaining = block_length - PRT_REPORT_BLOCK_MIN_LENGTH;
145        let mut receipt_time = vec![];
146        for _ in 0..remaining / 4 {
147            receipt_time.push(raw_packet.get_u32());
148        }
149
150        Ok(PacketReceiptTimesReportBlock {
151            t,
152
153            ssrc,
154            begin_seq,
155            end_seq,
156            receipt_time,
157        })
158    }
159}