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