1use crate::association::Association;
2use crate::association::state::AssociationState;
3use crate::chunk::chunk_payload_data::{ChunkPayloadData, PayloadProtocolIdentifier};
4use crate::error::{Error, Result};
5use crate::queue::reassembly_queue::{Chunks, ReassemblyQueue};
6use crate::{ErrorCauseCode, Side};
7
8use crate::util::{ByteSlice, BytesArray, BytesSource};
9use alloc::vec;
10use alloc::vec::Vec;
11use bytes::Bytes;
12use core::fmt;
13use log::{debug, error, trace};
14
15pub type StreamId = u16;
17
18#[non_exhaustive]
20#[derive(Debug, Copy, Clone, PartialEq, Eq)]
21pub enum StreamResetError {
22 Denied,
24 Failed,
26}
27
28#[non_exhaustive]
30#[derive(Debug, PartialEq, Eq)]
31pub enum StreamEvent {
32 Opened {
34 id: StreamId,
36 },
37 Readable {
39 id: StreamId,
41 },
42 Writable {
46 id: StreamId,
48 },
49 Finished {
59 id: StreamId,
61 },
62 ResetComplete {
67 id: StreamId,
69 },
70 ResetFailed {
75 id: StreamId,
77 reason: StreamResetError,
79 },
80 Stopped {
82 id: StreamId,
84 error_code: ErrorCauseCode,
86 },
87 Available,
89 BufferedAmountLow {
91 id: StreamId,
93 },
94 BufferedAmountHigh {
96 id: StreamId,
98 },
99}
100
101#[derive(Debug, Copy, Clone, PartialEq, Default)]
103pub enum ReliabilityType {
104 #[default]
106 Reliable = 0,
107 Rexmit = 1,
109 Timed = 2,
111}
112
113impl fmt::Display for ReliabilityType {
114 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
115 let s = match *self {
116 ReliabilityType::Reliable => "Reliable",
117 ReliabilityType::Rexmit => "Rexmit",
118 ReliabilityType::Timed => "Timed",
119 };
120 write!(f, "{}", s)
121 }
122}
123
124impl From<u8> for ReliabilityType {
125 fn from(v: u8) -> ReliabilityType {
126 match v {
127 1 => ReliabilityType::Rexmit,
128 2 => ReliabilityType::Timed,
129 _ => ReliabilityType::Reliable,
130 }
131 }
132}
133
134pub struct Stream<'a> {
136 pub(crate) stream_identifier: StreamId,
137 pub(crate) association: &'a mut Association,
138}
139
140impl<'a> Stream<'a> {
141 pub fn read(&mut self) -> Result<Option<Chunks>> {
145 self.read_sctp()
146 }
147
148 pub fn read_sctp(&mut self) -> Result<Option<Chunks>> {
153 let (message, drained) =
154 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
155 if s.state != RecvSendState::ReadWritable && s.state != RecvSendState::Readable {
156 return Err(Error::ErrStreamClosed);
157 }
158
159 let message = s.reassembly_queue.read();
160 let drained = message.is_some() && s.reassembly_queue.get_num_bytes() == 0;
161 (message, drained)
162 } else {
163 return Err(Error::ErrStreamClosed);
164 };
165
166 if drained {
167 self.association
168 .finish_retiring_stream(self.stream_identifier)?;
169 }
170
171 Ok(message)
172 }
173
174 pub fn write_sctp(&mut self, p: &Bytes, ppi: PayloadProtocolIdentifier) -> Result<usize> {
176 self.write_source(&mut ByteSlice::from_slice(p), ppi)
177 }
178
179 pub fn write(&mut self, data: &[u8]) -> Result<usize> {
185 self.write_with_ppi(data, self.get_default_payload_type()?)
186 }
187
188 pub fn write_with_ppi(&mut self, data: &[u8], ppi: PayloadProtocolIdentifier) -> Result<usize> {
192 self.write_source(&mut ByteSlice::from_slice(data), ppi)
193 }
194
195 pub fn write_chunk(&mut self, p: &Bytes) -> Result<usize> {
197 self.write_source(
198 &mut ByteSlice::from_slice(p),
199 self.get_default_payload_type()?,
200 )
201 }
202
203 pub fn write_chunks(&mut self, data: &mut [Bytes]) -> Result<usize> {
210 self.write_source(
211 &mut BytesArray::from_chunks(data),
212 self.get_default_payload_type()?,
213 )
214 }
215
216 fn write_source<B: BytesSource>(
218 &mut self,
219 source: &mut B,
220 ppi: PayloadProtocolIdentifier,
221 ) -> Result<usize> {
222 if !self.is_writable() {
223 return Err(Error::ErrStreamClosed);
224 }
225
226 if source.remaining() > self.association.max_send_message_size() as usize {
227 return Err(Error::ErrOutboundPacketTooLarge);
228 }
229
230 let state: AssociationState = self.association.state();
231 match state {
232 AssociationState::ShutdownSent
233 | AssociationState::ShutdownAckSent
234 | AssociationState::ShutdownPending
235 | AssociationState::ShutdownReceived => return Err(Error::ErrStreamClosed),
236 _ => {}
237 };
238
239 let (p, _) = source.pop_chunk(self.association.max_send_message_size() as usize);
240
241 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
242 let (is_buffered_amount_high, chunks) = s.packetize(&p, ppi);
243 self.association.send_payload_data(chunks)?;
244
245 if is_buffered_amount_high {
246 trace!("StreamEvent::BufferedAmountHigh");
247 self.association
248 .events
249 .push_back(crate::association::Event::Stream(
250 StreamEvent::BufferedAmountHigh {
251 id: self.stream_identifier,
252 },
253 ));
254 }
255
256 Ok(p.len())
257 } else {
258 Err(Error::ErrStreamClosed)
259 }
260 }
261
262 pub fn is_readable(&self) -> bool {
263 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
264 s.state == RecvSendState::Readable || s.state == RecvSendState::ReadWritable
265 } else {
266 false
267 }
268 }
269
270 pub fn is_writable(&self) -> bool {
271 if self
276 .association
277 .stream_reset_blocked(self.stream_identifier)
278 {
279 return false;
280 }
281 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
282 s.state == RecvSendState::Writable || s.state == RecvSendState::ReadWritable
283 } else {
284 false
285 }
286 }
287
288 pub fn stop(&mut self) -> Result<()> {
295 let retiring = self
296 .association
297 .retiring_streams
298 .contains_key(&self.stream_identifier);
299 let reset = self
300 .association
301 .streams
302 .get(&self.stream_identifier)
303 .is_some_and(|s| {
304 s.state == RecvSendState::Readable || s.state == RecvSendState::ReadWritable
305 });
306
307 if reset
308 && !retiring
309 && !self
310 .association
311 .stream_reset_in_progress(self.stream_identifier)
312 {
313 self.association
321 .send_reset_request(self.stream_identifier)?;
322 }
323
324 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
325 s.state = ((s.state as u8) & 0x2).into();
326 }
327
328 if retiring {
332 self.association
333 .discard_retiring_streams(self.stream_identifier);
334 }
335
336 Ok(())
337 }
338
339 pub fn finish(&mut self) -> Result<()> {
342 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
343 s.state = ((s.state as u8) & 0x1).into();
344 }
345 Ok(())
346 }
347
348 pub fn close(&mut self) -> Result<()> {
357 self.finish()?;
358 self.stop()
359 }
360
361 pub fn stream_identifier(&self) -> StreamId {
363 self.stream_identifier
364 }
365
366 pub fn set_default_payload_type(
368 &mut self,
369 default_payload_type: PayloadProtocolIdentifier,
370 ) -> Result<()> {
371 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
372 s.default_payload_type = default_payload_type;
373 Ok(())
374 } else {
375 Err(Error::ErrStreamClosed)
376 }
377 }
378
379 pub fn get_default_payload_type(&self) -> Result<PayloadProtocolIdentifier> {
381 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
382 Ok(s.default_payload_type)
383 } else {
384 Err(Error::ErrStreamClosed)
385 }
386 }
387
388 pub fn set_reliability_params(
390 &mut self,
391 unordered: bool,
392 rel_type: ReliabilityType,
393 rel_val: u32,
394 ) -> Result<()> {
395 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
396 debug!(
397 "[{}] reliability params: ordered={} type={} value={}",
398 s.side, !unordered, rel_type, rel_val
399 );
400 s.unordered = unordered;
401 s.reliability_type = rel_type;
402 s.reliability_value = rel_val;
403 Ok(())
404 } else {
405 Err(Error::ErrStreamClosed)
406 }
407 }
408
409 pub fn buffered_amount(&self) -> Result<usize> {
411 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
412 Ok(s.buffered_amount)
413 } else {
414 Err(Error::ErrStreamClosed)
415 }
416 }
417
418 pub fn buffered_amount_low_threshold(&self) -> Result<usize> {
421 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
422 Ok(s.buffered_amount_low)
423 } else {
424 Err(Error::ErrStreamClosed)
425 }
426 }
427
428 pub fn set_buffered_amount_low_threshold(&mut self, th: usize) -> Result<()> {
431 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
432 s.buffered_amount_low = th;
433 Ok(())
434 } else {
435 Err(Error::ErrStreamClosed)
436 }
437 }
438
439 pub fn buffered_amount_high_threshold(&self) -> Result<usize> {
442 if let Some(s) = self.association.streams.get(&self.stream_identifier) {
443 Ok(s.buffered_amount_high)
444 } else {
445 Err(Error::ErrStreamClosed)
446 }
447 }
448
449 pub fn set_buffered_amount_high_threshold(&mut self, th: usize) -> Result<()> {
452 if let Some(s) = self.association.streams.get_mut(&self.stream_identifier) {
453 s.buffered_amount_high = th;
454 Ok(())
455 } else {
456 Err(Error::ErrStreamClosed)
457 }
458 }
459}
460
461#[derive(Debug, Copy, Clone, Eq, PartialEq, Default)]
462pub enum RecvSendState {
463 #[default]
464 Closed = 0,
465 Readable = 1,
466 Writable = 2,
467 ReadWritable = 3,
468}
469
470impl From<u8> for RecvSendState {
471 fn from(v: u8) -> Self {
472 match v {
473 1 => RecvSendState::Readable,
474 2 => RecvSendState::Writable,
475 3 => RecvSendState::ReadWritable,
476 _ => RecvSendState::Closed,
477 }
478 }
479}
480
481#[derive(Default, Debug)]
483pub struct StreamState {
484 pub(crate) side: Side,
485 pub(crate) max_payload_size: u32,
486 pub(crate) stream_identifier: StreamId,
487 pub(crate) default_payload_type: PayloadProtocolIdentifier,
488 pub(crate) reassembly_queue: ReassemblyQueue,
489 pub(crate) sequence_number: u16,
490 pub(crate) state: RecvSendState,
491 pub(crate) unordered: bool,
492 pub(crate) reliability_type: ReliabilityType,
493 pub(crate) reliability_value: u32,
494 pub(crate) buffered_amount: usize,
495 pub(crate) buffered_amount_low: usize,
496 pub(crate) buffered_amount_high: usize,
497}
498impl StreamState {
499 pub(crate) fn new(
500 side: Side,
501 stream_identifier: StreamId,
502 max_payload_size: u32,
503 max_receive_message_size: u32,
504 default_payload_type: PayloadProtocolIdentifier,
505 ) -> Self {
506 StreamState {
507 side,
508 stream_identifier,
509 max_payload_size,
510 default_payload_type,
511 reassembly_queue: ReassemblyQueue::new(stream_identifier, max_receive_message_size),
512 sequence_number: 0,
513 state: RecvSendState::ReadWritable,
514 unordered: false,
515 reliability_type: ReliabilityType::Reliable,
516 reliability_value: 0,
517 buffered_amount: 0,
518 buffered_amount_low: 0,
519 buffered_amount_high: usize::MAX,
520 }
521 }
522
523 pub(crate) fn handle_data(&mut self, pd: &ChunkPayloadData) -> Result<bool> {
524 self.reassembly_queue.push(pd.clone())
525 }
526
527 fn packetize(
528 &mut self,
529 raw: &Bytes,
530 ppi: PayloadProtocolIdentifier,
531 ) -> (bool, Vec<ChunkPayloadData>) {
532 let mut i = 0;
533 let mut remaining = raw.len();
534
535 let unordered = ppi != PayloadProtocolIdentifier::Dcep && self.unordered;
539
540 let mut chunks = vec![];
541
542 let head_abandoned = false;
543 let head_all_inflight = false;
544 while remaining != 0 {
545 let fragment_size = core::cmp::min(self.max_payload_size as usize, remaining);
547
548 let user_data = raw.slice(i..i + fragment_size);
551
552 let chunk = ChunkPayloadData {
553 stream_identifier: self.stream_identifier,
554 user_data,
555 unordered,
556 beginning_fragment: i == 0,
557 ending_fragment: remaining - fragment_size == 0,
558 immediate_sack: false,
559 payload_type: ppi,
560 stream_sequence_number: self.sequence_number,
561 abandoned: head_abandoned, all_inflight: head_all_inflight, ..Default::default()
564 };
565
566 chunks.push(chunk);
567
568 remaining -= fragment_size;
569 i += fragment_size;
570 }
571
572 if !unordered {
577 self.sequence_number = self.sequence_number.wrapping_add(1);
578 }
579
580 let old_amount = self.buffered_amount;
581 self.buffered_amount += raw.len();
582 let new_amount = self.buffered_amount;
583
584 let is_buffered_amount_high =
586 old_amount < self.buffered_amount_high && new_amount >= self.buffered_amount_high;
587
588 (is_buffered_amount_high, chunks)
589 }
590
591 pub(crate) fn on_buffer_released(&mut self, n_bytes_released: i64) -> bool {
594 if n_bytes_released <= 0 {
595 return false;
596 }
597
598 let from_amount = self.buffered_amount;
599 let new_amount = if from_amount < n_bytes_released as usize {
600 self.buffered_amount = 0;
601 error!(
602 "[{}] released buffer size {} should be <= {}",
603 self.side, n_bytes_released, 0,
604 );
605 0
606 } else {
607 self.buffered_amount -= n_bytes_released as usize;
608
609 from_amount - n_bytes_released as usize
610 };
611
612 let buffered_amount_low = self.buffered_amount_low;
613
614 trace!(
615 "[{}] bufferedAmount = {}, from_amount = {}, buffered_amount_low = {}",
616 self.side, new_amount, from_amount, buffered_amount_low,
617 );
618
619 from_amount > buffered_amount_low && new_amount <= buffered_amount_low
620 }
621
622 pub(crate) fn get_num_bytes_in_reassembly_queue(&self) -> usize {
623 self.reassembly_queue.get_num_bytes()
625 }
626}