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