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