1#[cfg(test)]
10mod error_code_test;
11
12use crate::attributes::*;
13use crate::checks::*;
14use crate::message::*;
15use shared::error::*;
16
17use std::collections::HashMap;
18use std::fmt;
19
20#[derive(Default)]
24pub struct ErrorCodeAttribute {
26 pub code: ErrorCode,
28 pub reason: Vec<u8>,
30}
31
32impl fmt::Display for ErrorCodeAttribute {
33 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34 write!(
35 f,
36 "{}: {}",
37 self.code.0,
38 String::from_utf8_lossy(&self.reason)
39 )
40 }
41}
42
43const ERROR_CODE_CLASS_BYTE: usize = 2;
45const ERROR_CODE_NUMBER_BYTE: usize = 3;
46const ERROR_CODE_REASON_START: usize = 4;
47const ERROR_CODE_REASON_MAX_B: usize = 763;
48const ERROR_CODE_MODULO: u16 = 100;
49
50impl Setter for ErrorCodeAttribute {
51 fn add_to(&self, m: &mut Message) -> Result<()> {
53 check_overflow(
54 ATTR_ERROR_CODE,
55 self.reason.len() + ERROR_CODE_REASON_START,
56 ERROR_CODE_REASON_MAX_B + ERROR_CODE_REASON_START,
57 )?;
58
59 let mut value: Vec<u8> = Vec::with_capacity(ERROR_CODE_REASON_MAX_B);
60
61 let number = (self.code.0 % ERROR_CODE_MODULO) as u8; let class = (self.code.0 / ERROR_CODE_MODULO) as u8; value.extend_from_slice(&[0, 0]);
64 value.push(class); value.push(number); value.extend_from_slice(&self.reason); m.add(ATTR_ERROR_CODE, &value);
69
70 Ok(())
71 }
72}
73
74impl Getter for ErrorCodeAttribute {
75 fn get_from(&mut self, m: &Message) -> Result<()> {
77 let v = m.get(ATTR_ERROR_CODE)?;
78
79 if v.len() < ERROR_CODE_REASON_START {
80 return Err(Error::ErrUnexpectedEof);
81 }
82
83 let class = v[ERROR_CODE_CLASS_BYTE] as u16;
84 let number = v[ERROR_CODE_NUMBER_BYTE] as u16;
85 let code = class * ERROR_CODE_MODULO + number;
86 self.code = ErrorCode(code);
87 self.reason = v[ERROR_CODE_REASON_START..].to_vec();
88
89 Ok(())
90 }
91}
92
93#[derive(PartialEq, Eq, Hash, Copy, Clone, Default)]
95pub struct ErrorCode(pub u16);
97
98impl Setter for ErrorCode {
99 fn add_to(&self, m: &mut Message) -> Result<()> {
102 if let Some(reason) = ERROR_REASONS.get(self) {
103 let a = ErrorCodeAttribute {
104 code: *self,
105 reason: reason.clone(),
106 };
107 a.add_to(m)
108 } else {
109 Err(Error::ErrNoDefaultReason)
110 }
111 }
112}
113
114pub const CODE_TRY_ALTERNATE: ErrorCode = ErrorCode(300);
116pub const CODE_BAD_REQUEST: ErrorCode = ErrorCode(400);
118pub const CODE_UNAUTHORIZED: ErrorCode = ErrorCode(401);
120pub const CODE_UNKNOWN_ATTRIBUTE: ErrorCode = ErrorCode(420);
123pub const CODE_STALE_NONCE: ErrorCode = ErrorCode(438);
125pub const CODE_ROLE_CONFLICT: ErrorCode = ErrorCode(487);
127pub const CODE_SERVER_ERROR: ErrorCode = ErrorCode(500);
129
130pub const CODE_UNAUTHORISED: ErrorCode = CODE_UNAUTHORIZED;
133
134pub const CODE_FORBIDDEN: ErrorCode = ErrorCode(403);
139pub const CODE_ALLOC_MISMATCH: ErrorCode = ErrorCode(437);
141pub const CODE_WRONG_CREDENTIALS: ErrorCode = ErrorCode(441);
143pub const CODE_UNSUPPORTED_TRANS_PROTO: ErrorCode = ErrorCode(442);
145pub const CODE_ALLOC_QUOTA_REACHED: ErrorCode = ErrorCode(486);
147pub const CODE_INSUFFICIENT_CAPACITY: ErrorCode = ErrorCode(508);
149
150pub const CODE_CONN_ALREADY_EXISTS: ErrorCode = ErrorCode(446);
154pub const CODE_CONN_TIMEOUT_OR_FAILURE: ErrorCode = ErrorCode(447);
156
157pub const CODE_ADDR_FAMILY_NOT_SUPPORTED: ErrorCode = ErrorCode(440);
162pub const CODE_PEER_ADDR_FAMILY_MISMATCH: ErrorCode = ErrorCode(443);
164
165lazy_static! {
166 pub static ref ERROR_REASONS:HashMap<ErrorCode, Vec<u8>> =
168 [
169 (CODE_TRY_ALTERNATE, b"Try Alternate".to_vec()),
170 (CODE_BAD_REQUEST, b"Bad Request".to_vec()),
171 (CODE_UNAUTHORIZED, b"Unauthorized".to_vec()),
172 (CODE_UNKNOWN_ATTRIBUTE, b"Unknown Attribute".to_vec()),
173 (CODE_STALE_NONCE, b"Stale Nonce".to_vec()),
174 (CODE_SERVER_ERROR, b"Server Error".to_vec()),
175 (CODE_ROLE_CONFLICT, b"Role Conflict".to_vec()),
176
177 (CODE_FORBIDDEN, b"Forbidden".to_vec()),
179 (CODE_ALLOC_MISMATCH, b"Allocation Mismatch".to_vec()),
180 (CODE_WRONG_CREDENTIALS, b"Wrong Credentials".to_vec()),
181 (CODE_UNSUPPORTED_TRANS_PROTO, b"Unsupported Transport Protocol".to_vec()),
182 (CODE_ALLOC_QUOTA_REACHED, b"Allocation Quota Reached".to_vec()),
183 (CODE_INSUFFICIENT_CAPACITY, b"Insufficient Capacity".to_vec()),
184
185 (CODE_CONN_ALREADY_EXISTS, b"Connection Already Exists".to_vec()),
187 (CODE_CONN_TIMEOUT_OR_FAILURE, b"Connection Timeout or Failure".to_vec()),
188
189 (CODE_ADDR_FAMILY_NOT_SUPPORTED, b"Address Family not Supported".to_vec()),
191 (CODE_PEER_ADDR_FAMILY_MISMATCH, b"Peer Address Family Mismatch".to_vec()),
192 ].iter().cloned().collect();
193
194}