Skip to content
File

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

rust92 lines
1use super::{chunk_header::*, chunk_type::*, *};
2 
3use alloc::string::ToString;
4 
5///Abort represents an SCTP Chunk of type ABORT
6///
7///The ABORT chunk is sent to the peer of an association to close the
8///association. The ABORT chunk may contain Cause Parameters to inform
9///the receiver about the reason of the abort. DATA chunks MUST NOT be
10///bundled with ABORT. Control chunks (except for INIT, INIT ACK, and
11///SHUTDOWN COMPLETE) MAY be bundled with an ABORT, but they MUST be
12///placed before the ABORT in the SCTP packet or they will be ignored by
13///the receiver.
14///
15/// 0 1 2 3
16/// 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
17///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
18///| Type = 6 |Reserved |T| Length |
19///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
20///| |
21///| zero or more Error Causes |
22///| |
23///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24#[derive(Default, Debug, Clone)]
25pub(crate) struct ChunkAbort {
26 pub(crate) error_causes: Vec<ErrorCause>,
27}
28 
29/// String makes chunkAbort printable
30impl fmt::Display for ChunkAbort {
31 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
32 let mut res = vec![self.header().to_string()];
33 
34 for cause in &self.error_causes {
35 res.push(format!(" - {}", cause));
36 }
37 
38 write!(f, "{}", res.join("\n"))
39 }
40}
41 
42impl Chunk for ChunkAbort {
43 fn header(&self) -> ChunkHeader {
44 ChunkHeader {
45 typ: CT_ABORT,
46 flags: 0,
47 value_length: self.value_length() as u16,
48 }
49 }
50 
51 fn unmarshal(raw: &Bytes) -> Result<Self> {
52 let header = ChunkHeader::unmarshal(raw)?;
53 
54 if header.typ != CT_ABORT {
55 return Err(Error::ErrChunkTypeNotAbort);
56 }
57 
58 let value_end = CHUNK_HEADER_SIZE + header.value_length();
59 let mut error_causes = vec![];
60 let mut offset = CHUNK_HEADER_SIZE;
61 while offset + ERROR_CAUSE_HEADER_LENGTH <= value_end {
62 let e = ErrorCause::unmarshal(&raw.slice(offset..value_end))?;
63 offset += e.length();
64 error_causes.push(e);
65 }
66 
67 Ok(ChunkAbort { error_causes })
68 }
69 
70 fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize> {
71 self.header().marshal_to(buf)?;
72 for ec in &self.error_causes {
73 buf.extend(ec.marshal());
74 }
75 Ok(buf.len())
76 }
77 
78 fn check(&self) -> Result<()> {
79 Ok(())
80 }
81 
82 fn value_length(&self) -> usize {
83 self.error_causes
84 .iter()
85 .fold(0, |length, ec| length + ec.length())
86 }
87 
88 fn as_any(&self) -> &(dyn Any + Send + Sync) {
89 self
90 }
91}