Skip to main content

rtc_stun/
textattrs.rs

1#[cfg(test)]
2mod textattrs_test;
3
4use crate::attributes::*;
5use crate::checks::*;
6use crate::message::*;
7use shared::error::*;
8
9use std::fmt;
10
11const MAX_USERNAME_B: usize = 513;
12const MAX_REALM_B: usize = 763;
13const MAX_SOFTWARE_B: usize = 763;
14const MAX_NONCE_B: usize = 763;
15
16/// USERNAME attribute.
17///
18/// RFC 5389 Section 15.3.
19pub type Username = TextAttribute;
20
21/// REALM attribute.
22///
23/// RFC 5389 Section 15.7.
24pub type Realm = TextAttribute;
25
26/// NONCE attribute.
27///
28/// RFC 5389 Section 15.8.
29pub type Nonce = TextAttribute;
30
31/// SOFTWARE attribute.
32///
33/// RFC 5389 Section 15.10.
34pub type Software = TextAttribute;
35
36// TextAttribute is helper for adding and getting text attributes.
37#[derive(Clone, Default)]
38/// A text-valued attribute such as `USERNAME`, `REALM`, `NONCE` or `SOFTWARE`.
39pub struct TextAttribute {
40    /// Which attribute this text belongs to.
41    pub attr: AttrType,
42    /// The text value.
43    pub text: String,
44}
45
46impl fmt::Display for TextAttribute {
47    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
48        write!(f, "{}", self.text)
49    }
50}
51
52impl Setter for TextAttribute {
53    // add_to_as adds attribute with type t to m, checking maximum length. If max_len
54    // is less than 0, no check is performed.
55    fn add_to(&self, m: &mut Message) -> Result<()> {
56        let text = self.text.as_bytes();
57        let max_len = match self.attr {
58            ATTR_USERNAME => MAX_USERNAME_B,
59            ATTR_REALM => MAX_REALM_B,
60            ATTR_SOFTWARE => MAX_SOFTWARE_B,
61            ATTR_NONCE => MAX_NONCE_B,
62            _ => return Err(Error::Other(format!("Unsupported AttrType {}", self.attr))),
63        };
64
65        check_overflow(self.attr, text.len(), max_len)?;
66        m.add(self.attr, text);
67        Ok(())
68    }
69}
70
71impl Getter for TextAttribute {
72    fn get_from(&mut self, m: &Message) -> Result<()> {
73        let attr = self.attr;
74        *self = TextAttribute::get_from_as(m, attr)?;
75        Ok(())
76    }
77}
78
79impl TextAttribute {
80    /// A text attribute of type `attr` holding `text`.
81    pub fn new(attr: AttrType, text: String) -> Self {
82        TextAttribute { attr, text }
83    }
84
85    /// Get_from_as gets t attribute from m and appends its value to reset v.
86    pub fn get_from_as(m: &Message, attr: AttrType) -> Result<Self> {
87        match attr {
88            ATTR_USERNAME => {}
89            ATTR_REALM => {}
90            ATTR_SOFTWARE => {}
91            ATTR_NONCE => {}
92            _ => return Err(Error::Other(format!("Unsupported AttrType {attr}"))),
93        };
94
95        let a = m.get(attr)?;
96        let text = String::from_utf8(a)?;
97        Ok(TextAttribute { attr, text })
98    }
99}