|
1 | 1 | use super::*;
|
2 | 2 |
|
| 3 | +const SSR_REPORT_BLOCK_LENGTH: u16 = 4 + 2 * 2 + 4 * 6 + 4; |
| 4 | + |
3 | 5 | /// StatisticsSummaryReportBlock encodes a Statistics Summary Report
|
4 | 6 | /// Block as described in RFC 3611, section 4.6.
|
5 | 7 | ///
|
@@ -28,11 +30,13 @@ use super::*;
|
28 | 30 | /// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
29 | 31 | #[derive(Debug, Default, PartialEq, Clone)]
|
30 | 32 | pub struct StatisticsSummaryReportBlock {
|
31 |
| - pub xr_header: XRHeader, |
| 33 | + //not included in marshal/unmarshal |
32 | 34 | pub loss_reports: bool,
|
33 | 35 | pub duplicate_reports: bool,
|
34 | 36 | pub jitter_reports: bool,
|
35 | 37 | pub ttl_or_hop_limit: TTLorHopLimitType,
|
| 38 | + |
| 39 | + //marshal/unmarshal |
36 | 40 | pub ssrc: u32,
|
37 | 41 | pub begin_seq: u16,
|
38 | 42 | pub end_seq: u16,
|
@@ -90,49 +94,148 @@ impl fmt::Display for TTLorHopLimitType {
|
90 | 94 | }
|
91 | 95 | }
|
92 | 96 |
|
93 |
| -impl ReportBlock for StatisticsSummaryReportBlock { |
94 |
| - /// destination_ssrc returns an array of ssrc values that this report block refers to. |
95 |
| - fn destination_ssrc(&self) -> Vec<u32> { |
96 |
| - vec![self.ssrc] |
97 |
| - } |
98 |
| - |
99 |
| - fn setup_block_header(&mut self) { |
100 |
| - self.xr_header.block_type = ReportBlockType::StatisticsSummary; |
101 |
| - self.xr_header.type_specific = 0x00; |
| 97 | +impl StatisticsSummaryReportBlock { |
| 98 | + pub fn xr_header(&self) -> XRHeader { |
| 99 | + let mut type_specific = 0x00; |
102 | 100 | if self.loss_reports {
|
103 |
| - self.xr_header.type_specific |= 0x80; |
| 101 | + type_specific |= 0x80; |
104 | 102 | }
|
105 | 103 | if self.duplicate_reports {
|
106 |
| - self.xr_header.type_specific |= 0x40; |
| 104 | + type_specific |= 0x40; |
107 | 105 | }
|
108 | 106 | if self.jitter_reports {
|
109 |
| - self.xr_header.type_specific |= 0x20; |
| 107 | + type_specific |= 0x20; |
| 108 | + } |
| 109 | + type_specific |= (self.ttl_or_hop_limit as u8 & 0x03) << 3; |
| 110 | + |
| 111 | + XRHeader { |
| 112 | + block_type: BlockType::StatisticsSummary, |
| 113 | + type_specific, |
| 114 | + block_length: (self.raw_size() / 4 - 1) as u16, |
110 | 115 | }
|
111 |
| - self.xr_header.type_specific |= (self.ttl_or_hop_limit as u8 & 0x03) << 3; |
112 |
| - self.xr_header.block_length = (self.raw_size() / 4 - 1) as u16; |
113 | 116 | }
|
| 117 | +} |
114 | 118 |
|
115 |
| - fn unpack_block_header(&mut self) { |
116 |
| - self.loss_reports = self.xr_header.type_specific & 0x80 != 0; |
117 |
| - self.duplicate_reports = self.xr_header.type_specific & 0x40 != 0; |
118 |
| - self.jitter_reports = self.xr_header.type_specific & 0x20 != 0; |
119 |
| - self.ttl_or_hop_limit = ((self.xr_header.type_specific & 0x18) >> 3).into(); |
| 119 | +impl Packet for StatisticsSummaryReportBlock { |
| 120 | + fn header(&self) -> Header { |
| 121 | + Header::default() |
| 122 | + } |
| 123 | + |
| 124 | + /// destination_ssrc returns an array of ssrc values that this report block refers to. |
| 125 | + fn destination_ssrc(&self) -> Vec<u32> { |
| 126 | + vec![self.ssrc] |
120 | 127 | }
|
121 | 128 |
|
122 | 129 | fn raw_size(&self) -> usize {
|
123 |
| - 4 + 3 + 1 + 4 + 2 * 2 + 4 * 6 + 4 |
| 130 | + XR_HEADER_LENGTH + SSR_REPORT_BLOCK_LENGTH as usize |
124 | 131 | }
|
125 | 132 |
|
126 | 133 | fn as_any(&self) -> &(dyn Any + Send + Sync) {
|
127 | 134 | self
|
128 | 135 | }
|
129 |
| - fn equal(&self, other: &(dyn ReportBlock + Send + Sync)) -> bool { |
| 136 | + fn equal(&self, other: &(dyn Packet + Send + Sync)) -> bool { |
130 | 137 | other
|
131 | 138 | .as_any()
|
132 | 139 | .downcast_ref::<StatisticsSummaryReportBlock>()
|
133 | 140 | .map_or(false, |a| self == a)
|
134 | 141 | }
|
135 |
| - fn cloned(&self) -> Box<dyn ReportBlock + Send + Sync> { |
| 142 | + fn cloned(&self) -> Box<dyn Packet + Send + Sync> { |
136 | 143 | Box::new(self.clone())
|
137 | 144 | }
|
138 | 145 | }
|
| 146 | + |
| 147 | +impl MarshalSize for StatisticsSummaryReportBlock { |
| 148 | + fn marshal_size(&self) -> usize { |
| 149 | + self.raw_size() |
| 150 | + } |
| 151 | +} |
| 152 | + |
| 153 | +impl Marshal for StatisticsSummaryReportBlock { |
| 154 | + /// marshal_to encodes the StatisticsSummaryReportBlock in binary |
| 155 | + fn marshal_to(&self, mut buf: &mut [u8]) -> Result<usize> { |
| 156 | + if buf.remaining_mut() < self.marshal_size() { |
| 157 | + return Err(error::Error::BufferTooShort.into()); |
| 158 | + } |
| 159 | + |
| 160 | + let h = self.xr_header(); |
| 161 | + let n = h.marshal_to(buf)?; |
| 162 | + buf = &mut buf[n..]; |
| 163 | + |
| 164 | + buf.put_u32(self.ssrc); |
| 165 | + buf.put_u16(self.begin_seq); |
| 166 | + buf.put_u16(self.end_seq); |
| 167 | + buf.put_u32(self.lost_packets); |
| 168 | + buf.put_u32(self.dup_packets); |
| 169 | + buf.put_u32(self.min_jitter); |
| 170 | + buf.put_u32(self.max_jitter); |
| 171 | + buf.put_u32(self.mean_jitter); |
| 172 | + buf.put_u32(self.dev_jitter); |
| 173 | + buf.put_u8(self.min_ttl_or_hl); |
| 174 | + buf.put_u8(self.max_ttl_or_hl); |
| 175 | + buf.put_u8(self.mean_ttl_or_hl); |
| 176 | + buf.put_u8(self.dev_ttl_or_hl); |
| 177 | + |
| 178 | + Ok(self.marshal_size()) |
| 179 | + } |
| 180 | +} |
| 181 | + |
| 182 | +impl Unmarshal for StatisticsSummaryReportBlock { |
| 183 | + /// Unmarshal decodes the StatisticsSummaryReportBlock from binary |
| 184 | + fn unmarshal<B>(raw_packet: &mut B) -> Result<Self> |
| 185 | + where |
| 186 | + Self: Sized, |
| 187 | + B: Buf, |
| 188 | + { |
| 189 | + if raw_packet.remaining() < XR_HEADER_LENGTH { |
| 190 | + return Err(error::Error::PacketTooShort.into()); |
| 191 | + } |
| 192 | + |
| 193 | + let xr_header = XRHeader::unmarshal(raw_packet)?; |
| 194 | + |
| 195 | + if xr_header.block_length != SSR_REPORT_BLOCK_LENGTH |
| 196 | + || raw_packet.remaining() < xr_header.block_length as usize |
| 197 | + { |
| 198 | + return Err(error::Error::PacketTooShort.into()); |
| 199 | + } |
| 200 | + |
| 201 | + let loss_reports = xr_header.type_specific & 0x80 != 0; |
| 202 | + let duplicate_reports = xr_header.type_specific & 0x40 != 0; |
| 203 | + let jitter_reports = xr_header.type_specific & 0x20 != 0; |
| 204 | + let ttl_or_hop_limit: TTLorHopLimitType = ((xr_header.type_specific & 0x18) >> 3).into(); |
| 205 | + |
| 206 | + let ssrc = raw_packet.get_u32(); |
| 207 | + let begin_seq = raw_packet.get_u16(); |
| 208 | + let end_seq = raw_packet.get_u16(); |
| 209 | + let lost_packets = raw_packet.get_u32(); |
| 210 | + let dup_packets = raw_packet.get_u32(); |
| 211 | + let min_jitter = raw_packet.get_u32(); |
| 212 | + let max_jitter = raw_packet.get_u32(); |
| 213 | + let mean_jitter = raw_packet.get_u32(); |
| 214 | + let dev_jitter = raw_packet.get_u32(); |
| 215 | + let min_ttl_or_hl = raw_packet.get_u8(); |
| 216 | + let max_ttl_or_hl = raw_packet.get_u8(); |
| 217 | + let mean_ttl_or_hl = raw_packet.get_u8(); |
| 218 | + let dev_ttl_or_hl = raw_packet.get_u8(); |
| 219 | + |
| 220 | + Ok(StatisticsSummaryReportBlock { |
| 221 | + loss_reports, |
| 222 | + duplicate_reports, |
| 223 | + jitter_reports, |
| 224 | + ttl_or_hop_limit, |
| 225 | + |
| 226 | + ssrc, |
| 227 | + begin_seq, |
| 228 | + end_seq, |
| 229 | + lost_packets, |
| 230 | + dup_packets, |
| 231 | + min_jitter, |
| 232 | + max_jitter, |
| 233 | + mean_jitter, |
| 234 | + dev_jitter, |
| 235 | + min_ttl_or_hl, |
| 236 | + max_ttl_or_hl, |
| 237 | + mean_ttl_or_hl, |
| 238 | + dev_ttl_or_hl, |
| 239 | + }) |
| 240 | + } |
| 241 | +} |
0 commit comments