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