rtc_sctp/queue/
reassembly_queue.rs1use crate::StreamId;
2use crate::chunk::chunk_payload_data::{ChunkPayloadData, PayloadProtocolIdentifier};
3use crate::util::*;
4use shared::error::{Error, Result};
5
6use bytes::{Bytes, BytesMut};
7use std::collections::VecDeque;
8use std::time::Instant;
9
10#[derive(Debug, PartialEq)]
12pub struct Chunk {
13 pub bytes: Bytes,
15}
16
17#[derive(Debug, Clone)]
19pub struct Chunks {
20 pub ssn: u16,
22 pub ppi: PayloadProtocolIdentifier,
24 pub chunks: Vec<ChunkPayloadData>,
26 offset: usize,
27 index: usize,
28 timestamp: Instant,
29}
30
31impl Chunks {
32 pub fn is_empty(&self) -> bool {
34 self.len() == 0
35 }
36
37 pub fn len(&self) -> usize {
39 let mut l = 0;
40 for c in &self.chunks {
41 l += c.user_data.len();
42 }
43 l
44 }
45
46 pub fn to_payload(&self, max_len: usize) -> Result<BytesMut> {
56 let total = self.len();
57 if total > max_len {
58 return Err(Error::ErrShortBuffer);
59 }
60 let mut buf = BytesMut::with_capacity(total);
61 for c in &self.chunks {
62 buf.extend_from_slice(&c.user_data);
63 }
64 Ok(buf)
65 }
66
67 pub fn read(&self, buf: &mut [u8]) -> Result<usize> {
74 let mut n_written = 0;
75 for c in &self.chunks {
76 let to_copy = c.user_data.len();
77 let n = std::cmp::min(to_copy, buf.len() - n_written);
78 buf[n_written..n_written + n].copy_from_slice(&c.user_data[..n]);
79 n_written += n;
80 if n < to_copy {
81 return Err(Error::ErrShortBuffer);
82 }
83 }
84 Ok(n_written)
85 }
86
87 pub fn next(&mut self, max_length: usize) -> Option<Chunk> {
92 if self.index >= self.chunks.len() {
93 return None;
94 }
95
96 let mut buf = BytesMut::with_capacity(max_length);
97
98 let mut n_written = 0;
99 while self.index < self.chunks.len() {
100 let to_copy = self.chunks[self.index].user_data[self.offset..].len();
101 let n = std::cmp::min(to_copy, max_length - n_written);
102 buf.extend_from_slice(&self.chunks[self.index].user_data[self.offset..self.offset + n]);
103 n_written += n;
104 if n < to_copy {
105 self.offset += n;
106 return Some(Chunk {
107 bytes: buf.freeze(),
108 });
109 }
110 self.index += 1;
111 self.offset = 0;
112 }
113
114 Some(Chunk {
115 bytes: buf.freeze(),
116 })
117 }
118
119 pub(crate) fn new(
120 ssn: u16,
121 ppi: PayloadProtocolIdentifier,
122 chunks: Vec<ChunkPayloadData>,
123 ) -> Self {
124 Chunks {
125 ssn,
126 ppi,
127 chunks,
128 offset: 0,
129 index: 0,
130 timestamp: Instant::now(),
131 }
132 }
133
134 pub(crate) fn push(&mut self, chunk: ChunkPayloadData) -> bool {
135 let idx = self.chunks.partition_point(|c| sna32lt(c.tsn, chunk.tsn));
139 if idx < self.chunks.len() && self.chunks[idx].tsn == chunk.tsn {
140 return false;
141 }
142 self.chunks.insert(idx, chunk);
143
144 self.is_complete()
146 }
147
148 pub(crate) fn is_complete(&self) -> bool {
149 let n_chunks = self.chunks.len();
157 if n_chunks == 0 {
158 return false;
159 }
160
161 if !self.chunks[0].beginning_fragment {
163 return false;
164 }
165
166 if !self.chunks[n_chunks - 1].ending_fragment {
168 return false;
169 }
170
171 let mut last_tsn = 0u32;
173 for (i, c) in self.chunks.iter().enumerate() {
174 if i > 0 {
175 if c.tsn != last_tsn + 1 {
182 return false;
184 }
185 }
186
187 last_tsn = c.tsn;
188 }
189
190 true
191 }
192}
193
194#[derive(Default, Debug)]
195pub(crate) struct ReassemblyQueue {
196 pub(crate) si: StreamId,
197 pub(crate) next_ssn: u16,
198 pub(crate) ordered: VecDeque<Chunks>,
203 pub(crate) unordered: VecDeque<Chunks>,
204 pub(crate) unordered_chunks: Vec<ChunkPayloadData>,
205 pub(crate) n_bytes: usize,
206}
207
208impl ReassemblyQueue {
209 pub(crate) fn new(si: StreamId) -> Self {
215 ReassemblyQueue {
216 si,
217 next_ssn: 0, ordered: VecDeque::new(),
219 unordered: VecDeque::new(),
220 unordered_chunks: vec![],
221 n_bytes: 0,
222 }
223 }
224
225 pub(crate) fn push(&mut self, chunk: ChunkPayloadData) -> bool {
226 if chunk.stream_identifier != self.si {
227 return false;
228 }
229
230 if chunk.unordered {
231 self.n_bytes += chunk.user_data.len();
234 let idx = self
235 .unordered_chunks
236 .partition_point(|c| sna32lt(c.tsn, chunk.tsn));
237 self.unordered_chunks.insert(idx, chunk);
238
239 if let Some(cset) = self.find_complete_unordered_chunk_set() {
242 self.unordered.push_back(cset);
243 return true;
244 }
245
246 false
247 } else {
248 if sna16lt(chunk.stream_sequence_number, self.next_ssn) {
250 return false;
251 }
252
253 self.n_bytes += chunk.user_data.len();
254
255 let ssn = chunk.stream_sequence_number;
259 let idx = self.ordered.partition_point(|s| sna16lt(s.ssn, ssn));
260 if let Some(s) = self.ordered.get_mut(idx)
261 && s.ssn == ssn
262 {
263 return s.push(chunk);
264 }
265
266 let mut cset = Chunks::new(ssn, chunk.payload_type, vec![]);
269 let ok = cset.push(chunk);
270 self.ordered.insert(idx, cset);
271
272 ok
273 }
274 }
275
276 pub(crate) fn find_complete_unordered_chunk_set(&mut self) -> Option<Chunks> {
277 let mut start_idx = -1isize;
278 let mut n_chunks = 0usize;
279 let mut last_tsn = 0u32;
280 let mut found = false;
281
282 for (i, c) in self.unordered_chunks.iter().enumerate() {
283 if c.beginning_fragment {
285 start_idx = i as isize;
286 n_chunks = 1;
287 last_tsn = c.tsn;
288
289 if c.ending_fragment {
290 found = true;
291 break;
292 }
293 continue;
294 }
295
296 if start_idx < 0 {
297 continue;
298 }
299
300 if c.tsn != last_tsn + 1 {
302 start_idx = -1;
303 continue;
304 }
305
306 last_tsn = c.tsn;
307 n_chunks += 1;
308
309 if c.ending_fragment {
310 found = true;
311 break;
312 }
313 }
314
315 if !found {
316 return None;
317 }
318
319 let chunks: Vec<ChunkPayloadData> = self
321 .unordered_chunks
322 .drain(start_idx as usize..(start_idx as usize) + n_chunks)
323 .collect();
324 Some(Chunks::new(0, chunks[0].payload_type, chunks))
325 }
326
327 pub(crate) fn is_readable(&self) -> bool {
328 if !self.unordered.is_empty() {
330 return true;
332 }
333
334 if !self.ordered.is_empty() {
336 let cset = &self.ordered[0];
337 if cset.is_complete() && sna16lte(cset.ssn, self.next_ssn) {
338 return true;
339 }
340 }
341 false
342 }
343
344 fn readable_unordered_chunks(&self) -> Option<&Chunks> {
345 self.unordered.front()
346 }
347
348 fn readable_ordered_chunks(&self) -> Option<&Chunks> {
349 let ordered = self.ordered.front();
350 if let Some(chunks) = ordered {
351 if !chunks.is_complete() {
352 return None;
353 }
354 if sna16gt(chunks.ssn, self.next_ssn) {
355 return None;
356 }
357 Some(chunks)
358 } else {
359 None
360 }
361 }
362
363 pub(crate) fn read(&mut self) -> Option<Chunks> {
364 let chunks = if let (Some(unordered_chunks), Some(ordered_chunks)) = (
365 self.readable_unordered_chunks(),
366 self.readable_ordered_chunks(),
367 ) {
368 if unordered_chunks.timestamp < ordered_chunks.timestamp {
369 self.unordered.pop_front().unwrap()
370 } else {
371 if ordered_chunks.ssn == self.next_ssn {
372 self.next_ssn = self.next_ssn.wrapping_add(1);
373 }
374 self.ordered.pop_front().unwrap()
375 }
376 } else {
377 if !self.unordered.is_empty() {
379 self.unordered.pop_front().unwrap()
380 } else if !self.ordered.is_empty() {
381 let chunks = &self.ordered[0];
383 if !chunks.is_complete() {
384 return None;
385 }
386 if sna16gt(chunks.ssn, self.next_ssn) {
387 return None;
388 }
389 if chunks.ssn == self.next_ssn {
390 self.next_ssn = self.next_ssn.wrapping_add(1);
391 }
392 self.ordered.pop_front().unwrap()
393 } else {
394 return None;
395 }
396 };
397
398 self.subtract_num_bytes(chunks.len());
399
400 Some(chunks)
401 }
402
403 pub(crate) fn forward_tsn_for_ordered(&mut self, last_ssn: u16) {
406 let num_bytes = self
407 .ordered
408 .iter()
409 .filter(|s| sna16lte(s.ssn, last_ssn) && !s.is_complete())
410 .fold(0, |n, s| {
411 n + s.chunks.iter().fold(0, |acc, c| acc + c.user_data.len())
412 });
413 self.subtract_num_bytes(num_bytes);
414
415 self.ordered
416 .retain(|s| !sna16lte(s.ssn, last_ssn) || s.is_complete());
417
418 if sna16lte(self.next_ssn, last_ssn) {
420 self.next_ssn = last_ssn.wrapping_add(1);
421 }
422 }
423
424 pub(crate) fn forward_tsn_for_unordered(&mut self, new_cumulative_tsn: u32) {
430 let mut last_idx: isize = -1;
431 for (i, c) in self.unordered_chunks.iter().enumerate() {
432 if sna32gt(c.tsn, new_cumulative_tsn) {
433 break;
434 }
435 last_idx = i as isize;
436 }
437 if last_idx >= 0 {
438 for i in 0..(last_idx + 1) as usize {
439 self.subtract_num_bytes(self.unordered_chunks[i].user_data.len());
440 }
441 self.unordered_chunks.drain(..(last_idx + 1) as usize);
442 }
443 }
444
445 pub(crate) fn subtract_num_bytes(&mut self, n_bytes: usize) {
446 if self.n_bytes >= n_bytes {
447 self.n_bytes -= n_bytes;
448 } else {
449 self.n_bytes = 0;
450 }
451 }
452
453 pub(crate) fn get_num_bytes(&self) -> usize {
454 self.n_bytes
455 }
456}