1use crate::attributes::{stunt_attribute, DecodeAttributeValue, EncodeAttributeValue};
2use crate::context::{AttributeDecoderContext, AttributeEncoderContext};
3use crate::error::{StunError, StunErrorType};
4use crate::strings::QuotedString;
5use crate::{Decode, Encode};
6use std::convert::TryFrom;
7
8const NONCE: u16 = 0x0015;
9const MAX_ENCODED_SIZE: usize = 509;
10const MAX_DECODED_SIZE: usize = 763;
11
12#[derive(Debug, PartialEq, Clone, Hash, Eq, PartialOrd, Ord)]
39pub struct Nonce(QuotedString);
40
41impl Nonce {
42 pub fn new<S>(value: S) -> Result<Self, StunError>
45 where
46 S: AsRef<str>,
47 {
48 let name = QuotedString::try_from(value.as_ref())?;
49 let name_len = name.as_str().len();
50 (name_len <= MAX_ENCODED_SIZE)
51 .then_some(Nonce(name))
52 .ok_or_else(|| {
53 StunError::new(
54 StunErrorType::ValueTooLong,
55 format!(
56 "Value length {} > max. encoded size {}",
57 name_len, MAX_ENCODED_SIZE
58 ),
59 )
60 })
61 }
62
63 pub fn as_str(&self) -> &str {
65 self.0.as_str()
66 }
67}
68
69impl PartialEq<&str> for Nonce {
70 fn eq(&self, other: &&str) -> bool {
71 self.as_str().eq(*other)
72 }
73}
74
75impl PartialEq<Nonce> for &str {
76 fn eq(&self, other: &Nonce) -> bool {
77 other.as_str().eq(*self)
78 }
79}
80
81impl PartialEq<str> for Nonce {
82 fn eq(&self, other: &str) -> bool {
83 self.as_str().eq(other)
84 }
85}
86
87impl PartialEq<String> for Nonce {
88 fn eq(&self, other: &String) -> bool {
89 other.eq(self.as_str())
90 }
91}
92
93impl PartialEq<Nonce> for String {
94 fn eq(&self, other: &Nonce) -> bool {
95 self.eq(other.as_str())
96 }
97}
98
99impl AsRef<str> for Nonce {
100 fn as_ref(&self) -> &str {
101 self.0.as_ref()
102 }
103}
104
105impl AsRef<String> for Nonce {
106 fn as_ref(&self) -> &String {
107 self.0.as_ref()
108 }
109}
110
111impl TryFrom<&str> for Nonce {
112 type Error = StunError;
113
114 fn try_from(value: &str) -> Result<Self, Self::Error> {
117 Nonce::new(value)
118 }
119}
120
121impl TryFrom<&String> for Nonce {
122 type Error = StunError;
123
124 fn try_from(value: &String) -> Result<Self, Self::Error> {
127 Nonce::new(value)
128 }
129}
130
131impl TryFrom<String> for Nonce {
132 type Error = StunError;
133
134 fn try_from(value: String) -> Result<Self, Self::Error> {
137 Nonce::new(value)
138 }
139}
140
141impl DecodeAttributeValue for Nonce {
142 fn decode(ctx: AttributeDecoderContext) -> Result<(Self, usize), StunError> {
143 let raw_value = ctx.raw_value();
144 if raw_value.len() > MAX_DECODED_SIZE {
145 return Err(StunError::new(
146 StunErrorType::ValueTooLong,
147 format!(
148 "Value length {} is bigger than max. decoded size {}",
149 raw_value.len(),
150 MAX_DECODED_SIZE
151 ),
152 ));
153 }
154
155 let (quoted, size) = QuotedString::decode(raw_value)?;
156
157 Ok((Self(quoted), size))
158 }
159}
160
161impl EncodeAttributeValue for Nonce {
162 fn encode(&self, mut ctx: AttributeEncoderContext) -> Result<usize, StunError> {
163 if self.as_str().len() > MAX_ENCODED_SIZE {
164 return Err(StunError::new(
165 StunErrorType::ValueTooLong,
166 format!(
167 "Value length {} is bigger than max. decoded size {}",
168 self.as_str().len(),
169 MAX_ENCODED_SIZE
170 ),
171 ));
172 }
173
174 self.0.encode(ctx.raw_value_mut())
175 }
176}
177
178impl crate::attributes::AsVerifiable for Nonce {}
179
180stunt_attribute!(Nonce, NONCE);
181
182#[cfg(test)]
183mod tests {
184 use super::*;
185 use crate::StunAttribute;
186
187 #[test]
188 fn constructor() {
189 let value = String::from("f//499k954d6OL34oL9FSTvy64sA");
190 let attr_1 = Nonce::try_from(&value).expect("Can not create a Nonce attribute");
191 let attr_2 = Nonce::new(&value).expect("Can not create a Nonce attribute");
192 let attr_3 = Nonce::try_from(value.clone()).expect("Can not create Software attribute");
193
194 assert_eq!(attr_1, value);
195 assert_eq!(value, attr_1);
196 assert_eq!(attr_1, "f//499k954d6OL34oL9FSTvy64sA");
197 assert_eq!("f//499k954d6OL34oL9FSTvy64sA", attr_1);
198 assert_eq!(attr_1, attr_2);
199 assert_eq!(attr_1, attr_3);
200
201 let val: &String = attr_1.as_ref();
202 assert!(value.eq(val));
203
204 let value: &str = attr_1.as_ref();
205 assert!(value.eq(val));
206
207 let value = "x".repeat(MAX_ENCODED_SIZE);
208 let _result = Nonce::try_from(&value).expect("Can not create a Nonce attribute");
209
210 let value = "x".repeat(MAX_ENCODED_SIZE + 1);
211 let result = Nonce::try_from(&value);
212 assert_eq!(
213 result.expect_err("Error expected"),
214 StunErrorType::ValueTooLong
215 );
216 }
217
218 #[test]
219 fn decode_nonce_value() {
220 let dummy_msg = [];
221 let buffer = [
223 0x66, 0x2f, 0x2f, 0x34, 0x39, 0x39, 0x6b, 0x39, 0x35, 0x34, 0x64, 0x36, 0x4f, 0x4c, 0x33, 0x34, 0x6f, 0x4c, 0x39, 0x46, 0x53, 0x54, 0x76, 0x79, 0x36, 0x34, 0x73, 0x41, ];
231 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
232
233 let (nonce, size) = Nonce::decode(ctx).expect("Can not decode NONCE");
234 assert_eq!(size, 28);
235 assert_eq!(nonce.as_str(), "f//499k954d6OL34oL9FSTvy64sA");
236
237 let value = "x".repeat(MAX_DECODED_SIZE);
238 let ctx = AttributeDecoderContext::new(None, &dummy_msg, value.as_bytes());
239 let (_nonce, size) = Nonce::decode(ctx).expect("Can not decode NONCE");
240 assert_eq!(size, MAX_DECODED_SIZE);
241 }
242
243 #[test]
244 fn decode_nonce_value_error() {
245 let dummy_msg = [];
246 let buffer = [
248 0x22, 0x66, 0x2f, 0x2f, 0x34, 0x39, 0x39, 0x6b, 0x39, 0x35, 0x34, 0x64, 0x36, 0x4f, 0x4c, 0x33, 0x34, 0x6f, 0x4c, 0x39, 0x46, 0x53, 0x54, 0x76, 0x79, 0x36, 0x34, 0x73, 0x41, 0x22, ];
258 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
259
260 assert_eq!(
261 Nonce::decode(ctx).expect_err("Error expected"),
262 StunErrorType::InvalidParam
263 );
264
265 let value = "x".repeat(MAX_DECODED_SIZE + 1);
266 let ctx = AttributeDecoderContext::new(None, &dummy_msg, value.as_bytes());
267 assert_eq!(
268 Nonce::decode(ctx).expect_err("Error expected"),
269 StunErrorType::ValueTooLong
270 );
271 }
272
273 #[test]
274 fn encode_nonce_value() {
275 let dummy_msg: [u8; 0] = [0x0; 0];
276 let nonce = Nonce::try_from("f//499k954d6OL34oL9FSTvy64sA").expect("Expected QuotedString");
277
278 let mut buffer: [u8; 28] = [0x0; 28];
279 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
280
281 let result = nonce.encode(ctx);
282 assert_eq!(result, Ok(28));
283
284 let mut buffer: [u8; MAX_ENCODED_SIZE] = [0x0; MAX_ENCODED_SIZE];
285 let nonce = Nonce::try_from("x".repeat(MAX_ENCODED_SIZE))
286 .expect("Can not create a Nonce attribute");
287 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
288 let result = nonce.encode(ctx);
289 assert_eq!(result, Ok(MAX_ENCODED_SIZE));
290 }
291
292 #[test]
293 fn encode_nonce_value_error() {
294 let dummy_msg: [u8; 0] = [0x0; 0];
295 let nonce = Nonce::try_from("f//499k954d6OL34oL9FSTvy64sA").expect("Expected QuotedString");
296
297 let mut buffer: [u8; 27] = [0x0; 27];
298 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
299 let result = nonce.encode(ctx);
300 assert_eq!(
301 result.expect_err("Error expected"),
302 StunErrorType::SmallBuffer
303 );
304
305 let mut buffer: [u8; MAX_ENCODED_SIZE + 1] = [0x0; MAX_ENCODED_SIZE + 1];
306 let str = "x".repeat(MAX_ENCODED_SIZE + 1);
307 let value = QuotedString::try_from(str.as_str()).expect("Expected QuotedString");
308 let nonce = Nonce(value);
309 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
310 let result = nonce.encode(ctx);
311 assert_eq!(
312 result.expect_err("Error expected"),
313 StunErrorType::ValueTooLong
314 );
315 }
316
317 #[test]
318 fn nonce_stunt_attribute() {
319 let attr =
320 StunAttribute::Nonce(Nonce::try_from("test").expect("Can not create Nonce attribute"));
321 assert!(attr.is_nonce());
322 assert!(attr.as_nonce().is_ok());
323 assert!(attr.as_unknown().is_err());
324
325 assert!(attr.attribute_type().is_comprehension_required());
326 assert!(!attr.attribute_type().is_comprehension_optional());
327
328 let dbg_fmt = format!("{:?}", attr);
329 assert_eq!("Nonce(Nonce(QuotedString(\"test\")))", dbg_fmt);
330 }
331}