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,
21 String = 51,
23 Binary = 53,
25 StringEmpty = 56,
29 BinaryEmpty = 57,
31 #[default]
32 Unknown,
34}
35
36impl fmt::Display for PayloadProtocolIdentifier {
37 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38 let s = match *self {
39 PayloadProtocolIdentifier::Dcep => "WebRTC DCEP",
40 PayloadProtocolIdentifier::String => "WebRTC String",
41 PayloadProtocolIdentifier::Binary => "WebRTC Binary",
42 PayloadProtocolIdentifier::StringEmpty => "WebRTC String (Empty)",
43 PayloadProtocolIdentifier::BinaryEmpty => "WebRTC Binary (Empty)",
44 _ => "Unknown Payload Protocol Identifier",
45 };
46 write!(f, "{}", s)
47 }
48}
49
50impl From<u32> for PayloadProtocolIdentifier {
51 fn from(v: u32) -> PayloadProtocolIdentifier {
52 match v {
53 50 => PayloadProtocolIdentifier::Dcep,
54 51 => PayloadProtocolIdentifier::String,
55 53 => PayloadProtocolIdentifier::Binary,
56 56 => PayloadProtocolIdentifier::StringEmpty,
57 57 => PayloadProtocolIdentifier::BinaryEmpty,
58 _ => PayloadProtocolIdentifier::Unknown,
59 }
60 }
61}
62
63#[derive(Debug, Clone)]
98pub struct ChunkPayloadData {
99 pub(crate) unordered: bool,
100 pub(crate) beginning_fragment: bool,
101 pub(crate) ending_fragment: bool,
102 pub(crate) immediate_sack: bool,
103
104 pub(crate) tsn: u32,
105 pub(crate) stream_identifier: u16,
106 pub(crate) stream_sequence_number: u16,
107 pub(crate) payload_type: PayloadProtocolIdentifier,
108 pub(crate) user_data: Bytes,
109
110 pub(crate) acked: bool,
112 pub(crate) miss_indicator: u32,
113
114 pub(crate) since: Option<Instant>,
116 pub(crate) nsent: u32,
118
119 pub(crate) abandoned: bool,
121 pub(crate) all_inflight: bool,
123
124 pub(crate) retransmit: bool,
127}
128
129impl Default for ChunkPayloadData {
130 fn default() -> Self {
131 ChunkPayloadData {
132 unordered: false,
133 beginning_fragment: false,
134 ending_fragment: false,
135 immediate_sack: false,
136 tsn: 0,
137 stream_identifier: 0,
138 stream_sequence_number: 0,
139 payload_type: PayloadProtocolIdentifier::default(),
140 user_data: Bytes::new(),
141 acked: false,
142 miss_indicator: 0,
143 since: None,
144 nsent: 0,
145 abandoned: false,
146 all_inflight: false,
147 retransmit: false,
148 }
149 }
150}
151
152impl fmt::Display for ChunkPayloadData {
154 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
155 write!(f, "{}\n{}", self.header(), self.tsn)
156 }
157}
158
159impl Chunk for ChunkPayloadData {
160 fn header(&self) -> ChunkHeader {
161 let mut flags: u8 = 0;
162 if self.ending_fragment {
163 flags = 1;
164 }
165 if self.beginning_fragment {
166 flags |= 1 << 1;
167 }
168 if self.unordered {
169 flags |= 1 << 2;
170 }
171 if self.immediate_sack {
172 flags |= 1 << 3;
173 }
174
175 ChunkHeader {
176 typ: CT_PAYLOAD_DATA,
177 flags,
178 value_length: self.value_length() as u16,
179 }
180 }
181
182 fn unmarshal(raw: &Bytes) -> Result<Self> {
183 let header = ChunkHeader::unmarshal(raw)?;
184
185 if header.typ != CT_PAYLOAD_DATA {
186 return Err(Error::ErrChunkTypeNotPayloadData);
187 }
188
189 let immediate_sack = (header.flags & PAYLOAD_DATA_IMMEDIATE_SACK) != 0;
190 let unordered = (header.flags & PAYLOAD_DATA_UNORDERED_BITMASK) != 0;
191 let beginning_fragment = (header.flags & PAYLOAD_DATA_BEGINING_FRAGMENT_BITMASK) != 0;
192 let ending_fragment = (header.flags & PAYLOAD_DATA_ENDING_FRAGMENT_BITMASK) != 0;
193
194 if raw.len() < CHUNK_HEADER_SIZE + PAYLOAD_DATA_HEADER_SIZE {
195 return Err(Error::ErrChunkPayloadSmall);
196 }
197
198 if header.value_length() < PAYLOAD_DATA_HEADER_SIZE {
199 return Err(Error::ErrChunkUnmarshalPayloadData);
200 }
201
202 let reader = &mut raw.slice(CHUNK_HEADER_SIZE..CHUNK_HEADER_SIZE + header.value_length());
203
204 let tsn = reader.get_u32();
205 let stream_identifier = reader.get_u16();
206 let stream_sequence_number = reader.get_u16();
207 let payload_type: PayloadProtocolIdentifier = reader.get_u32().into();
208 let user_data = raw.slice(
209 CHUNK_HEADER_SIZE + PAYLOAD_DATA_HEADER_SIZE..CHUNK_HEADER_SIZE + header.value_length(),
210 );
211
212 Ok(ChunkPayloadData {
213 unordered,
214 beginning_fragment,
215 ending_fragment,
216 immediate_sack,
217 tsn,
218 stream_identifier,
219 stream_sequence_number,
220 payload_type,
221 user_data,
222
223 acked: false,
224 miss_indicator: 0,
225 since: None,
226 nsent: 0,
227 abandoned: false,
228 all_inflight: false,
229 retransmit: false,
230 })
231 }
232
233 fn marshal_to(&self, writer: &mut BytesMut) -> Result<usize> {
234 self.header().marshal_to(writer)?;
235
236 writer.put_u32(self.tsn);
237 writer.put_u16(self.stream_identifier);
238 writer.put_u16(self.stream_sequence_number);
239 writer.put_u32(self.payload_type as u32);
240 writer.extend_from_slice(&self.user_data);
243
244 Ok(writer.len())
245 }
246
247 fn check(&self) -> Result<()> {
248 Ok(())
249 }
250
251 fn value_length(&self) -> usize {
252 PAYLOAD_DATA_HEADER_SIZE + self.user_data.len()
253 }
254
255 fn as_any(&self) -> &dyn Any {
256 self
257 }
258}
259
260impl ChunkPayloadData {
261 pub(crate) fn abandoned(&self) -> bool {
262 self.abandoned && self.all_inflight
263 }
264
265 pub(crate) fn set_abandoned(&mut self, abandoned: bool) {
266 self.abandoned = abandoned;
267 }
268
269 pub(crate) fn set_all_inflight(&mut self) {
270 if self.ending_fragment {
271 self.all_inflight = true;
272 }
273 }
274}