sctp_proto/chunk/
mod.rs

1#[cfg(test)]
2mod chunk_test;
3
4pub(crate) mod chunk_abort;
5pub(crate) mod chunk_cookie_ack;
6pub(crate) mod chunk_cookie_echo;
7pub(crate) mod chunk_error;
8pub(crate) mod chunk_forward_tsn;
9pub(crate) mod chunk_header;
10pub(crate) mod chunk_heartbeat;
11pub(crate) mod chunk_heartbeat_ack;
12pub(crate) mod chunk_init;
13pub mod chunk_payload_data;
14pub(crate) mod chunk_reconfig;
15pub(crate) mod chunk_selective_ack;
16pub(crate) mod chunk_shutdown;
17pub(crate) mod chunk_shutdown_ack;
18pub(crate) mod chunk_shutdown_complete;
19pub(crate) mod chunk_type;
20
21use crate::error::{Error, Result};
22use chunk_header::*;
23
24use bytes::{Buf, BufMut, Bytes, BytesMut};
25use std::{any::Any, fmt};
26
27pub(crate) trait Chunk: fmt::Display + fmt::Debug {
28    fn header(&self) -> ChunkHeader;
29    fn unmarshal(raw: &Bytes) -> Result<Self>
30    where
31        Self: Sized;
32    fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize>;
33    fn check(&self) -> Result<()>;
34    fn value_length(&self) -> usize;
35    fn as_any(&self) -> &(dyn Any + Send + Sync);
36
37    fn marshal(&self) -> Result<Bytes> {
38        let capacity = CHUNK_HEADER_SIZE + self.value_length();
39        let mut buf = BytesMut::with_capacity(capacity);
40        self.marshal_to(&mut buf)?;
41        Ok(buf.freeze())
42    }
43}
44
45/// ErrorCauseCode is a cause code that appears in either a ERROR or ABORT chunk
46#[derive(Debug, Copy, Clone, PartialEq, Eq, Default)]
47pub struct ErrorCauseCode(pub(crate) u16);
48
49pub(crate) const INVALID_STREAM_IDENTIFIER: ErrorCauseCode = ErrorCauseCode(1);
50pub(crate) const MISSING_MANDATORY_PARAMETER: ErrorCauseCode = ErrorCauseCode(2);
51pub(crate) const STALE_COOKIE_ERROR: ErrorCauseCode = ErrorCauseCode(3);
52pub(crate) const OUT_OF_RESOURCE: ErrorCauseCode = ErrorCauseCode(4);
53pub(crate) const UNRESOLVABLE_ADDRESS: ErrorCauseCode = ErrorCauseCode(5);
54pub(crate) const UNRECOGNIZED_CHUNK_TYPE: ErrorCauseCode = ErrorCauseCode(6);
55pub(crate) const INVALID_MANDATORY_PARAMETER: ErrorCauseCode = ErrorCauseCode(7);
56pub(crate) const UNRECOGNIZED_PARAMETERS: ErrorCauseCode = ErrorCauseCode(8);
57pub(crate) const NO_USER_DATA: ErrorCauseCode = ErrorCauseCode(9);
58pub(crate) const COOKIE_RECEIVED_WHILE_SHUTTING_DOWN: ErrorCauseCode = ErrorCauseCode(10);
59pub(crate) const RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESSES: ErrorCauseCode = ErrorCauseCode(11);
60pub(crate) const USER_INITIATED_ABORT: ErrorCauseCode = ErrorCauseCode(12);
61pub(crate) const PROTOCOL_VIOLATION: ErrorCauseCode = ErrorCauseCode(13);
62
63impl fmt::Display for ErrorCauseCode {
64    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
65        let others = format!("Unknown CauseCode: {}", self.0);
66        let s = match *self {
67            INVALID_STREAM_IDENTIFIER => "Invalid Stream Identifier",
68            MISSING_MANDATORY_PARAMETER => "Missing Mandatory Parameter",
69            STALE_COOKIE_ERROR => "Stale Cookie Error",
70            OUT_OF_RESOURCE => "Out Of Resource",
71            UNRESOLVABLE_ADDRESS => "Unresolvable IP",
72            UNRECOGNIZED_CHUNK_TYPE => "Unrecognized Chunk Type",
73            INVALID_MANDATORY_PARAMETER => "Invalid Mandatory Parameter",
74            UNRECOGNIZED_PARAMETERS => "Unrecognized Parameters",
75            NO_USER_DATA => "No User Data",
76            COOKIE_RECEIVED_WHILE_SHUTTING_DOWN => "Cookie Received While Shutting Down",
77            RESTART_OF_AN_ASSOCIATION_WITH_NEW_ADDRESSES => {
78                "Restart Of An Association With New Addresses"
79            }
80            USER_INITIATED_ABORT => "User Initiated Abort",
81            PROTOCOL_VIOLATION => "Protocol Violation",
82            _ => others.as_str(),
83        };
84        write!(f, "{}", s)
85    }
86}
87
88impl From<u16> for ErrorCauseCode {
89    fn from(v: u16) -> Self {
90        ErrorCauseCode(v)
91    }
92}
93
94/// ErrorCauseHeader represents the shared header that is shared by all error causes
95#[derive(Debug, Clone, Default)]
96pub(crate) struct ErrorCause {
97    pub(crate) code: ErrorCauseCode,
98    pub(crate) raw: Bytes,
99}
100
101/// ErrorCauseInvalidMandatoryParameter represents an SCTP error cause
102pub(crate) type ErrorCauseInvalidMandatoryParameter = ErrorCause;
103
104/// ErrorCauseUnrecognizedChunkType represents an SCTP error cause
105pub(crate) type ErrorCauseUnrecognizedChunkType = ErrorCause;
106
107///
108/// This error cause MAY be included in ABORT chunks that are sent
109/// because an SCTP endpoint detects a protocol violation of the peer
110/// that is not covered by the error causes described in Section 3.3.10.1
111/// to Section 3.3.10.12.  An implementation MAY provide additional
112/// information specifying what kind of protocol violation has been
113/// detected.
114///      0                   1                   2                   3
115///      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
116///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
117///     |         Cause Code=13         |      Cause Length=Variable    |
118///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
119///     /                    Additional Information                     /
120///     \                                                               \
121///     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
122///
123pub(crate) type ErrorCauseProtocolViolation = ErrorCause;
124
125pub(crate) const ERROR_CAUSE_HEADER_LENGTH: usize = 4;
126
127/// makes ErrorCauseHeader printable
128impl fmt::Display for ErrorCause {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        write!(f, "{}", self.code)
131    }
132}
133
134impl ErrorCause {
135    pub(crate) fn unmarshal(buf: &Bytes) -> Result<Self> {
136        if buf.len() < ERROR_CAUSE_HEADER_LENGTH {
137            return Err(Error::ErrErrorCauseTooSmall);
138        }
139
140        let reader = &mut buf.clone();
141
142        let code = ErrorCauseCode(reader.get_u16());
143        let len = reader.get_u16();
144
145        if len < ERROR_CAUSE_HEADER_LENGTH as u16 {
146            return Err(Error::ErrErrorCauseTooSmall);
147        }
148
149        let value_length = len as usize - ERROR_CAUSE_HEADER_LENGTH;
150        let raw = buf.slice(ERROR_CAUSE_HEADER_LENGTH..ERROR_CAUSE_HEADER_LENGTH + value_length);
151
152        Ok(ErrorCause { code, raw })
153    }
154
155    pub(crate) fn marshal(&self) -> Bytes {
156        let mut buf = BytesMut::with_capacity(self.length());
157        let _ = self.marshal_to(&mut buf);
158        buf.freeze()
159    }
160
161    pub(crate) fn marshal_to(&self, writer: &mut BytesMut) -> usize {
162        let len = self.raw.len() + ERROR_CAUSE_HEADER_LENGTH;
163        writer.put_u16(self.code.0);
164        writer.put_u16(len as u16);
165        writer.extend(self.raw.clone());
166        writer.len()
167    }
168
169    pub(crate) fn length(&self) -> usize {
170        self.raw.len() + ERROR_CAUSE_HEADER_LENGTH
171    }
172
173    pub(crate) fn error_cause_code(&self) -> ErrorCauseCode {
174        self.code
175    }
176}