1use std::convert::TryFrom;
10
11use byteorder::{BigEndian, ByteOrder};
12
13use crate::message::StunParseError;
14
15use super::{
16 Attribute, AttributeFromRaw, AttributeStaticType, AttributeType, AttributeWrite,
17 AttributeWriteExt, RawAttribute,
18};
19
20#[derive(Debug, Clone, PartialEq, Eq)]
22pub struct Priority {
23 priority: u32,
24}
25
26impl AttributeStaticType for Priority {
27 const TYPE: AttributeType = AttributeType(0x0024);
28}
29impl Attribute for Priority {
30 fn get_type(&self) -> AttributeType {
31 Self::TYPE
32 }
33
34 fn length(&self) -> u16 {
35 4
36 }
37}
38impl AttributeWrite for Priority {
39 fn to_raw(&self) -> RawAttribute {
40 let mut buf = [0; 4];
41 BigEndian::write_u32(&mut buf[0..4], self.priority);
42 RawAttribute::new(Priority::TYPE, &buf).into_owned()
43 }
44 fn write_into_unchecked(&self, dest: &mut [u8]) {
45 self.write_header_unchecked(dest);
46 BigEndian::write_u32(&mut dest[4..8], self.priority);
47 }
48}
49
50impl AttributeFromRaw<'_> for Priority {
51 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
52 where
53 Self: Sized,
54 {
55 Self::try_from(raw)
56 }
57}
58
59impl TryFrom<&RawAttribute<'_>> for Priority {
60 type Error = StunParseError;
61
62 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
63 raw.check_type_and_len(Self::TYPE, 4..=4)?;
64 Ok(Self {
65 priority: BigEndian::read_u32(&raw.value[..4]),
66 })
67 }
68}
69
70impl Priority {
71 pub fn new(priority: u32) -> Self {
81 Self { priority }
82 }
83
84 pub fn priority(&self) -> u32 {
94 self.priority
95 }
96}
97
98impl std::fmt::Display for Priority {
99 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
100 write!(f, "{}: {}", Self::TYPE, self.priority)
101 }
102}
103
104#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct UseCandidate {}
107
108impl AttributeStaticType for UseCandidate {
109 const TYPE: AttributeType = AttributeType(0x0025);
110}
111impl Attribute for UseCandidate {
112 fn get_type(&self) -> AttributeType {
113 Self::TYPE
114 }
115
116 fn length(&self) -> u16 {
117 0
118 }
119}
120impl AttributeWrite for UseCandidate {
121 fn to_raw(&self) -> RawAttribute {
122 static BUF: [u8; 0] = [0; 0];
123 RawAttribute::new(UseCandidate::TYPE, &BUF)
124 }
125 fn write_into_unchecked(&self, dest: &mut [u8]) {
126 self.write_header_unchecked(dest);
127 }
128}
129
130impl AttributeFromRaw<'_> for UseCandidate {
131 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
132 where
133 Self: Sized,
134 {
135 Self::try_from(raw)
136 }
137}
138
139impl TryFrom<&RawAttribute<'_>> for UseCandidate {
140 type Error = StunParseError;
141
142 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
143 raw.check_type_and_len(Self::TYPE, 0..=0)?;
144 Ok(Self {})
145 }
146}
147
148impl Default for UseCandidate {
149 fn default() -> Self {
150 UseCandidate::new()
151 }
152}
153
154impl UseCandidate {
155 pub fn new() -> Self {
164 Self {}
165 }
166}
167
168impl std::fmt::Display for UseCandidate {
169 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
170 write!(f, "{}", Self::TYPE)
171 }
172}
173
174#[derive(Debug, Clone, PartialEq, Eq)]
176pub struct IceControlled {
177 tie_breaker: u64,
178}
179
180impl AttributeStaticType for IceControlled {
181 const TYPE: AttributeType = AttributeType(0x8029);
182}
183impl Attribute for IceControlled {
184 fn get_type(&self) -> AttributeType {
185 Self::TYPE
186 }
187
188 fn length(&self) -> u16 {
189 8
190 }
191}
192impl AttributeWrite for IceControlled {
193 fn to_raw(&self) -> RawAttribute {
194 let mut buf = [0; 8];
195 BigEndian::write_u64(&mut buf[..8], self.tie_breaker);
196 RawAttribute::new(IceControlled::TYPE, &buf).into_owned()
197 }
198 fn write_into_unchecked(&self, dest: &mut [u8]) {
199 self.write_header_unchecked(dest);
200 BigEndian::write_u64(&mut dest[4..12], self.tie_breaker);
201 }
202}
203
204impl AttributeFromRaw<'_> for IceControlled {
205 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
206 where
207 Self: Sized,
208 {
209 Self::try_from(raw)
210 }
211}
212
213impl TryFrom<&RawAttribute<'_>> for IceControlled {
214 type Error = StunParseError;
215
216 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
217 raw.check_type_and_len(Self::TYPE, 8..=8)?;
218 Ok(Self {
219 tie_breaker: BigEndian::read_u64(&raw.value),
220 })
221 }
222}
223
224impl IceControlled {
225 pub fn new(tie_breaker: u64) -> Self {
235 Self { tie_breaker }
236 }
237
238 pub fn tie_breaker(&self) -> u64 {
248 self.tie_breaker
249 }
250}
251
252impl std::fmt::Display for IceControlled {
253 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
254 write!(f, "{}", Self::TYPE)
255 }
256}
257
258#[derive(Debug, Clone, PartialEq, Eq)]
260pub struct IceControlling {
261 tie_breaker: u64,
262}
263
264impl AttributeStaticType for IceControlling {
265 const TYPE: AttributeType = AttributeType(0x802A);
266}
267
268impl Attribute for IceControlling {
269 fn get_type(&self) -> AttributeType {
270 Self::TYPE
271 }
272
273 fn length(&self) -> u16 {
274 8
275 }
276}
277
278impl AttributeWrite for IceControlling {
279 fn to_raw(&self) -> RawAttribute {
280 let mut buf = [0; 8];
281 BigEndian::write_u64(&mut buf[..8], self.tie_breaker);
282 RawAttribute::new(IceControlling::TYPE, &buf).into_owned()
283 }
284 fn write_into_unchecked(&self, dest: &mut [u8]) {
285 self.write_header_unchecked(dest);
286 BigEndian::write_u64(&mut dest[4..12], self.tie_breaker);
287 }
288}
289
290impl AttributeFromRaw<'_> for IceControlling {
291 fn from_raw_ref(raw: &RawAttribute) -> Result<Self, StunParseError>
292 where
293 Self: Sized,
294 {
295 Self::try_from(raw)
296 }
297}
298
299impl TryFrom<&RawAttribute<'_>> for IceControlling {
300 type Error = StunParseError;
301
302 fn try_from(raw: &RawAttribute) -> Result<Self, Self::Error> {
303 raw.check_type_and_len(Self::TYPE, 8..=8)?;
304 Ok(Self {
305 tie_breaker: BigEndian::read_u64(&raw.value),
306 })
307 }
308}
309
310impl IceControlling {
311 pub fn new(tie_breaker: u64) -> Self {
321 Self { tie_breaker }
322 }
323
324 pub fn tie_breaker(&self) -> u64 {
334 self.tie_breaker
335 }
336}
337
338impl std::fmt::Display for IceControlling {
339 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
340 write!(f, "{}", Self::TYPE)
341 }
342}
343
344#[cfg(test)]
345mod tests {
346 use super::*;
347 use tracing::trace;
348
349 #[test]
350 fn priority() {
351 let _log = crate::tests::test_init_log();
352 let val = 100;
353 let priority = Priority::new(val);
354 trace!("{priority}");
355 assert_eq!(priority.priority(), val);
356 assert_eq!(priority.length(), 4);
357 let raw = RawAttribute::from(&priority);
358 trace!("{raw}");
359 assert_eq!(raw.get_type(), Priority::TYPE);
360 let mapped2 = Priority::try_from(&raw).unwrap();
361 assert_eq!(mapped2.priority(), val);
362 let mut data: Vec<_> = raw.clone().into();
364 let len = data.len();
365 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
366 assert!(matches!(
367 Priority::try_from(&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()),
368 Err(StunParseError::Truncated {
369 expected: 4,
370 actual: 3
371 })
372 ));
373 let mut data: Vec<_> = raw.into();
375 BigEndian::write_u16(&mut data[0..2], 0);
376 assert!(matches!(
377 Priority::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
378 Err(StunParseError::WrongAttributeImplementation)
379 ));
380 }
381
382 #[test]
383 fn use_candidate() {
384 let _log = crate::tests::test_init_log();
385 let use_candidate = UseCandidate::default();
386 trace!("{use_candidate}");
387 assert_eq!(use_candidate.length(), 0);
388 let raw = RawAttribute::from(&use_candidate);
389 trace!("{raw}");
390 assert_eq!(raw.get_type(), UseCandidate::TYPE);
391 let _mapped2 = UseCandidate::try_from(&raw).unwrap();
392 let mut data: Vec<_> = raw.into();
394 BigEndian::write_u16(&mut data[0..2], 0);
395 assert!(matches!(
396 UseCandidate::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
397 Err(StunParseError::WrongAttributeImplementation)
398 ));
399 }
400
401 #[test]
402 fn ice_controlling() {
403 let _log = crate::tests::test_init_log();
404 let tb = 100;
405 let attr = IceControlling::new(tb);
406 trace!("{attr}");
407 assert_eq!(attr.tie_breaker(), tb);
408 assert_eq!(attr.length(), 8);
409 let raw = RawAttribute::from(&attr);
410 trace!("{raw}");
411 assert_eq!(raw.get_type(), IceControlling::TYPE);
412 let mapped2 = IceControlling::try_from(&raw).unwrap();
413 assert_eq!(mapped2.tie_breaker(), tb);
414 let mut data: Vec<_> = raw.clone().into();
416 let len = data.len();
417 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
418 assert!(matches!(
419 IceControlling::try_from(&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()),
420 Err(StunParseError::Truncated {
421 expected: 8,
422 actual: 7
423 })
424 ));
425 let mut data: Vec<_> = raw.into();
427 BigEndian::write_u16(&mut data[0..2], 0);
428 assert!(matches!(
429 IceControlling::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
430 Err(StunParseError::WrongAttributeImplementation)
431 ));
432 }
433
434 #[test]
435 fn ice_controlled() {
436 let _log = crate::tests::test_init_log();
437 let tb = 100;
438 let attr = IceControlled::new(tb);
439 trace!("{attr}");
440 assert_eq!(attr.tie_breaker(), tb);
441 assert_eq!(attr.length(), 8);
442 let raw = RawAttribute::from(&attr);
443 trace!("{raw}");
444 assert_eq!(raw.get_type(), IceControlled::TYPE);
445 let mapped2 = IceControlled::try_from(&raw).unwrap();
446 assert_eq!(mapped2.tie_breaker(), tb);
447 let mut data: Vec<_> = raw.clone().into();
449 let len = data.len();
450 BigEndian::write_u16(&mut data[2..4], len as u16 - 4 - 1);
451 assert!(matches!(
452 IceControlled::try_from(&RawAttribute::from_bytes(data[..len - 1].as_ref()).unwrap()),
453 Err(StunParseError::Truncated {
454 expected: 8,
455 actual: 7
456 })
457 ));
458 let mut data: Vec<_> = raw.into();
460 BigEndian::write_u16(&mut data[0..2], 0);
461 assert!(matches!(
462 IceControlled::try_from(&RawAttribute::from_bytes(data.as_ref()).unwrap()),
463 Err(StunParseError::WrongAttributeImplementation)
464 ));
465 }
466}