1use std::convert::TryFrom;
10
11use byteorder::{BigEndian, ByteOrder};
12
13use crate::message::StunParseError;
14
15use super::{
16 Attribute, AttributeStaticType, AttributeType, AttributeWrite, AttributeWriteExt, RawAttribute,
17};
18
19#[derive(Debug, Clone, PartialEq, Eq)]
21pub struct Priority {
22 priority: u32,
23}
24
25impl AttributeStaticType for Priority {
26 const TYPE: AttributeType = AttributeType(0x0024);
27}
28impl Attribute for Priority {
29 fn get_type(&self) -> AttributeType {
30 Self::TYPE
31 }
32
33 fn length(&self) -> u16 {
34 4
35 }
36}
37impl AttributeWrite for Priority {
38 fn to_raw(&self) -> RawAttribute {
39 let mut buf = [0; 4];
40 BigEndian::write_u32(&mut buf[0..4], self.priority);
41 RawAttribute::new(Priority::TYPE, &buf).into_owned()
42 }
43 fn write_into_unchecked(&self, dest: &mut [u8]) {
44 self.write_header_unchecked(dest);
45 BigEndian::write_u32(&mut dest[4..8], self.priority);
46 }
47}
48impl<'a> TryFrom<&RawAttribute<'a>> for Priority {
49 type Error = StunParseError;
50
51 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
52 raw.check_type_and_len(Self::TYPE, 4..=4)?;
53 Ok(Self {
54 priority: BigEndian::read_u32(&raw.value[..4]),
55 })
56 }
57}
58
59impl Priority {
60 pub fn new(priority: u32) -> Self {
70 Self { priority }
71 }
72
73 pub fn priority(&self) -> u32 {
83 self.priority
84 }
85}
86
87impl std::fmt::Display for Priority {
88 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
89 write!(f, "{}: {}", Self::TYPE, self.priority)
90 }
91}
92
93#[derive(Debug, Clone, PartialEq, Eq)]
95pub struct UseCandidate {}
96
97impl AttributeStaticType for UseCandidate {
98 const TYPE: AttributeType = AttributeType(0x0025);
99}
100impl Attribute for UseCandidate {
101 fn get_type(&self) -> AttributeType {
102 Self::TYPE
103 }
104
105 fn length(&self) -> u16 {
106 0
107 }
108}
109impl AttributeWrite for UseCandidate {
110 fn to_raw(&self) -> RawAttribute {
111 static BUF: [u8; 0] = [0; 0];
112 RawAttribute::new(UseCandidate::TYPE, &BUF)
113 }
114 fn write_into_unchecked(&self, dest: &mut [u8]) {
115 self.write_header_unchecked(dest);
116 }
117}
118impl<'a> TryFrom<&RawAttribute<'a>> for UseCandidate {
119 type Error = StunParseError;
120
121 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
122 raw.check_type_and_len(Self::TYPE, 0..=0)?;
123 Ok(Self {})
124 }
125}
126
127impl Default for UseCandidate {
128 fn default() -> Self {
129 UseCandidate::new()
130 }
131}
132
133impl UseCandidate {
134 pub fn new() -> Self {
143 Self {}
144 }
145}
146
147impl std::fmt::Display for UseCandidate {
148 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149 write!(f, "{}", Self::TYPE)
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq)]
155pub struct IceControlled {
156 tie_breaker: u64,
157}
158
159impl AttributeStaticType for IceControlled {
160 const TYPE: AttributeType = AttributeType(0x8029);
161}
162impl Attribute for IceControlled {
163 fn get_type(&self) -> AttributeType {
164 Self::TYPE
165 }
166
167 fn length(&self) -> u16 {
168 8
169 }
170}
171impl AttributeWrite for IceControlled {
172 fn to_raw(&self) -> RawAttribute {
173 let mut buf = [0; 8];
174 BigEndian::write_u64(&mut buf[..8], self.tie_breaker);
175 RawAttribute::new(IceControlled::TYPE, &buf).into_owned()
176 }
177 fn write_into_unchecked(&self, dest: &mut [u8]) {
178 self.write_header_unchecked(dest);
179 BigEndian::write_u64(&mut dest[4..12], self.tie_breaker);
180 }
181}
182impl<'a> TryFrom<&RawAttribute<'a>> for IceControlled {
183 type Error = StunParseError;
184
185 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
186 raw.check_type_and_len(Self::TYPE, 8..=8)?;
187 Ok(Self {
188 tie_breaker: BigEndian::read_u64(&raw.value),
189 })
190 }
191}
192
193impl IceControlled {
194 pub fn new(tie_breaker: u64) -> Self {
204 Self { tie_breaker }
205 }
206
207 pub fn tie_breaker(&self) -> u64 {
217 self.tie_breaker
218 }
219}
220
221impl std::fmt::Display for IceControlled {
222 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
223 write!(f, "{}", Self::TYPE)
224 }
225}
226
227#[derive(Debug, Clone, PartialEq, Eq)]
229pub struct IceControlling {
230 tie_breaker: u64,
231}
232
233impl AttributeStaticType for IceControlling {
234 const TYPE: AttributeType = AttributeType(0x802A);
235}
236impl Attribute for IceControlling {
237 fn get_type(&self) -> AttributeType {
238 Self::TYPE
239 }
240
241 fn length(&self) -> u16 {
242 8
243 }
244}
245impl AttributeWrite for IceControlling {
246 fn to_raw(&self) -> RawAttribute {
247 let mut buf = [0; 8];
248 BigEndian::write_u64(&mut buf[..8], self.tie_breaker);
249 RawAttribute::new(IceControlling::TYPE, &buf).into_owned()
250 }
251 fn write_into_unchecked(&self, dest: &mut [u8]) {
252 self.write_header_unchecked(dest);
253 BigEndian::write_u64(&mut dest[4..12], self.tie_breaker);
254 }
255}
256impl<'a> TryFrom<&RawAttribute<'a>> for IceControlling {
257 type Error = StunParseError;
258
259 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
260 raw.check_type_and_len(Self::TYPE, 8..=8)?;
261 Ok(Self {
262 tie_breaker: BigEndian::read_u64(&raw.value),
263 })
264 }
265}
266
267impl IceControlling {
268 pub fn new(tie_breaker: u64) -> Self {
278 Self { tie_breaker }
279 }
280
281 pub fn tie_breaker(&self) -> u64 {
291 self.tie_breaker
292 }
293}
294
295impl std::fmt::Display for IceControlling {
296 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
297 write!(f, "{}", Self::TYPE)
298 }
299}
300
301#[cfg(test)]
302mod tests {
303 use super::*;
304 use tracing::trace;
305
306 #[test]
307 fn priority() {
308 let _log = crate::tests::test_init_log();
309 let val = 100;
310 let priority = Priority::new(val);
311 trace!("{priority}");
312 assert_eq!(priority.priority(), val);
313 assert_eq!(priority.length(), 4);
314 let raw = RawAttribute::from(&priority);
315 trace!("{raw}");
316 assert_eq!(raw.get_type(), Priority::TYPE);
317 let mapped2 = Priority::try_from(&raw).unwrap();
318 assert_eq!(mapped2.priority(), val);
319 let mut data: Vec<_> = raw.clone().into();
321 let len = data.len();
322 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
323 assert!(matches!(
324 Priority::try_from(&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()),
325 Err(StunParseError::Truncated {
326 expected: 4,
327 actual: 3
328 })
329 ));
330 let mut data: Vec<_> = raw.into();
332 BigEndian::write_u16(&mut data[0..2], 0);
333 assert!(matches!(
334 Priority::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
335 Err(StunParseError::WrongAttributeImplementation)
336 ));
337 }
338
339 #[test]
340 fn use_candidate() {
341 let _log = crate::tests::test_init_log();
342 let use_candidate = UseCandidate::default();
343 trace!("{use_candidate}");
344 assert_eq!(use_candidate.length(), 0);
345 let raw = RawAttribute::from(&use_candidate);
346 trace!("{raw}");
347 assert_eq!(raw.get_type(), UseCandidate::TYPE);
348 let _mapped2 = UseCandidate::try_from(&raw).unwrap();
349 let mut data: Vec<_> = raw.into();
351 BigEndian::write_u16(&mut data[0..2], 0);
352 assert!(matches!(
353 UseCandidate::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
354 Err(StunParseError::WrongAttributeImplementation)
355 ));
356 }
357
358 #[test]
359 fn ice_controlling() {
360 let _log = crate::tests::test_init_log();
361 let tb = 100;
362 let attr = IceControlling::new(tb);
363 trace!("{attr}");
364 assert_eq!(attr.tie_breaker(), tb);
365 assert_eq!(attr.length(), 8);
366 let raw = RawAttribute::from(&attr);
367 trace!("{raw}");
368 assert_eq!(raw.get_type(), IceControlling::TYPE);
369 let mapped2 = IceControlling::try_from(&raw).unwrap();
370 assert_eq!(mapped2.tie_breaker(), tb);
371 let mut data: Vec<_> = raw.clone().into();
373 let len = data.len();
374 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
375 assert!(matches!(
376 IceControlling::try_from(&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()),
377 Err(StunParseError::Truncated {
378 expected: 8,
379 actual: 7
380 })
381 ));
382 let mut data: Vec<_> = raw.into();
384 BigEndian::write_u16(&mut data[0..2], 0);
385 assert!(matches!(
386 IceControlling::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
387 Err(StunParseError::WrongAttributeImplementation)
388 ));
389 }
390
391 #[test]
392 fn ice_controlled() {
393 let _log = crate::tests::test_init_log();
394 let tb = 100;
395 let attr = IceControlled::new(tb);
396 trace!("{attr}");
397 assert_eq!(attr.tie_breaker(), tb);
398 assert_eq!(attr.length(), 8);
399 let raw = RawAttribute::from(&attr);
400 trace!("{raw}");
401 assert_eq!(raw.get_type(), IceControlled::TYPE);
402 let mapped2 = IceControlled::try_from(&raw).unwrap();
403 assert_eq!(mapped2.tie_breaker(), tb);
404 let mut data: Vec<_> = raw.clone().into();
406 let len = data.len();
407 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
408 assert!(matches!(
409 IceControlled::try_from(&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()),
410 Err(StunParseError::Truncated {
411 expected: 8,
412 actual: 7
413 })
414 ));
415 let mut data: Vec<_> = raw.into();
417 BigEndian::write_u16(&mut data[0..2], 0);
418 assert!(matches!(
419 IceControlled::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
420 Err(StunParseError::WrongAttributeImplementation)
421 ));
422 }
423}