1 #[cfg(test)] 2 mod param_test; 3 4 pub(crate) mod param_chunk_list; 5 pub(crate) mod param_forward_tsn_supported; 6 pub(crate) mod param_header; 7 pub(crate) mod param_heartbeat_info; 8 pub(crate) mod param_outgoing_reset_request; 9 pub(crate) mod param_random; 10 pub(crate) mod param_reconfig_response; 11 pub(crate) mod param_requested_hmac_algorithm; 12 pub(crate) mod param_state_cookie; 13 pub(crate) mod param_supported_extensions; 14 pub(crate) mod param_type; 15 pub(crate) mod param_unknown; 16 pub(crate) mod param_unrecognized; 17 18 use crate::error::{Error, Result}; 19 use crate::param::{ 20 param_chunk_list::ParamChunkList, param_forward_tsn_supported::ParamForwardTsnSupported, 21 param_heartbeat_info::ParamHeartbeatInfo, 22 param_outgoing_reset_request::ParamOutgoingResetRequest, param_random::ParamRandom, 23 param_reconfig_response::ParamReconfigResponse, 24 param_requested_hmac_algorithm::ParamRequestedHmacAlgorithm, 25 param_state_cookie::ParamStateCookie, param_supported_extensions::ParamSupportedExtensions, 26 }; 27 use param_header::*; 28 use param_type::*; 29 30 use crate::param::param_unknown::ParamUnknown; 31 use bytes::{Buf, Bytes, BytesMut}; 32 use std::{any::Any, fmt}; 33 34 pub(crate) trait Param: fmt::Display + fmt::Debug { 35 fn header(&self) -> ParamHeader; 36 fn unmarshal(raw: &Bytes) -> Result<Self> 37 where 38 Self: Sized; 39 fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize>; 40 fn value_length(&self) -> usize; 41 fn clone_to(&self) -> Box<dyn Param + Send + Sync>; 42 fn as_any(&self) -> &(dyn Any + Send + Sync); 43 44 fn marshal(&self) -> Result<Bytes> { 45 let capacity = PARAM_HEADER_LENGTH + self.value_length(); 46 let mut buf = BytesMut::with_capacity(capacity); 47 self.marshal_to(&mut buf)?; 48 Ok(buf.freeze()) 49 } 50 } 51 52 impl Clone for Box<dyn Param + Send + Sync> { 53 fn clone(&self) -> Box<dyn Param + Send + Sync> { 54 self.clone_to() 55 } 56 } 57 58 pub(crate) fn build_param(raw_param: &Bytes) -> Result<Box<dyn Param + Send + Sync>> { 59 if raw_param.len() < PARAM_HEADER_LENGTH { 60 return Err(Error::ErrParamHeaderTooShort); 61 } 62 let reader = &mut raw_param.slice(..2); 63 let raw_type = reader.get_u16(); 64 match raw_type.into() { 65 ParamType::ForwardTsnSupp => Ok(Box::new(ParamForwardTsnSupported::unmarshal(raw_param)?)), 66 ParamType::SupportedExt => Ok(Box::new(ParamSupportedExtensions::unmarshal(raw_param)?)), 67 ParamType::Random => Ok(Box::new(ParamRandom::unmarshal(raw_param)?)), 68 ParamType::ReqHmacAlgo => Ok(Box::new(ParamRequestedHmacAlgorithm::unmarshal(raw_param)?)), 69 ParamType::ChunkList => Ok(Box::new(ParamChunkList::unmarshal(raw_param)?)), 70 ParamType::StateCookie => Ok(Box::new(ParamStateCookie::unmarshal(raw_param)?)), 71 ParamType::HeartbeatInfo => Ok(Box::new(ParamHeartbeatInfo::unmarshal(raw_param)?)), 72 ParamType::OutSsnResetReq => Ok(Box::new(ParamOutgoingResetRequest::unmarshal(raw_param)?)), 73 ParamType::ReconfigResp => Ok(Box::new(ParamReconfigResponse::unmarshal(raw_param)?)), 74 _ => { 75 // According to RFC https://datatracker.ietf.org/doc/html/rfc4960#section-3.2.1 76 let stop_processing = ((raw_type >> 15) & 0x01) == 0; 77 if stop_processing { 78 Err(Error::ErrParamTypeUnhandled { typ: raw_type }) 79 } else { 80 // We still might need to report this param as unrecognized. 81 // This depends on the context though. 82 Ok(Box::new(ParamUnknown::unmarshal(raw_param)?)) 83 } 84 } 85 } 86 } 87