xref: /webrtc/sctp/src/error_cause.rs (revision 5d8fe953)
1 use crate::error::{Error, Result};
2 
3 use bytes::{Buf, BufMut, Bytes, BytesMut};
4 use std::fmt;
5 
6 /// errorCauseCode is a cause code that appears in either a ERROR or ABORT chunk
7 #[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
8 pub(crate) struct ErrorCauseCode(pub(crate) u16);
9 
10 pub(crate) const INVALID_STREAM_IDENTIFIER: ErrorCauseCode = ErrorCauseCode(1);
11 pub(crate) const MISSING_MANDATORY_PARAMETER: ErrorCauseCode = ErrorCauseCode(2);
12 pub(crate) const STALE_COOKIE_ERROR: ErrorCauseCode = ErrorCauseCode(3);
13 pub(crate) const OUT_OF_RESOURCE: ErrorCauseCode = ErrorCauseCode(4);
14 pub(crate) const UNRESOLVABLE_ADDRESS: ErrorCauseCode = ErrorCauseCode(5);
15 pub(crate) const UNRECOGNIZED_CHUNK_TYPE: ErrorCauseCode = ErrorCauseCode(6);
16 pub(crate) const INVALID_MANDATORY_PARAMETER: ErrorCauseCode = ErrorCauseCode(7);
17 pub(crate) const UNRECOGNIZED_PARAMETERS: ErrorCauseCode = ErrorCauseCode(8);
18 pub(crate) const NO_USER_DATA: ErrorCauseCode = ErrorCauseCode(9);
19 pub(crate) const COOKIE_RECEIVED_WHILE_SHUTTING_DOWN: ErrorCauseCode = ErrorCauseCode(10);
20 pub(crate) const RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESSES: ErrorCauseCode = ErrorCauseCode(11);
21 pub(crate) const USER_INITIATED_ABORT: ErrorCauseCode = ErrorCauseCode(12);
22 pub(crate) const PROTOCOL_VIOLATION: ErrorCauseCode = ErrorCauseCode(13);
23 
24 impl fmt::Display for ErrorCauseCode {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result25     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26         let others = format!("Unknown CauseCode: {}", self.0);
27         let s = match *self {
28             INVALID_STREAM_IDENTIFIER => "Invalid Stream Identifier",
29             MISSING_MANDATORY_PARAMETER => "Missing Mandatory Parameter",
30             STALE_COOKIE_ERROR => "Stale Cookie Error",
31             OUT_OF_RESOURCE => "Out Of Resource",
32             UNRESOLVABLE_ADDRESS => "Unresolvable IP",
33             UNRECOGNIZED_CHUNK_TYPE => "Unrecognized Chunk Type",
34             INVALID_MANDATORY_PARAMETER => "Invalid Mandatory Parameter",
35             UNRECOGNIZED_PARAMETERS => "Unrecognized Parameters",
36             NO_USER_DATA => "No User Data",
37             COOKIE_RECEIVED_WHILE_SHUTTING_DOWN => "Cookie Received While Shutting Down",
38             RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESSES => {
39                 "Restart Of An Association With New Addresses"
40             }
41             USER_INITIATED_ABORT => "User Initiated Abort",
42             PROTOCOL_VIOLATION => "Protocol Violation",
43             _ => others.as_str(),
44         };
45         write!(f, "{s}")
46     }
47 }
48 
49 /// ErrorCauseHeader represents the shared header that is shared by all error causes
50 #[derive(Debug, Clone, Default)]
51 pub(crate) struct ErrorCause {
52     pub(crate) code: ErrorCauseCode,
53     pub(crate) raw: Bytes,
54 }
55 
56 /// ErrorCauseInvalidMandatoryParameter represents an SCTP error cause
57 pub(crate) type ErrorCauseInvalidMandatoryParameter = ErrorCause;
58 
59 /// ErrorCauseUnrecognizedChunkType represents an SCTP error cause
60 pub(crate) type ErrorCauseUnrecognizedChunkType = ErrorCause;
61 
62 ///
63 /// This error cause MAY be included in ABORT chunks that are sent
64 /// because an SCTP endpoint detects a protocol violation of the peer
65 /// that is not covered by the error causes described in Section 3.3.10.1
66 /// to Section 3.3.10.12.  An implementation MAY provide additional
67 /// information specifying what kind of protocol violation has been
68 /// detected.
69 ///      0                   1                   2                   3
70 ///      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
71 ///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
72 ///     |         Cause Code=13         |      Cause Length=Variable    |
73 ///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
74 ///     /                    Additional Information                     /
75 ///     \                                                               \
76 ///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
77 ///
78 pub(crate) type ErrorCauseProtocolViolation = ErrorCause;
79 
80 pub(crate) const ERROR_CAUSE_HEADER_LENGTH: usize = 4;
81 
82 /// makes ErrorCauseHeader printable
83 impl fmt::Display for ErrorCause {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result84     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85         write!(f, "{}", self.code)
86     }
87 }
88 
89 impl ErrorCause {
unmarshal(buf: &Bytes) -> Result<Self>90     pub(crate) fn unmarshal(buf: &Bytes) -> Result<Self> {
91         if buf.len() < ERROR_CAUSE_HEADER_LENGTH {
92             return Err(Error::ErrErrorCauseTooSmall);
93         }
94 
95         let reader = &mut buf.clone();
96 
97         let code = ErrorCauseCode(reader.get_u16());
98         let len = reader.get_u16();
99 
100         if len < ERROR_CAUSE_HEADER_LENGTH as u16 {
101             return Err(Error::ErrErrorCauseTooSmall);
102         }
103         if buf.len() < len as usize {
104             return Err(Error::ErrErrorCauseTooSmall);
105         }
106 
107         let value_length = len as usize - ERROR_CAUSE_HEADER_LENGTH;
108 
109         let raw = buf.slice(ERROR_CAUSE_HEADER_LENGTH..ERROR_CAUSE_HEADER_LENGTH + value_length);
110 
111         Ok(ErrorCause { code, raw })
112     }
113 
marshal(&self) -> Bytes114     pub(crate) fn marshal(&self) -> Bytes {
115         let mut buf = BytesMut::with_capacity(self.length());
116         let _ = self.marshal_to(&mut buf);
117         buf.freeze()
118     }
119 
marshal_to(&self, writer: &mut BytesMut) -> usize120     pub(crate) fn marshal_to(&self, writer: &mut BytesMut) -> usize {
121         let len = self.raw.len() + ERROR_CAUSE_HEADER_LENGTH;
122         writer.put_u16(self.code.0);
123         writer.put_u16(len as u16);
124         writer.extend(self.raw.clone());
125         writer.len()
126     }
127 
length(&self) -> usize128     pub(crate) fn length(&self) -> usize {
129         self.raw.len() + ERROR_CAUSE_HEADER_LENGTH
130     }
131 
error_cause_code(&self) -> ErrorCauseCode132     pub(crate) fn error_cause_code(&self) -> ErrorCauseCode {
133         self.code
134     }
135 }
136