turn_types/attribute/
transport.rs1use stun_types::{attribute::*, message::StunParseError};
10
11#[derive(Debug, Clone)]
13pub struct RequestedTransport {
14 protocol: u8,
15}
16
17impl AttributeStaticType for RequestedTransport {
18 const TYPE: AttributeType = AttributeType::new(0x0019);
19}
20
21impl Attribute for RequestedTransport {
22 fn get_type(&self) -> AttributeType {
23 Self::TYPE
24 }
25
26 fn length(&self) -> u16 {
27 4
28 }
29}
30
31impl AttributeWrite for RequestedTransport {
32 fn to_raw(&self) -> RawAttribute {
33 RawAttribute::new(self.get_type(), &[self.protocol, 0, 0, 0]).into_owned()
34 }
35
36 fn write_into_unchecked(&self, dest: &mut [u8]) {
37 self.write_header_unchecked(dest);
38 dest[4] = self.protocol;
39 dest[5] = 0x0;
40 dest[6] = 0x0;
41 dest[7] = 0x0;
42 }
43}
44
45impl AttributeFromRaw<'_> for RequestedTransport {
46 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
47 where
48 Self: Sized,
49 {
50 Self::try_from(raw)
51 }
52}
53
54impl TryFrom<&RawAttribute<'_>> for RequestedTransport {
55 type Error = StunParseError;
56 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
57 raw.check_type_and_len(Self::TYPE, 4..=4)?;
58 Ok(Self {
59 protocol: raw.value[0],
60 })
61 }
62}
63
64impl RequestedTransport {
65 pub const UDP: u8 = 17;
67
68 pub fn new(protocol: u8) -> Self {
78 Self { protocol }
79 }
80
81 pub fn protocol(&self) -> u8 {
91 self.protocol
92 }
93}
94
95impl std::fmt::Display for RequestedTransport {
96 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
97 write!(f, "{}: {}", self.get_type(), self.protocol())
98 }
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 use byteorder::{BigEndian, ByteOrder};
105
106 #[test]
107 fn requested_transport() {
108 let _log = crate::tests::test_init_log();
109 let trans = RequestedTransport::new(17);
110 assert_eq!(trans.get_type(), RequestedTransport::TYPE);
111 assert_eq!(trans.protocol(), 17);
112 let raw: RawAttribute = trans.to_raw();
113 println!("raw: {raw:?}");
114 assert_eq!(raw.get_type(), RequestedTransport::TYPE);
115 let trans2 = RequestedTransport::try_from(&raw).unwrap();
116 assert_eq!(trans2.get_type(), RequestedTransport::TYPE);
117 assert_eq!(trans2.protocol(), 17);
118 let mut data: Vec<_> = raw.into();
120 BigEndian::write_u16(&mut data[0..2], 0);
121 assert!(matches!(
122 RequestedTransport::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
123 Err(StunParseError::WrongAttributeImplementation)
124 ));
125 let mut data = [0; 8];
126 trans.write_into(&mut data).unwrap();
127 let raw = RawAttribute::from_bytes(&data).unwrap();
128 let trans2 = RequestedTransport::from_raw_ref(&raw).unwrap();
129 assert_eq!(trans.protocol(), trans2.protocol());
130 }
131}