Skip to content
File

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

rust94 lines
1use super::{chunk_header::*, chunk_type::*, *};
2 
3use alloc::string::ToString;
4 
5///Operation Error (ERROR) (9)
6///
7///An endpoint sends this chunk to its peer endpoint to notify it of
8///certain error conditions. It contains one or more error causes. An
9///Operation Error is not considered fatal in and of itself, but may be
10///used with an ERROR chunk to report a fatal condition. It has the
11///following parameters:
12/// 0 1 2 3
13/// 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
14///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
15///| Type = 9 | Chunk Flags | Length |
16///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17///| |
18///| one or more Error Causes |
19///| |
20///+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
21///Chunk Flags: 8 bits
22/// Set to 0 on transmit and ignored on receipt.
23///Length: 16 bits (unsigned integer)
24/// Set to the size of the chunk in bytes, including the chunk header
25/// and all the Error Cause fields present.
26#[derive(Default, Debug, Clone)]
27pub(crate) struct ChunkError {
28 pub(crate) error_causes: Vec<ErrorCause>,
29}
30 
31/// makes ChunkError printable
32impl fmt::Display for ChunkError {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 let mut res = vec![self.header().to_string()];
35 
36 for cause in &self.error_causes {
37 res.push(format!(" - {}", cause));
38 }
39 
40 write!(f, "{}", res.join("\n"))
41 }
42}
43 
44impl Chunk for ChunkError {
45 fn header(&self) -> ChunkHeader {
46 ChunkHeader {
47 typ: CT_ERROR,
48 flags: 0,
49 value_length: self.value_length() as u16,
50 }
51 }
52 
53 fn unmarshal(raw: &Bytes) -> Result<Self> {
54 let header = ChunkHeader::unmarshal(raw)?;
55 
56 if header.typ != CT_ERROR {
57 return Err(Error::ErrChunkTypeNotCt);
58 }
59 
60 let value_end = CHUNK_HEADER_SIZE + header.value_length();
61 let mut error_causes = vec![];
62 let mut offset = CHUNK_HEADER_SIZE;
63 while offset + ERROR_CAUSE_HEADER_LENGTH <= value_end {
64 let e = ErrorCause::unmarshal(&raw.slice(offset..value_end))?;
65 offset += e.length();
66 error_causes.push(e);
67 }
68 
69 Ok(ChunkError { error_causes })
70 }
71 
72 fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize> {
73 self.header().marshal_to(buf)?;
74 for ec in &self.error_causes {
75 buf.extend(ec.marshal());
76 }
77 Ok(buf.len())
78 }
79 
80 fn check(&self) -> Result<()> {
81 Ok(())
82 }
83 
84 fn value_length(&self) -> usize {
85 self.error_causes
86 .iter()
87 .fold(0, |length, ec| length + ec.length())
88 }
89 
90 fn as_any(&self) -> &(dyn Any + Send + Sync) {
91 self
92 }
93}