Skip to content
File

Blob: firmware/vendor/sctp-proto/src/chunk/chunk_forward_tsn.rs

rust180 lines
1use super::{chunk_header::*, chunk_type::*, *};
2 
3use alloc::string::ToString;
4 
5///This chunk shall be used by the data sender to inform the data
6///receiver to adjust its cumulative received TSN point forward because
7///some missing TSNs are associated with data chunks that SHOULD NOT be
8///transmitted or retransmitted by the sender.
9/// 0 1 2 3
10/// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
11///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
12///| Type = 192 | Flags = 0x00 | Length = Variable |
13///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
14///| New Cumulative TSN |
15///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16///| Stream-1 | Stream Sequence-1 |
17///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18///| |
19///| |
20///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21///| Stream-N | Stream Sequence-N |
22///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23#[derive(Default, Debug, Clone)]
24pub(crate) struct ChunkForwardTsn {
25 /// This indicates the new cumulative TSN to the data receiver. Upon
26 /// the reception of this value, the data receiver MUST consider
27 /// any missing TSNs earlier than or equal to this value as received,
28 /// and stop reporting them as gaps in any subsequent SACKs.
29 pub(crate) new_cumulative_tsn: u32,
30 pub(crate) streams: Vec<ChunkForwardTsnStream>,
31}
32 
33pub(crate) const NEW_CUMULATIVE_TSN_LENGTH: usize = 4;
34pub(crate) const FORWARD_TSN_STREAM_LENGTH: usize = 4;
35 
36/// makes ChunkForwardTsn printable
37impl fmt::Display for ChunkForwardTsn {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 let mut res = vec![self.header().to_string()];
40 res.push(format!("New Cumulative TSN: {}", self.new_cumulative_tsn));
41 for s in &self.streams {
42 res.push(format!(" - si={}, ssn={}", s.identifier, s.sequence));
43 }
44 
45 write!(f, "{}", res.join("\n"))
46 }
47}
48 
49impl Chunk for ChunkForwardTsn {
50 fn header(&self) -> ChunkHeader {
51 ChunkHeader {
52 typ: CT_FORWARD_TSN,
53 flags: 0,
54 value_length: self.value_length() as u16,
55 }
56 }
57 
58 fn unmarshal(buf: &Bytes) -> Result<Self> {
59 let header = ChunkHeader::unmarshal(buf)?;
60 
61 if header.typ != CT_FORWARD_TSN {
62 return Err(Error::ErrChunkTypeNotForwardTsn);
63 }
64 
65 if header.value_length() < NEW_CUMULATIVE_TSN_LENGTH {
66 return Err(Error::ErrChunkTooShort);
67 }
68 
69 let mut offset = CHUNK_HEADER_SIZE + NEW_CUMULATIVE_TSN_LENGTH;
70 let reader = &mut buf.slice(CHUNK_HEADER_SIZE..CHUNK_HEADER_SIZE + header.value_length());
71 let new_cumulative_tsn = reader.get_u32();
72 
73 let mut streams = vec![];
74 let value_end = CHUNK_HEADER_SIZE + header.value_length();
75 let mut remaining = value_end - offset;
76 while remaining > 0 {
77 let s = ChunkForwardTsnStream::unmarshal(&buf.slice(offset..value_end))?;
78 offset += s.value_length();
79 remaining -= s.value_length();
80 streams.push(s);
81 }
82 
83 Ok(ChunkForwardTsn {
84 new_cumulative_tsn,
85 streams,
86 })
87 }
88 
89 fn marshal_to(&self, writer: &mut BytesMut) -> Result<usize> {
90 self.header().marshal_to(writer)?;
91 
92 writer.put_u32(self.new_cumulative_tsn);
93 
94 for s in &self.streams {
95 writer.extend(s.marshal()?);
96 }
97 
98 Ok(writer.len())
99 }
100 
101 fn check(&self) -> Result<()> {
102 Ok(())
103 }
104 
105 fn value_length(&self) -> usize {
106 NEW_CUMULATIVE_TSN_LENGTH + FORWARD_TSN_STREAM_LENGTH * self.streams.len()
107 }
108 
109 fn as_any(&self) -> &(dyn Any + Send + Sync) {
110 self
111 }
112}
113 
114#[derive(Debug, Clone)]
115pub(crate) struct ChunkForwardTsnStream {
116 /// This field holds a stream number that was skipped by this
117 /// FWD-TSN.
118 pub(crate) identifier: u16,
119 
120 /// This field holds the sequence number associated with the stream
121 /// that was skipped. The stream sequence field holds the largest
122 /// stream sequence number in this stream being skipped. The receiver
123 /// of the FWD-TSN's can use the Stream-N and Stream Sequence-N fields
124 /// to enable delivery of any stranded TSN's that remain on the stream
125 /// re-ordering queues. This field MUST NOT report TSN's corresponding
126 /// to DATA chunks that are marked as unordered. For ordered DATA
127 /// chunks this field MUST be filled in.
128 pub(crate) sequence: u16,
129}
130 
131/// makes ChunkForwardTsnStream printable
132impl fmt::Display for ChunkForwardTsnStream {
133 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134 write!(f, "{}, {}", self.identifier, self.sequence)
135 }
136}
137 
138impl Chunk for ChunkForwardTsnStream {
139 fn header(&self) -> ChunkHeader {
140 ChunkHeader {
141 typ: ChunkType(0),
142 flags: 0,
143 value_length: self.value_length() as u16,
144 }
145 }
146 
147 fn unmarshal(buf: &Bytes) -> Result<Self> {
148 if buf.len() < FORWARD_TSN_STREAM_LENGTH {
149 return Err(Error::ErrChunkTooShort);
150 }
151 
152 let reader = &mut buf.clone();
153 let identifier = reader.get_u16();
154 let sequence = reader.get_u16();
155 
156 Ok(ChunkForwardTsnStream {
157 identifier,
158 sequence,
159 })
160 }
161 
162 fn marshal_to(&self, writer: &mut BytesMut) -> Result<usize> {
163 writer.put_u16(self.identifier);
164 writer.put_u16(self.sequence);
165 Ok(writer.len())
166 }
167 
168 fn check(&self) -> Result<()> {
169 Ok(())
170 }
171 
172 fn value_length(&self) -> usize {
173 FORWARD_TSN_STREAM_LENGTH
174 }
175 
176 fn as_any(&self) -> &(dyn Any + Send + Sync) {
177 self
178 }
179}