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 {
header(&self) -> ParamHeader35 fn header(&self) -> ParamHeader;
unmarshal(raw: &Bytes) -> Result<Self> where Self: Sized36 fn unmarshal(raw: &Bytes) -> Result<Self>
37 where
38 Self: Sized;
marshal_to(&self, buf: &mut BytesMut) -> Result<usize>39 fn marshal_to(&self, buf: &mut BytesMut) -> Result<usize>;
value_length(&self) -> usize40 fn value_length(&self) -> usize;
clone_to(&self) -> Box<dyn Param + Send + Sync>41 fn clone_to(&self) -> Box<dyn Param + Send + Sync>;
as_any(&self) -> &(dyn Any + Send + Sync)42 fn as_any(&self) -> &(dyn Any + Send + Sync);
43
marshal(&self) -> Result<Bytes>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> {
clone(&self) -> Box<dyn Param + Send + Sync>53 fn clone(&self) -> Box<dyn Param + Send + Sync> {
54 self.clone_to()
55 }
56 }
57
build_param(raw_param: &Bytes) -> Result<Box<dyn Param + Send + Sync>>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