1use super::{chunk_header::*, chunk_type::*, *};
2
3use bytes::{Buf, BufMut, Bytes, BytesMut};
4use std::fmt;
5use std::time::Instant;
6
7pub(crate) const PAYLOAD_DATA_ENDING_FRAGMENT_BITMASK: u8 = 1;
8pub(crate) const PAYLOAD_DATA_BEGINING_FRAGMENT_BITMASK: u8 = 2;
9pub(crate) const PAYLOAD_DATA_UNORDERED_BITMASK: u8 = 4;
10pub(crate) const PAYLOAD_DATA_IMMEDIATE_SACK: u8 = 8;
11pub(crate) const PAYLOAD_DATA_HEADER_SIZE: usize = 12;
12
13#[derive(Default, Debug, Copy, Clone, PartialEq)]
17#[repr(C)]
18pub enum PayloadProtocolIdentifier {
19 Dcep = 50,
20 String = 51,
21 Binary = 53,
22 StringEmpty = 56,
23 BinaryEmpty = 57,
24 #[default]
25 Unknown,
26}
27
28impl fmt::Display for PayloadProtocolIdentifier {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 let s = match *self {
31 PayloadProtocolIdentifier::Dcep => "WebRTC DCEP",
32 PayloadProtocolIdentifier::String => "WebRTC String",
33 PayloadProtocolIdentifier::Binary => "WebRTC Binary",
34 PayloadProtocolIdentifier::StringEmpty => "WebRTC String (Empty)",
35 PayloadProtocolIdentifier::BinaryEmpty => "WebRTC Binary (Empty)",
36 _ => "Unknown Payload Protocol Identifier",
37 };
38 write!(f, "{}", s)
39 }
40}
41
42impl From<u32> for PayloadProtocolIdentifier {
43 fn from(v: u32) -> PayloadProtocolIdentifier {
44 match v {
45 50 => PayloadProtocolIdentifier::Dcep,
46 51 => PayloadProtocolIdentifier::String,
47 53 => PayloadProtocolIdentifier::Binary,
48 56 => PayloadProtocolIdentifier::StringEmpty,
49 57 => PayloadProtocolIdentifier::BinaryEmpty,
50 _ => PayloadProtocolIdentifier::Unknown,
51 }
52 }
53}
54
55#[derive(Debug, Clone)]
90pub struct ChunkPayloadData {
91 pub(crate) unordered: bool,
92 pub(crate) beginning_fragment: bool,
93 pub(crate) ending_fragment: bool,
94 pub(crate) immediate_sack: bool,
95
96 pub(crate) tsn: u32,
97 pub(crate) stream_identifier: u16,
98 pub(crate) stream_sequence_number: u16,
99 pub(crate) payload_type: PayloadProtocolIdentifier,
100 pub(crate) user_data: Bytes,
101
102 pub(crate) acked: bool,
104 pub(crate) miss_indicator: u32,
105
106 pub(crate) since: Option<Instant>,
108 pub(crate) nsent: u32,
110
111 pub(crate) abandoned: bool,
113 pub(crate) all_inflight: bool,
115
116 pub(crate) retransmit: bool,
119}
120
121impl Default for ChunkPayloadData {
122 fn default() -> Self {
123 ChunkPayloadData {
124 unordered: false,
125 beginning_fragment: false,
126 ending_fragment: false,
127 immediate_sack: false,
128 tsn: 0,
129 stream_identifier: 0,
130 stream_sequence_number: 0,
131 payload_type: PayloadProtocolIdentifier::default(),
132 user_data: Bytes::new(),
133 acked: false,
134 miss_indicator: 0,
135 since: None,
136 nsent: 0,
137 abandoned: false,
138 all_inflight: false,
139 retransmit: false,
140 }
141 }
142}
143
144impl fmt::Display for ChunkPayloadData {
146 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
147 write!(f, "{}\n{}", self.header(), self.tsn)
148 }
149}
150
151impl Chunk for ChunkPayloadData {
152 fn header(&self) -> ChunkHeader {
153 let mut flags: u8 = 0;
154 if self.ending_fragment {
155 flags = 1;
156 }
157 if self.beginning_fragment {
158 flags |= 1 << 1;
159 }
160 if self.unordered {
161 flags |= 1 << 2;
162 }
163 if self.immediate_sack {
164 flags |= 1 << 3;
165 }
166
167 ChunkHeader {
168 typ: CT_PAYLOAD_DATA,
169 flags,
170 value_length: self.value_length() as u16,
171 }
172 }
173
174 fn unmarshal(raw: &Bytes) -> Result<Self> {
175 let header = ChunkHeader::unmarshal(raw)?;
176
177 if header.typ != CT_PAYLOAD_DATA {
178 return Err(Error::ErrChunkTypeNotPayloadData);
179 }
180
181 let immediate_sack = (header.flags & PAYLOAD_DATA_IMMEDIATE_SACK) != 0;
182 let unordered = (header.flags & PAYLOAD_DATA_UNORDERED_BITMASK) != 0;
183 let beginning_fragment = (header.flags & PAYLOAD_DATA_BEGINING_FRAGMENT_BITMASK) != 0;
184 let ending_fragment = (header.flags & PAYLOAD_DATA_ENDING_FRAGMENT_BITMASK) != 0;
185
186 if raw.len() < PAYLOAD_DATA_HEADER_SIZE {
187 return Err(Error::ErrChunkPayloadSmall);
188 }
189
190 let reader = &mut raw.slice(CHUNK_HEADER_SIZE..CHUNK_HEADER_SIZE + header.value_length());
191
192 let tsn = reader.get_u32();
193 let stream_identifier = reader.get_u16();
194 let stream_sequence_number = reader.get_u16();
195 let payload_type: PayloadProtocolIdentifier = reader.get_u32().into();
196 let user_data = raw.slice(
197 CHUNK_HEADER_SIZE + PAYLOAD_DATA_HEADER_SIZE..CHUNK_HEADER_SIZE + header.value_length(),
198 );
199
200 Ok(ChunkPayloadData {
201 unordered,
202 beginning_fragment,
203 ending_fragment,
204 immediate_sack,
205 tsn,
206 stream_identifier,
207 stream_sequence_number,
208 payload_type,
209 user_data,
210
211 acked: false,
212 miss_indicator: 0,
213 since: None,
214 nsent: 0,
215 abandoned: false,
216 all_inflight: false,
217 retransmit: false,
218 })
219 }
220
221 fn marshal_to(&self, writer: &mut BytesMut) -> Result<usize> {
222 self.header().marshal_to(writer)?;
223
224 writer.put_u32(self.tsn);
225 writer.put_u16(self.stream_identifier);
226 writer.put_u16(self.stream_sequence_number);
227 writer.put_u32(self.payload_type as u32);
228 writer.extend(self.user_data.clone());
229
230 Ok(writer.len())
231 }
232
233 fn check(&self) -> Result<()> {
234 Ok(())
235 }
236
237 fn value_length(&self) -> usize {
238 PAYLOAD_DATA_HEADER_SIZE + self.user_data.len()
239 }
240
241 fn as_any(&self) -> &(dyn Any) {
242 self
243 }
244}
245
246impl ChunkPayloadData {
247 pub(crate) fn abandoned(&self) -> bool {
248 self.abandoned && self.all_inflight
249 }
250
251 pub(crate) fn set_abandoned(&mut self, abandoned: bool) {
252 self.abandoned = abandoned;
253 }
254
255 pub(crate) fn set_all_inflight(&mut self) {
256 if self.ending_fragment {
257 self.all_inflight = true;
258 }
259 }
260}