1use crate::attributes::{stunt_attribute, DecodeAttributeValue, EncodeAttributeValue};
2use crate::context::{AttributeDecoderContext, AttributeEncoderContext};
3use crate::Decode;
4use crate::Encode;
5use crate::ErrorCode as ErrorCodeType;
6use crate::StunError;
7
8const ERROR_CODE: u16 = 0x0009;
9
10#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct ErrorCode(ErrorCodeType);
36
37impl ErrorCode {
38 pub fn new(error_code: ErrorCodeType) -> Self {
42 Self(error_code)
43 }
44
45 pub fn error_code(&self) -> &ErrorCodeType {
47 &self.0
48 }
49}
50
51impl From<ErrorCodeType> for ErrorCode {
52 fn from(error: ErrorCodeType) -> Self {
53 ErrorCode::new(error)
54 }
55}
56
57impl DecodeAttributeValue for ErrorCode {
58 fn decode(ctx: AttributeDecoderContext) -> Result<(Self, usize), StunError> {
59 let (error, size) = ErrorCodeType::decode(ctx.raw_value())?;
60 Ok((ErrorCode::new(error), size))
61 }
62}
63
64impl EncodeAttributeValue for ErrorCode {
65 fn encode(&self, mut ctx: AttributeEncoderContext) -> Result<usize, StunError> {
66 self.0.encode(ctx.raw_value_mut())
67 }
68}
69
70impl crate::attributes::AsVerifiable for ErrorCode {}
71
72stunt_attribute!(ErrorCode, ERROR_CODE);
73
74#[cfg(test)]
75mod tests {
76 use super::*;
77 use crate::attributes::{DecodeAttributeValue, EncodeAttributeValue};
78 use crate::error::StunErrorType;
79 use crate::StunAttribute;
80
81 #[test]
82 fn error_code() {
83 let error = ErrorCodeType::new(318, "test reason").expect("Can not create error code type");
84 let attr = ErrorCode::from(error);
85 assert_eq!(attr.error_code().class(), 3);
86 assert_eq!(attr.error_code().number(), 18);
87 assert_eq!(attr.error_code().reason(), "test reason");
88 assert_eq!(attr.error_code().error_code(), 318);
89 }
90
91 #[test]
92 fn decode_error_code() {
93 let dummy_msg: [u8; 0] = [0x0; 0];
94 let buffer = [
95 0x00, 0x00, 0x03, 0x12, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6f,
96 0x6e,
97 ];
98 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
99 let (error_code, size) = ErrorCode::decode(ctx).expect("Can not decode ERROR-CODE");
100 assert_eq!(size, 15);
101 let error = error_code.error_code();
102 assert_eq!(error.error_code(), 318);
103 assert_eq!(error.class(), 3);
104 assert_eq!(error.number(), 18);
105 assert_eq!(error.reason(), "test reason");
106
107 let buffer = [0x00, 0x00, 0x03, 0x12];
108 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
109 let (error_code, size) = ErrorCode::decode(ctx).expect("Can not decode ERROR-CODE");
110 assert_eq!(size, 4);
111 let error = error_code.error_code();
112 assert_eq!(error.error_code(), 318);
113 assert_eq!(error.class(), 3);
114 assert_eq!(error.number(), 18);
115 assert!(error.reason().is_empty());
116 }
117
118 #[test]
119 fn decode_error_code_fail() {
120 let dummy_msg: [u8; 0] = [0x0; 0];
121 let buffer = [0x00, 0x00, 0x03];
123 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
124 let result = ErrorCode::decode(ctx);
125 assert_eq!(
126 result.expect_err("Error expected"),
127 StunErrorType::SmallBuffer
128 );
129
130 let buffer = [
132 0x00, 0x00, 0x02, 0x12, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6f,
133 0x6e,
134 ];
135 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
136 let result = ErrorCode::decode(ctx);
137 assert_eq!(
138 result.expect_err("Error expected"),
139 StunErrorType::InvalidParam
140 );
141
142 let buffer = [
144 0x00, 0x00, 0x03, 0x70, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6f,
145 0x6e,
146 ];
147 let ctx = AttributeDecoderContext::new(None, &dummy_msg, &buffer);
148 let result = ErrorCode::decode(ctx);
149 assert_eq!(
150 result.expect_err("Error expected"),
151 StunErrorType::InvalidParam
152 );
153 }
154
155 #[test]
156 fn encode_error_code() {
157 let dummy_msg: [u8; 0] = [0x0; 0];
158 let result = ErrorCodeType::new(318, "test reason");
159 assert!(result.is_ok());
160 let error_code = ErrorCode::new(result.unwrap());
161
162 let mut buffer: [u8; 15] = [0x0; 15];
163 let ctx = AttributeEncoderContext::new(None, &dummy_msg, &mut buffer);
164 let result = error_code.encode(ctx);
165 assert_eq!(result, Ok(15));
166
167 let cmp_buffer = [
168 0x00, 0x00, 0x03, 0x12, 0x74, 0x65, 0x73, 0x74, 0x20, 0x72, 0x65, 0x61, 0x73, 0x6f,
169 0x6e,
170 ];
171 assert_eq!(&buffer[..], &cmp_buffer[..]);
172 }
173
174 #[test]
175 fn error_code_stunt_attribute() {
176 let error = ErrorCodeType::new(318, "test reason").expect("Can not create error code type");
177 let attr = StunAttribute::ErrorCode(ErrorCode::new(error));
178 assert!(attr.is_error_code());
179 assert!(attr.as_error_code().is_ok());
180 assert!(attr.as_unknown().is_err());
181
182 assert!(attr.attribute_type().is_comprehension_required());
183 assert!(!attr.attribute_type().is_comprehension_optional());
184
185 let dbg_fmt = format!("{:?}", attr);
186 assert_eq!(
187 "ErrorCode(ErrorCode(ErrorCode { error_code: 318, reason: \"test reason\" }))",
188 dbg_fmt
189 );
190 }
191}