stun_coder/message/
utils.rs

1use stringprep::saslprep;
2
3pub use super::errors::{IntegrityKeyGenerationError, MessageDecodeError, MessageEncodeError};
4use crate::definitions::StunTransactionId;
5use crate::header::StunHeader;
6use crate::header::{StunMessageClass, StunMessageMethod};
7use crate::StunAttribute;
8
9use super::message::StunMessage;
10
11impl StunMessage {
12    /// Creates a new message
13    pub fn new(method: StunMessageMethod, class: StunMessageClass) -> Self {
14        let header = StunHeader::new(method, class, None);
15
16        Self {
17            header,
18            attributes: Vec::new(),
19        }
20    }
21
22    /// Creates a Binding Request
23    pub fn create_request() -> Self {
24        Self::default().set_message_class(StunMessageClass::Request)
25    }
26
27    /// Creates a Binding Success Response
28    pub fn create_success_response() -> Self {
29        Self::default().set_message_class(StunMessageClass::SuccessResponse)
30    }
31
32    /// Creates a Binding Error Response
33    pub fn create_error_response() -> Self {
34        Self::default().set_message_class(StunMessageClass::ErrorResponse)
35    }
36
37    /// Creates a Binding Indication
38    pub fn create_indication() -> Self {
39        Self::default().set_message_class(StunMessageClass::Indication)
40    }
41
42    /// Sets message transaction id
43    pub fn set_transaction_id(mut self, transaction_id: StunTransactionId) -> Self {
44        self.header.transaction_id = transaction_id;
45
46        self
47    }
48
49    /// Sets message class
50    pub fn set_message_class(mut self, class: StunMessageClass) -> Self {
51        self.header.message_class = class;
52
53        self
54    }
55
56    /// Sets message method
57    pub fn set_message_method(mut self, method: StunMessageMethod) -> Self {
58        self.header.message_method = method;
59
60        self
61    }
62
63    /// Returns an immutable reference to the message header
64    pub fn get_header(&self) -> &StunHeader {
65        &self.header
66    }
67
68    /// Returns an immutable reference to the message attributes
69    pub fn get_attributes(&self) -> &Vec<StunAttribute> {
70        &self.attributes
71    }
72
73    /// Adds an attribute to the list
74    pub fn add_attribute(mut self, attr: StunAttribute) -> Self {
75        self.attributes.push(attr);
76
77        self
78    }
79
80    /// Adds a Fingerprint attribute at the end of the message
81    ///
82    /// NOTE: This function should be invoked only when all other attributes are added
83    pub fn add_fingerprint(mut self) -> Self {
84        self.attributes
85            .push(StunAttribute::Fingerprint { value: 0 });
86
87        self
88    }
89
90    /// Adds a MessageIntegrity attribute at the end of the message
91    ///
92    /// NOTE: This function should be invoked only when all other attributes are added but before the Fingerprint attribute
93    pub fn add_message_integrity(mut self) -> Self {
94        self.attributes
95            .push(StunAttribute::MessageIntegrity { key: Vec::new() });
96
97        self
98    }
99
100    /// Adds USER, REALM and MESSAGE-INTEGRITY attributes for long term credential authentication
101    ///
102    /// NOTE: This function should be invoked only when all other attributes are added but before the Fingerprint attribute
103    pub fn add_long_term_credential_message_integrity(
104        mut self,
105        username: &str,
106        realm: &str,
107    ) -> Result<Self, stringprep::Error> {
108        self.attributes.push(StunAttribute::Username {
109            value: saslprep(username)?.to_string(),
110        });
111
112        self.attributes.push(StunAttribute::Realm {
113            value: saslprep(realm)?.to_string(),
114        });
115
116        Ok(self.add_message_integrity())
117    }
118}
119
120impl std::default::Default for StunMessage {
121    /// Default STUN message.
122    ///
123    /// Class: Request
124    /// Method: Binding
125    /// Transaction ID: randomly generated
126    fn default() -> Self {
127        Self::new(StunMessageMethod::BindingRequest, StunMessageClass::Request)
128    }
129}