xref: /webrtc/rtcp/src/extended_report/prt.rs (revision 5d8fe953)
1 use super::*;
2 
3 const 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)]
26 pub struct PacketReceiptTimesReportBlock {
27     //not included in marshal/unmarshal
28     pub t: u8,
29 
30     //marshal/unmarshal
31     pub ssrc: u32,
32     pub begin_seq: u16,
33     pub end_seq: u16,
34     pub receipt_time: Vec<u32>,
35 }
36 
37 impl fmt::Display for PacketReceiptTimesReportBlock {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result38     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39         write!(f, "{self:?}")
40     }
41 }
42 
43 impl PacketReceiptTimesReportBlock {
xr_header(&self) -> XRHeader44     pub fn xr_header(&self) -> XRHeader {
45         XRHeader {
46             block_type: BlockType::PacketReceiptTimes,
47             type_specific: self.t & 0x0F,
48             block_length: (self.raw_size() / 4 - 1) as u16,
49         }
50     }
51 }
52 
53 impl Packet for PacketReceiptTimesReportBlock {
header(&self) -> Header54     fn header(&self) -> Header {
55         Header::default()
56     }
57 
58     /// destination_ssrc returns an array of ssrc values that this report block refers to.
destination_ssrc(&self) -> Vec<u32>59     fn destination_ssrc(&self) -> Vec<u32> {
60         vec![self.ssrc]
61     }
62 
raw_size(&self) -> usize63     fn raw_size(&self) -> usize {
64         XR_HEADER_LENGTH + PRT_REPORT_BLOCK_MIN_LENGTH as usize + self.receipt_time.len() * 4
65     }
66 
as_any(&self) -> &(dyn Any + Send + Sync)67     fn as_any(&self) -> &(dyn Any + Send + Sync) {
68         self
69     }
equal(&self, other: &(dyn Packet + Send + Sync)) -> bool70     fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool {
71         other
72             .as_any()
73             .downcast_ref::<PacketReceiptTimesReportBlock>()
74             .map_or(false, |a| self == a)
75     }
cloned(&self) -> Box<dyn Packet + Send + Sync>76     fn cloned(&self) -> Box<dyn Packet + Send + Sync> {
77         Box::new(self.clone())
78     }
79 }
80 
81 impl MarshalSize for PacketReceiptTimesReportBlock {
marshal_size(&self) -> usize82     fn marshal_size(&self) -> usize {
83         self.raw_size()
84     }
85 }
86 
87 impl Marshal for PacketReceiptTimesReportBlock {
88     /// marshal_to encodes the PacketReceiptTimesReportBlock in binary
marshal_to(&self, mut buf: &mut [u8]) -> Result<usize>89     fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
90         if buf.remaining_mut() < self.marshal_size() {
91             return Err(error::Error::BufferTooShort.into());
92         }
93 
94         let h = self.xr_header();
95         let n = h.marshal_to(buf)?;
96         buf = &mut buf[n..];
97 
98         buf.put_u32(self.ssrc);
99         buf.put_u16(self.begin_seq);
100         buf.put_u16(self.end_seq);
101         for rt in &self.receipt_time {
102             buf.put_u32(*rt);
103         }
104 
105         Ok(self.marshal_size())
106     }
107 }
108 
109 impl Unmarshal for PacketReceiptTimesReportBlock {
110     /// Unmarshal decodes the PacketReceiptTimesReportBlock from binary
unmarshal<B>(raw_packet: &mut B) -> Result<Self> where Self: Sized, B: Buf,111     fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
112     where
113         Self: Sized,
114         B: Buf,
115     {
116         if raw_packet.remaining() < XR_HEADER_LENGTH {
117             return Err(error::Error::PacketTooShort.into());
118         }
119 
120         let xr_header = XRHeader::unmarshal(raw_packet)?;
121         let block_length = xr_header.block_length * 4;
122         if block_length < PRT_REPORT_BLOCK_MIN_LENGTH
123             || (block_length - PRT_REPORT_BLOCK_MIN_LENGTH) % 4 != 0
124             || raw_packet.remaining() < block_length as usize
125         {
126             return Err(error::Error::PacketTooShort.into());
127         }
128 
129         let t = xr_header.type_specific & 0x0F;
130 
131         let ssrc = raw_packet.get_u32();
132         let begin_seq = raw_packet.get_u16();
133         let end_seq = raw_packet.get_u16();
134 
135         let remaining = block_length - PRT_REPORT_BLOCK_MIN_LENGTH;
136         let mut receipt_time = vec![];
137         for _ in 0..remaining / 4 {
138             receipt_time.push(raw_packet.get_u32());
139         }
140 
141         Ok(PacketReceiptTimesReportBlock {
142             t,
143 
144             ssrc,
145             begin_seq,
146             end_seq,
147             receipt_time,
148         })
149     }
150 }
151