1use crate::association::Association;
2use crate::association::state::AssociationState;
3use crate::chunk::chunk_payload_data::{ChunkPayloadData, PayloadProtocolIdentifier};
4use crate::queue::reassembly_queue::{Chunks, ReassemblyQueue};
5use crate::{ErrorCauseCode, Event, Side};
6use shared::error::{Error, Result};
7
8use crate::util::{ByteSlice, BytesArray, BytesChunk, BytesSource};
9use bytes::Bytes;
10use log::{debug, error, trace};
11use std::fmt;
12
13pub type StreamId = u16;
15
16#[derive(Debug, PartialEq, Eq)]
18#[non_exhaustive]
19pub enum StreamEvent {
20 Opened {
22 id: StreamId,
24 },
25 Readable {
27 id: StreamId,
29 },
30 Writable {
34 id: StreamId,
36 },
37 Finished {
39 id: StreamId,
41 },
42 Stopped {
44 id: StreamId,
46 error_code: ErrorCauseCode,
48 },
49 Available,
51 BufferedAmountLow {
53 id: StreamId,
55 },
56 BufferedAmountHigh {
58 id: StreamId,
60 },
61 BufferedAmountReleased {
67 id: StreamId,
69 n_bytes: usize,
71 },
72}
73
74#[derive(Default, Debug, Copy, Clone, PartialEq)]
76pub enum ReliabilityType {
77 #[default]
79 Reliable = 0,
80 Rexmit = 1,
82 Timed = 2,
84}
85
86impl fmt::Display for ReliabilityType {
87 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
88 let s = match *self {
89 ReliabilityType::Reliable => "Reliable",
90 ReliabilityType::Rexmit => "Rexmit",
91 ReliabilityType::Timed => "Timed",
92 };
93 write!(f, "{}", s)
94 }
95}
96
97impl From<u8> for ReliabilityType {
98 fn from(v: u8) -> ReliabilityType {
99 match v {
100 1 => ReliabilityType::Rexmit,
101 2 => ReliabilityType::Timed,
102 _ => ReliabilityType::Reliable,
103 }
104 }
105}
106
107pub struct Stream<'a> {
109 pub(crate) stream_identifier: StreamId,
110 pub(crate) association: &'a mut Association,
111}
112
113impl Stream<'_> {
114 pub fn read(&mut self) -> Result<Option<Chunks>> {
118 self.read_sctp()
119 }
120
121 pub fn read_sctp(&mut self) -> Result<Option<Chunks>> {
126 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier)
127 && (s.state == RecvSendState::ReadWritable || s.state == RecvSendState::Readable)
128 {
129 Ok(s.reassembly_queue.read())
130 } else {
131 Err(Error::ErrStreamClosed)
132 }
133 }
134
135 pub fn write_sctp(&mut self, p: &Bytes, ppi: PayloadProtocolIdentifier) -> Result<usize> {
137 self.write_source(&mut BytesChunk::new(p), ppi)
138 }
139
140 pub fn write(&mut self, data: &[u8]) -> Result<usize> {
146 self.write_with_ppi(data, self.get_default_payload_type()?)
147 }
148
149 pub fn write_with_ppi(&mut self, data: &[u8], ppi: PayloadProtocolIdentifier) -> Result<usize> {
153 self.write_source(&mut ByteSlice::from_slice(data), ppi)
154 }
155
156 pub fn write_chunk(&mut self, p: &Bytes) -> Result<usize> {
158 self.write_source(&mut BytesChunk::new(p), self.get_default_payload_type()?)
159 }
160
161 pub fn write_chunk_with_ppi(
170 &mut self,
171 data: &Bytes,
172 ppi: PayloadProtocolIdentifier,
173 ) -> Result<usize> {
174 self.write_source(&mut BytesChunk::new(data), ppi)
175 }
176
177 pub fn write_chunks(&mut self, data: &mut [Bytes]) -> Result<usize> {
184 self.write_source(
185 &mut BytesArray::from_chunks(data),
186 self.get_default_payload_type()?,
187 )
188 }
189
190 fn write_source<B: BytesSource>(
192 &mut self,
193 source: &mut B,
194 ppi: PayloadProtocolIdentifier,
195 ) -> Result<usize> {
196 if !self.is_writable() {
197 return Err(Error::ErrStreamClosed);
198 }
199
200 if source.remaining() > self.association.max_message_size() as usize {
201 return Err(Error::ErrOutboundPacketTooLarge);
202 }
203
204 let state: AssociationState = self.association.state();
205 match state {
206 AssociationState::ShutdownSent
207 | AssociationState::ShutdownAckSent
208 | AssociationState::ShutdownPending
209 | AssociationState::ShutdownReceived => return Err(Error::ErrStreamClosed),
210 _ => {}
211 };
212
213 let (p, _) = source.pop_chunk(self.association.max_message_size() as usize);
214
215 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
216 let (is_buffered_amount_high, chunks) = s.packetize(&p, ppi);
217
218 if is_buffered_amount_high {
219 trace!("StreamEvent::BufferedAmountHigh");
220 self.association
221 .events
222 .push_back(Event::Stream(StreamEvent::BufferedAmountHigh {
223 id: self.stream_identifier,
224 }))
225 }
226
227 self.association.send_payload_data(chunks)?;
228
229 Ok(p.len())
230 } else {
231 Err(Error::ErrStreamClosed)
232 }
233 }
234
235 pub fn is_readable(&self) -> bool {
237 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
238 s.state == RecvSendState::Readable || s.state == RecvSendState::ReadWritable
239 } else {
240 false
241 }
242 }
243
244 pub fn is_writable(&self) -> bool {
246 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
247 s.state == RecvSendState::Writable || s.state == RecvSendState::ReadWritable
248 } else {
249 false
250 }
251 }
252
253 pub fn stop(&mut self) -> Result<()> {
256 let mut reset = false;
257 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
258 if s.state == RecvSendState::Readable || s.state == RecvSendState::ReadWritable {
259 reset = true;
260 }
261 s.state = ((s.state as u8) & 0x2).into();
262 }
263
264 if reset {
265 self.association
268 .send_reset_request(self.stream_identifier)?;
269 }
270
271 Ok(())
272 }
273
274 pub fn finish(&mut self) -> Result<()> {
277 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
278 s.state = ((s.state as u8) & 0x1).into();
279 }
280 Ok(())
281 }
282
283 pub fn close(&mut self) -> Result<()> {
290 self.finish()?;
291 self.stop()
292 }
293
294 pub fn stream_identifier(&self) -> StreamId {
296 self.stream_identifier
297 }
298
299 pub fn set_default_payload_type(
301 &mut self,
302 default_payload_type: PayloadProtocolIdentifier,
303 ) -> Result<()> {
304 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
305 s.default_payload_type = default_payload_type;
306 Ok(())
307 } else {
308 Err(Error::ErrStreamClosed)
309 }
310 }
311
312 pub fn get_default_payload_type(&self) -> Result<PayloadProtocolIdentifier> {
314 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
315 Ok(s.default_payload_type)
316 } else {
317 Err(Error::ErrStreamClosed)
318 }
319 }
320
321 pub fn set_reliability_params(
323 &mut self,
324 unordered: bool,
325 rel_type: ReliabilityType,
326 rel_val: u32,
327 ) -> Result<()> {
328 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
329 debug!(
330 "[{}] reliability params: ordered={} type={} value={}",
331 s.side, !unordered, rel_type, rel_val
332 );
333 s.unordered = unordered;
334 s.reliability_type = rel_type;
335 s.reliability_value = rel_val;
336 Ok(())
337 } else {
338 Err(Error::ErrStreamClosed)
339 }
340 }
341
342 pub fn buffered_amount(&self) -> Result<usize> {
344 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
345 Ok(s.buffered_amount)
346 } else {
347 Err(Error::ErrStreamClosed)
348 }
349 }
350
351 pub fn buffered_amount_low_threshold(&self) -> Result<usize> {
354 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
355 Ok(s.buffered_amount_low)
356 } else {
357 Err(Error::ErrStreamClosed)
358 }
359 }
360
361 pub fn set_buffered_amount_low_threshold(&mut self, th: usize) -> Result<()> {
364 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
365 s.buffered_amount_low = th;
366 Ok(())
367 } else {
368 Err(Error::ErrStreamClosed)
369 }
370 }
371
372 pub fn buffered_amount_high_threshold(&self) -> Result<usize> {
375 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
376 Ok(s.buffered_amount_high)
377 } else {
378 Err(Error::ErrStreamClosed)
379 }
380 }
381
382 pub fn set_buffered_amount_high_threshold(&mut self, th: usize) -> Result<()> {
385 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
386 s.buffered_amount_high = th;
387 Ok(())
388 } else {
389 Err(Error::ErrStreamClosed)
390 }
391 }
392}
393
394#[derive(Default, Debug, Copy, Clone, Eq, PartialEq)]
395pub enum RecvSendState {
396 #[default]
397 Closed = 0,
398 Readable = 1,
399 Writable = 2,
400 ReadWritable = 3,
401}
402
403impl From<u8> for RecvSendState {
404 fn from(v: u8) -> Self {
405 match v {
406 1 => RecvSendState::Readable,
407 2 => RecvSendState::Writable,
408 3 => RecvSendState::ReadWritable,
409 _ => RecvSendState::Closed,
410 }
411 }
412}
413
414#[derive(Default, Debug)]
416pub struct StreamState {
417 pub(crate) side: Side,
418 pub(crate) max_payload_size: u32,
419 pub(crate) stream_identifier: StreamId,
420 pub(crate) default_payload_type: PayloadProtocolIdentifier,
421 pub(crate) reassembly_queue: ReassemblyQueue,
422 pub(crate) sequence_number: u16,
423 pub(crate) state: RecvSendState,
424 pub(crate) unordered: bool,
425 pub(crate) reliability_type: ReliabilityType,
426 pub(crate) reliability_value: u32,
427 pub(crate) buffered_amount: usize,
428 pub(crate) buffered_amount_low: usize,
429 pub(crate) buffered_amount_high: usize,
430}
431impl StreamState {
432 pub(crate) fn new(
433 side: Side,
434 stream_identifier: StreamId,
435 max_payload_size: u32,
436 default_payload_type: PayloadProtocolIdentifier,
437 ) -> Self {
438 StreamState {
439 side,
440 stream_identifier,
441 max_payload_size,
442 default_payload_type,
443 reassembly_queue: ReassemblyQueue::new(stream_identifier),
444 sequence_number: 0,
445 state: RecvSendState::ReadWritable,
446 unordered: false,
447 reliability_type: ReliabilityType::Reliable,
448 reliability_value: 0,
449 buffered_amount: 0,
450 buffered_amount_low: 0,
451 buffered_amount_high: u32::MAX as usize,
452 }
453 }
454
455 pub(crate) fn handle_data(&mut self, pd: &ChunkPayloadData) -> bool {
456 self.reassembly_queue.push(pd.clone())
457 }
458
459 pub(crate) fn handle_forward_tsn_for_ordered(&mut self, ssn: u16) {
460 if self.unordered {
461 return; }
463
464 self.reassembly_queue.forward_tsn_for_ordered(ssn);
467 }
468
469 pub(crate) fn handle_forward_tsn_for_unordered(&mut self, new_cumulative_tsn: u32) {
470 if !self.unordered {
471 return; }
473
474 self.reassembly_queue
477 .forward_tsn_for_unordered(new_cumulative_tsn);
478 }
479
480 fn packetize(
481 &mut self,
482 raw: &Bytes,
483 ppi: PayloadProtocolIdentifier,
484 ) -> (bool, Vec<ChunkPayloadData>) {
485 let mut i = 0;
486 let mut remaining = raw.len();
487
488 let unordered = ppi != PayloadProtocolIdentifier::Dcep && self.unordered;
492
493 let mut chunks = vec![];
494
495 let head_abandoned = false;
496 let head_all_inflight = false;
497 while remaining != 0 {
498 let fragment_size = std::cmp::min(self.max_payload_size as usize, remaining); let user_data = raw.slice(i..i + fragment_size);
503
504 let chunk = ChunkPayloadData {
505 stream_identifier: self.stream_identifier,
506 user_data,
507 unordered,
508 beginning_fragment: i == 0,
509 ending_fragment: remaining - fragment_size == 0,
510 immediate_sack: false,
511 payload_type: ppi,
512 stream_sequence_number: self.sequence_number,
513 abandoned: head_abandoned, all_inflight: head_all_inflight, ..Default::default()
516 };
517
518 chunks.push(chunk);
519
520 remaining -= fragment_size;
521 i += fragment_size;
522 }
523
524 if !unordered {
529 self.sequence_number = self.sequence_number.wrapping_add(1);
530 }
531
532 let old_amount = self.buffered_amount;
533 let n_bytes_added = raw.len();
534 self.buffered_amount += raw.len();
535 let new_amount = self.buffered_amount;
536
537 trace!(
538 "[{}] new_amount = {}, old_amount = {}, buffered_amount_high = {}, n_bytes_added = {}",
539 self.side, new_amount, old_amount, self.buffered_amount_high, n_bytes_added,
540 );
541
542 let is_buffered_amount_high =
543 old_amount < self.buffered_amount_high && new_amount >= self.buffered_amount_high;
544
545 (is_buffered_amount_high, chunks)
546 }
547
548 pub(crate) fn on_buffer_released(&mut self, n_bytes_released: i64) -> bool {
551 if n_bytes_released <= 0 {
552 return false;
553 }
554
555 let old_amount = self.buffered_amount;
556 let new_amount = if old_amount < n_bytes_released as usize {
557 self.buffered_amount = 0;
558 error!(
559 "[{}] released buffer size {} should be <= {}",
560 self.side, n_bytes_released, 0,
561 );
562 0
563 } else {
564 self.buffered_amount -= n_bytes_released as usize;
565
566 old_amount - n_bytes_released as usize
567 };
568
569 trace!(
570 "[{}] new_amount = {}, old_amount = {}, buffered_amount_low = {}, n_bytes_released = {}",
571 self.side, new_amount, old_amount, self.buffered_amount_low, n_bytes_released,
572 );
573
574 old_amount > self.buffered_amount_low && new_amount <= self.buffered_amount_low
575 }
576
577 pub(crate) fn get_num_bytes_in_reassembly_queue(&self) -> usize {
578 self.reassembly_queue.get_num_bytes()
580 }
581}