Skip to main content

rtc_rtcp/extended_report/
ssr.rs

1use super::*;
2
3const SSR_REPORT_BLOCK_LENGTH: u16 = 4 + 2 * 2 + 4 * 6 + 4;
4
5/// StatisticsSummaryReportBlock encodes a Statistics Summary Report
6/// Block as described in RFC 3611, section 4.6.
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=6      |L|D|J|ToH|rsvd.|       block length = 9        |
12/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
13/// |                        ssrc of source                         |
14/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15/// |          begin_seq            |             end_seq           |
16/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17/// |                        lost_packets                           |
18/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19/// |                        dup_packets                            |
20/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21/// |                         min_jitter                            |
22/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23/// |                         max_jitter                            |
24/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25/// |                         mean_jitter                           |
26/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27/// |                         dev_jitter                            |
28/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
29/// | min_ttl_or_hl | max_ttl_or_hl |mean_ttl_or_hl | dev_ttl_or_hl |
30/// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31#[derive(Debug, Default, PartialEq, Eq, Clone)]
32pub struct StatisticsSummaryReportBlock {
33    //not included in marshal/unmarshal
34    pub loss_reports: bool,
35    pub duplicate_reports: bool,
36    pub jitter_reports: bool,
37    pub ttl_or_hop_limit: TTLorHopLimitType,
38
39    //marshal/unmarshal
40    pub ssrc: u32,
41    pub begin_seq: u16,
42    pub end_seq: u16,
43    pub lost_packets: u32,
44    pub dup_packets: u32,
45    pub min_jitter: u32,
46    pub max_jitter: u32,
47    pub mean_jitter: u32,
48    pub dev_jitter: u32,
49    pub min_ttl_or_hl: u8,
50    pub max_ttl_or_hl: u8,
51    pub mean_ttl_or_hl: u8,
52    pub dev_ttl_or_hl: u8,
53}
54
55impl fmt::Display for StatisticsSummaryReportBlock {
56    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
57        write!(f, "{self:?}")
58    }
59}
60
61/// TTLorHopLimitType encodes values for the ToH field in
62/// a StatisticsSummaryReportBlock
63#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
64pub enum TTLorHopLimitType {
65    #[default]
66    Missing = 0,
67    IPv4 = 1,
68    IPv6 = 2,
69}
70
71impl From<u8> for TTLorHopLimitType {
72    fn from(v: u8) -> Self {
73        match v {
74            1 => TTLorHopLimitType::IPv4,
75            2 => TTLorHopLimitType::IPv6,
76            _ => TTLorHopLimitType::Missing,
77        }
78    }
79}
80
81impl fmt::Display for TTLorHopLimitType {
82    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83        let s = match *self {
84            TTLorHopLimitType::Missing => "[ToH Missing]",
85            TTLorHopLimitType::IPv4 => "[ToH = IPv4]",
86            TTLorHopLimitType::IPv6 => "[ToH = IPv6]",
87        };
88        write!(f, "{s}")
89    }
90}
91
92impl StatisticsSummaryReportBlock {
93    pub fn xr_header(&self) -> XRHeader {
94        let mut type_specific = 0x00;
95        if self.loss_reports {
96            type_specific |= 0x80;
97        }
98        if self.duplicate_reports {
99            type_specific |= 0x40;
100        }
101        if self.jitter_reports {
102            type_specific |= 0x20;
103        }
104        type_specific |= (self.ttl_or_hop_limit as u8 & 0x03) << 3;
105
106        XRHeader {
107            block_type: BlockType::StatisticsSummary,
108            type_specific,
109            block_length: (self.raw_size() / 4 - 1) as u16,
110        }
111    }
112}
113
114impl Packet for StatisticsSummaryReportBlock {
115    fn header(&self) -> Header {
116        Header::default()
117    }
118
119    /// destination_ssrc returns an array of ssrc values that this report block refers to.
120    fn destination_ssrc(&self) -> Vec<u32> {
121        vec![self.ssrc]
122    }
123
124    fn raw_size(&self) -> usize {
125        XR_HEADER_LENGTH + SSR_REPORT_BLOCK_LENGTH as usize
126    }
127
128    fn as_any(&self) -> &dyn Any {
129        self
130    }
131    fn equal(&self, other: &dyn Packet) -> bool {
132        other
133            .as_any()
134            .downcast_ref::<StatisticsSummaryReportBlock>()
135            == Some(self)
136    }
137    fn cloned(&self) -> Box<dyn Packet> {
138        Box::new(self.clone())
139    }
140}
141
142impl MarshalSize for StatisticsSummaryReportBlock {
143    fn marshal_size(&self) -> usize {
144        self.raw_size()
145    }
146}
147
148impl Marshal for StatisticsSummaryReportBlock {
149    /// marshal_to encodes the StatisticsSummaryReportBlock in binary
150    fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> {
151        if buf.remaining_mut() < self.marshal_size() {
152            return Err(Error::BufferTooShort);
153        }
154
155        let h = self.xr_header();
156        let n = h.marshal_to(buf)?;
157        buf = &mut buf[n..];
158
159        buf.put_u32(self.ssrc);
160        buf.put_u16(self.begin_seq);
161        buf.put_u16(self.end_seq);
162        buf.put_u32(self.lost_packets);
163        buf.put_u32(self.dup_packets);
164        buf.put_u32(self.min_jitter);
165        buf.put_u32(self.max_jitter);
166        buf.put_u32(self.mean_jitter);
167        buf.put_u32(self.dev_jitter);
168        buf.put_u8(self.min_ttl_or_hl);
169        buf.put_u8(self.max_ttl_or_hl);
170        buf.put_u8(self.mean_ttl_or_hl);
171        buf.put_u8(self.dev_ttl_or_hl);
172
173        Ok(self.marshal_size())
174    }
175}
176
177impl Unmarshal for StatisticsSummaryReportBlock {
178    /// Unmarshal decodes the StatisticsSummaryReportBlock from binary
179    fn unmarshal<B>(raw_packet: &mut B) -> Result<Self>
180    where
181        Self: Sized,
182        B: Buf,
183    {
184        if raw_packet.remaining() < XR_HEADER_LENGTH {
185            return Err(Error::PacketTooShort);
186        }
187
188        let xr_header = XRHeader::unmarshal(raw_packet)?;
189        let block_length = match xr_header.block_length.checked_mul(4) {
190            Some(length) => length,
191            None => return Err(Error::InvalidBlockSize),
192        };
193        if block_length != SSR_REPORT_BLOCK_LENGTH || raw_packet.remaining() < block_length as usize
194        {
195            return Err(Error::PacketTooShort);
196        }
197
198        let loss_reports = xr_header.type_specific & 0x80 != 0;
199        let duplicate_reports = xr_header.type_specific & 0x40 != 0;
200        let jitter_reports = xr_header.type_specific & 0x20 != 0;
201        let ttl_or_hop_limit: TTLorHopLimitType = ((xr_header.type_specific & 0x18) >> 3).into();
202
203        let ssrc = raw_packet.get_u32();
204        let begin_seq = raw_packet.get_u16();
205        let end_seq = raw_packet.get_u16();
206        let lost_packets = raw_packet.get_u32();
207        let dup_packets = raw_packet.get_u32();
208        let min_jitter = raw_packet.get_u32();
209        let max_jitter = raw_packet.get_u32();
210        let mean_jitter = raw_packet.get_u32();
211        let dev_jitter = raw_packet.get_u32();
212        let min_ttl_or_hl = raw_packet.get_u8();
213        let max_ttl_or_hl = raw_packet.get_u8();
214        let mean_ttl_or_hl = raw_packet.get_u8();
215        let dev_ttl_or_hl = raw_packet.get_u8();
216
217        Ok(StatisticsSummaryReportBlock {
218            loss_reports,
219            duplicate_reports,
220            jitter_reports,
221            ttl_or_hop_limit,
222
223            ssrc,
224            begin_seq,
225            end_seq,
226            lost_packets,
227            dup_packets,
228            min_jitter,
229            max_jitter,
230            mean_jitter,
231            dev_jitter,
232            min_ttl_or_hl,
233            max_ttl_or_hl,
234            mean_ttl_or_hl,
235            dev_ttl_or_hl,
236        })
237    }
238}