xref: /webrtc/stun/src/error_code.rs (revision ffe74184)
1*ffe74184SMartin Algesten use crate::attributes::*;
2*ffe74184SMartin Algesten use crate::checks::*;
3*ffe74184SMartin Algesten use crate::error::*;
4*ffe74184SMartin Algesten use crate::message::*;
5*ffe74184SMartin Algesten 
6*ffe74184SMartin Algesten use std::collections::HashMap;
7*ffe74184SMartin Algesten use std::fmt;
8*ffe74184SMartin Algesten 
9*ffe74184SMartin Algesten // ErrorCodeAttribute represents ERROR-CODE attribute.
10*ffe74184SMartin Algesten //
11*ffe74184SMartin Algesten // RFC 5389 Section 15.6
12*ffe74184SMartin Algesten #[derive(Default)]
13*ffe74184SMartin Algesten pub struct ErrorCodeAttribute {
14*ffe74184SMartin Algesten     pub code: ErrorCode,
15*ffe74184SMartin Algesten     pub reason: Vec<u8>,
16*ffe74184SMartin Algesten }
17*ffe74184SMartin Algesten 
18*ffe74184SMartin Algesten impl fmt::Display for ErrorCodeAttribute {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result19*ffe74184SMartin Algesten     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
20*ffe74184SMartin Algesten         let reason = match String::from_utf8(self.reason.clone()) {
21*ffe74184SMartin Algesten             Ok(reason) => reason,
22*ffe74184SMartin Algesten             Err(_) => return Err(fmt::Error {}),
23*ffe74184SMartin Algesten         };
24*ffe74184SMartin Algesten 
25*ffe74184SMartin Algesten         write!(f, "{}: {}", self.code.0, reason)
26*ffe74184SMartin Algesten     }
27*ffe74184SMartin Algesten }
28*ffe74184SMartin Algesten 
29*ffe74184SMartin Algesten // constants for ERROR-CODE encoding.
30*ffe74184SMartin Algesten const ERROR_CODE_CLASS_BYTE: usize = 2;
31*ffe74184SMartin Algesten const ERROR_CODE_NUMBER_BYTE: usize = 3;
32*ffe74184SMartin Algesten const ERROR_CODE_REASON_START: usize = 4;
33*ffe74184SMartin Algesten const ERROR_CODE_REASON_MAX_B: usize = 763;
34*ffe74184SMartin Algesten const ERROR_CODE_MODULO: u16 = 100;
35*ffe74184SMartin Algesten 
36*ffe74184SMartin Algesten impl Setter for ErrorCodeAttribute {
37*ffe74184SMartin Algesten     // add_to adds ERROR-CODE to m.
add_to(&self, m: &mut Message) -> Result<()>38*ffe74184SMartin Algesten     fn add_to(&self, m: &mut Message) -> Result<()> {
39*ffe74184SMartin Algesten         check_overflow(
40*ffe74184SMartin Algesten             ATTR_ERROR_CODE,
41*ffe74184SMartin Algesten             self.reason.len() + ERROR_CODE_REASON_START,
42*ffe74184SMartin Algesten             ERROR_CODE_REASON_MAX_B + ERROR_CODE_REASON_START,
43*ffe74184SMartin Algesten         )?;
44*ffe74184SMartin Algesten 
45*ffe74184SMartin Algesten         let mut value: Vec<u8> = Vec::with_capacity(ERROR_CODE_REASON_MAX_B);
46*ffe74184SMartin Algesten 
47*ffe74184SMartin Algesten         let number = (self.code.0 % ERROR_CODE_MODULO) as u8; // error code modulo 100
48*ffe74184SMartin Algesten         let class = (self.code.0 / ERROR_CODE_MODULO) as u8; // hundred digit
49*ffe74184SMartin Algesten         value.extend_from_slice(&[0, 0]);
50*ffe74184SMartin Algesten         value.push(class); // [ERROR_CODE_CLASS_BYTE]
51*ffe74184SMartin Algesten         value.push(number); //[ERROR_CODE_NUMBER_BYTE] =
52*ffe74184SMartin Algesten         value.extend_from_slice(&self.reason); //[ERROR_CODE_REASON_START:]
53*ffe74184SMartin Algesten 
54*ffe74184SMartin Algesten         m.add(ATTR_ERROR_CODE, &value);
55*ffe74184SMartin Algesten 
56*ffe74184SMartin Algesten         Ok(())
57*ffe74184SMartin Algesten     }
58*ffe74184SMartin Algesten }
59*ffe74184SMartin Algesten 
60*ffe74184SMartin Algesten impl Getter for ErrorCodeAttribute {
61*ffe74184SMartin Algesten     // GetFrom decodes ERROR-CODE from m. Reason is valid until m.Raw is valid.
get_from(&mut self, m: &Message) -> Result<()>62*ffe74184SMartin Algesten     fn get_from(&mut self, m: &Message) -> Result<()> {
63*ffe74184SMartin Algesten         let v = m.get(ATTR_ERROR_CODE)?;
64*ffe74184SMartin Algesten 
65*ffe74184SMartin Algesten         if v.len() < ERROR_CODE_REASON_START {
66*ffe74184SMartin Algesten             return Err(Error::ErrUnexpectedEof);
67*ffe74184SMartin Algesten         }
68*ffe74184SMartin Algesten 
69*ffe74184SMartin Algesten         let class = v[ERROR_CODE_CLASS_BYTE] as u16;
70*ffe74184SMartin Algesten         let number = v[ERROR_CODE_NUMBER_BYTE] as u16;
71*ffe74184SMartin Algesten         let code = class * ERROR_CODE_MODULO + number;
72*ffe74184SMartin Algesten         self.code = ErrorCode(code);
73*ffe74184SMartin Algesten         self.reason = v[ERROR_CODE_REASON_START..].to_vec();
74*ffe74184SMartin Algesten 
75*ffe74184SMartin Algesten         Ok(())
76*ffe74184SMartin Algesten     }
77*ffe74184SMartin Algesten }
78*ffe74184SMartin Algesten 
79*ffe74184SMartin Algesten // ErrorCode is code for ERROR-CODE attribute.
80*ffe74184SMartin Algesten #[derive(PartialEq, Eq, Hash, Copy, Clone, Default)]
81*ffe74184SMartin Algesten pub struct ErrorCode(pub u16);
82*ffe74184SMartin Algesten 
83*ffe74184SMartin Algesten impl Setter for ErrorCode {
84*ffe74184SMartin Algesten     // add_to adds ERROR-CODE with default reason to m. If there
85*ffe74184SMartin Algesten     // is no default reason, returns ErrNoDefaultReason.
add_to(&self, m: &mut Message) -> Result<()>86*ffe74184SMartin Algesten     fn add_to(&self, m: &mut Message) -> Result<()> {
87*ffe74184SMartin Algesten         if let Some(reason) = ERROR_REASONS.get(self) {
88*ffe74184SMartin Algesten             let a = ErrorCodeAttribute {
89*ffe74184SMartin Algesten                 code: *self,
90*ffe74184SMartin Algesten                 reason: reason.clone(),
91*ffe74184SMartin Algesten             };
92*ffe74184SMartin Algesten             a.add_to(m)
93*ffe74184SMartin Algesten         } else {
94*ffe74184SMartin Algesten             Err(Error::ErrNoDefaultReason)
95*ffe74184SMartin Algesten         }
96*ffe74184SMartin Algesten     }
97*ffe74184SMartin Algesten }
98*ffe74184SMartin Algesten 
99*ffe74184SMartin Algesten // Possible error codes.
100*ffe74184SMartin Algesten pub const CODE_TRY_ALTERNATE: ErrorCode = ErrorCode(300);
101*ffe74184SMartin Algesten pub const CODE_BAD_REQUEST: ErrorCode = ErrorCode(400);
102*ffe74184SMartin Algesten pub const CODE_UNAUTHORIZED: ErrorCode = ErrorCode(401);
103*ffe74184SMartin Algesten pub const CODE_UNKNOWN_ATTRIBUTE: ErrorCode = ErrorCode(420);
104*ffe74184SMartin Algesten pub const CODE_STALE_NONCE: ErrorCode = ErrorCode(438);
105*ffe74184SMartin Algesten pub const CODE_ROLE_CONFLICT: ErrorCode = ErrorCode(487);
106*ffe74184SMartin Algesten pub const CODE_SERVER_ERROR: ErrorCode = ErrorCode(500);
107*ffe74184SMartin Algesten 
108*ffe74184SMartin Algesten // DEPRECATED constants.
109*ffe74184SMartin Algesten // DEPRECATED, use CODE_UNAUTHORIZED.
110*ffe74184SMartin Algesten pub const CODE_UNAUTHORISED: ErrorCode = CODE_UNAUTHORIZED;
111*ffe74184SMartin Algesten 
112*ffe74184SMartin Algesten // Error codes from RFC 5766.
113*ffe74184SMartin Algesten //
114*ffe74184SMartin Algesten // RFC 5766 Section 15
115*ffe74184SMartin Algesten pub const CODE_FORBIDDEN: ErrorCode = ErrorCode(403); // Forbidden
116*ffe74184SMartin Algesten pub const CODE_ALLOC_MISMATCH: ErrorCode = ErrorCode(437); // Allocation Mismatch
117*ffe74184SMartin Algesten pub const CODE_WRONG_CREDENTIALS: ErrorCode = ErrorCode(441); // Wrong Credentials
118*ffe74184SMartin Algesten pub const CODE_UNSUPPORTED_TRANS_PROTO: ErrorCode = ErrorCode(442); // Unsupported Transport Protocol
119*ffe74184SMartin Algesten pub const CODE_ALLOC_QUOTA_REACHED: ErrorCode = ErrorCode(486); // Allocation Quota Reached
120*ffe74184SMartin Algesten pub const CODE_INSUFFICIENT_CAPACITY: ErrorCode = ErrorCode(508); // Insufficient Capacity
121*ffe74184SMartin Algesten 
122*ffe74184SMartin Algesten // Error codes from RFC 6062.
123*ffe74184SMartin Algesten //
124*ffe74184SMartin Algesten // RFC 6062 Section 6.3
125*ffe74184SMartin Algesten pub const CODE_CONN_ALREADY_EXISTS: ErrorCode = ErrorCode(446);
126*ffe74184SMartin Algesten pub const CODE_CONN_TIMEOUT_OR_FAILURE: ErrorCode = ErrorCode(447);
127*ffe74184SMartin Algesten 
128*ffe74184SMartin Algesten // Error codes from RFC 6156.
129*ffe74184SMartin Algesten //
130*ffe74184SMartin Algesten // RFC 6156 Section 10.2
131*ffe74184SMartin Algesten pub const CODE_ADDR_FAMILY_NOT_SUPPORTED: ErrorCode = ErrorCode(440); // Address Family not Supported
132*ffe74184SMartin Algesten pub const CODE_PEER_ADDR_FAMILY_MISMATCH: ErrorCode = ErrorCode(443); // Peer Address Family Mismatch
133*ffe74184SMartin Algesten 
134*ffe74184SMartin Algesten lazy_static! {
135*ffe74184SMartin Algesten     pub static ref ERROR_REASONS:HashMap<ErrorCode, Vec<u8>> =
136*ffe74184SMartin Algesten         [
137*ffe74184SMartin Algesten             (CODE_TRY_ALTERNATE,     b"Try Alternate".to_vec()),
138*ffe74184SMartin Algesten             (CODE_BAD_REQUEST,       b"Bad Request".to_vec()),
139*ffe74184SMartin Algesten             (CODE_UNAUTHORIZED,     b"Unauthorized".to_vec()),
140*ffe74184SMartin Algesten             (CODE_UNKNOWN_ATTRIBUTE, b"Unknown Attribute".to_vec()),
141*ffe74184SMartin Algesten             (CODE_STALE_NONCE,       b"Stale Nonce".to_vec()),
142*ffe74184SMartin Algesten             (CODE_SERVER_ERROR,      b"Server Error".to_vec()),
143*ffe74184SMartin Algesten             (CODE_ROLE_CONFLICT,     b"Role Conflict".to_vec()),
144*ffe74184SMartin Algesten 
145*ffe74184SMartin Algesten             // RFC 5766.
146*ffe74184SMartin Algesten             (CODE_FORBIDDEN,             b"Forbidden".to_vec()),
147*ffe74184SMartin Algesten             (CODE_ALLOC_MISMATCH,         b"Allocation Mismatch".to_vec()),
148*ffe74184SMartin Algesten             (CODE_WRONG_CREDENTIALS,      b"Wrong Credentials".to_vec()),
149*ffe74184SMartin Algesten             (CODE_UNSUPPORTED_TRANS_PROTO, b"Unsupported Transport Protocol".to_vec()),
150*ffe74184SMartin Algesten             (CODE_ALLOC_QUOTA_REACHED,     b"Allocation Quota Reached".to_vec()),
151*ffe74184SMartin Algesten             (CODE_INSUFFICIENT_CAPACITY,  b"Insufficient Capacity".to_vec()),
152*ffe74184SMartin Algesten 
153*ffe74184SMartin Algesten             // RFC 6062.
154*ffe74184SMartin Algesten             (CODE_CONN_ALREADY_EXISTS,    b"Connection Already Exists".to_vec()),
155*ffe74184SMartin Algesten             (CODE_CONN_TIMEOUT_OR_FAILURE, b"Connection Timeout or Failure".to_vec()),
156*ffe74184SMartin Algesten 
157*ffe74184SMartin Algesten             // RFC 6156.
158*ffe74184SMartin Algesten             (CODE_ADDR_FAMILY_NOT_SUPPORTED, b"Address Family not Supported".to_vec()),
159*ffe74184SMartin Algesten             (CODE_PEER_ADDR_FAMILY_MISMATCH, b"Peer Address Family Mismatch".to_vec()),
160*ffe74184SMartin Algesten         ].iter().cloned().collect();
161*ffe74184SMartin Algesten 
162*ffe74184SMartin Algesten }
163