Skip to main content

webrtc_sctp/chunk/
chunk_error.rs

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