webrtc_stun/
error_code.rs

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