hawk_ws/
protocol.rs

1use std::convert::{From, Into};
2use std::fmt;
3
4use self::OpCode::*;
5/// Operation codes as part of rfc6455.
6#[derive(Debug, Eq, PartialEq, Clone, Copy)]
7pub enum OpCode {
8    /// Indicates a continuation frame of a fragmented message.
9    Continue,
10    /// Indicates a text data frame.
11    Text,
12    /// Indicates a binary data frame.
13    Binary,
14    /// Indicates a close control frame.
15    Close,
16    /// Indicates a ping control frame.
17    Ping,
18    /// Indicates a pong control frame.
19    Pong,
20    /// Indicates an invalid opcode was received.
21    Bad,
22}
23
24impl OpCode {
25    /// Test whether the opcode indicates a control frame.
26    pub fn is_control(&self) -> bool {
27        match *self {
28            Text | Binary | Continue => false,
29            _ => true,
30        }
31    }
32}
33
34impl fmt::Display for OpCode {
35    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
36        match *self {
37            Continue => write!(f, "CONTINUE"),
38            Text => write!(f, "TEXT"),
39            Binary => write!(f, "BINARY"),
40            Close => write!(f, "CLOSE"),
41            Ping => write!(f, "PING"),
42            Pong => write!(f, "PONG"),
43            Bad => write!(f, "BAD"),
44        }
45    }
46}
47
48impl Into<u8> for OpCode {
49    fn into(self) -> u8 {
50        match self {
51            Continue => 0,
52            Text => 1,
53            Binary => 2,
54            Close => 8,
55            Ping => 9,
56            Pong => 10,
57            Bad => {
58                debug_assert!(
59                    false,
60                    "Attempted to convert invalid opcode to u8. This is a bug."
61                );
62                8 // if this somehow happens, a close frame will help us tear down quickly
63            }
64        }
65    }
66}
67
68impl From<u8> for OpCode {
69    fn from(byte: u8) -> OpCode {
70        match byte {
71            0 => Continue,
72            1 => Text,
73            2 => Binary,
74            8 => Close,
75            9 => Ping,
76            10 => Pong,
77            _ => Bad,
78        }
79    }
80}
81
82use self::CloseCode::*;
83/// Status code used to indicate why an endpoint is closing the WebSocket connection.
84#[derive(Debug, Eq, PartialEq, Clone, Copy)]
85pub enum CloseCode {
86    /// Indicates a normal closure, meaning that the purpose for
87    /// which the connection was established has been fulfilled.
88    Normal,
89    /// Indicates that an endpoint is "going away", such as a server
90    /// going down or a browser having navigated away from a page.
91    Away,
92    /// Indicates that an endpoint is terminating the connection due
93    /// to a protocol error.
94    Protocol,
95    /// Indicates that an endpoint is terminating the connection
96    /// because it has received a type of data it cannot accept (e.g., an
97    /// endpoint that understands only text data MAY send this if it
98    /// receives a binary message).
99    Unsupported,
100    /// Indicates that no status code was included in a closing frame. This
101    /// close code makes it possible to use a single method, `on_close` to
102    /// handle even cases where no close code was provided.
103    Status,
104    /// Indicates an abnormal closure. If the abnormal closure was due to an
105    /// error, this close code will not be used. Instead, the `on_error` method
106    /// of the handler will be called with the error. However, if the connection
107    /// is simply dropped, without an error, this close code will be sent to the
108    /// handler.
109    Abnormal,
110    /// Indicates that an endpoint is terminating the connection
111    /// because it has received data within a message that was not
112    /// consistent with the type of the message (e.g., non-UTF-8 [RFC3629]
113    /// data within a text message).
114    Invalid,
115    /// Indicates that an endpoint is terminating the connection
116    /// because it has received a message that violates its policy.  This
117    /// is a generic status code that can be returned when there is no
118    /// other more suitable status code (e.g., Unsupported or Size) or if there
119    /// is a need to hide specific details about the policy.
120    Policy,
121    /// Indicates that an endpoint is terminating the connection
122    /// because it has received a message that is too big for it to
123    /// process.
124    Size,
125    /// Indicates that an endpoint (client) is terminating the
126    /// connection because it has expected the server to negotiate one or
127    /// more extension, but the server didn't return them in the response
128    /// message of the WebSocket handshake.  The list of extensions that
129    /// are needed should be given as the reason for closing.
130    /// Note that this status code is not used by the server, because it
131    /// can fail the WebSocket handshake instead.
132    Extension,
133    /// Indicates that a server is terminating the connection because
134    /// it encountered an unexpected condition that prevented it from
135    /// fulfilling the request.
136    Error,
137    /// Indicates that the server is restarting. A client may choose to reconnect,
138    /// and if it does, it should use a randomized delay of 5-30 seconds between attempts.
139    Restart,
140    /// Indicates that the server is overloaded and the client should either connect
141    /// to a different IP (when multiple targets exist), or reconnect to the same IP
142    /// when a user has performed an action.
143    Again,
144    #[doc(hidden)]
145    Tls,
146    #[doc(hidden)]
147    Empty,
148    #[doc(hidden)]
149    Other(u16),
150}
151
152impl Into<u16> for CloseCode {
153    fn into(self) -> u16 {
154        match self {
155            Normal => 1000,
156            Away => 1001,
157            Protocol => 1002,
158            Unsupported => 1003,
159            Status => 1005,
160            Abnormal => 1006,
161            Invalid => 1007,
162            Policy => 1008,
163            Size => 1009,
164            Extension => 1010,
165            Error => 1011,
166            Restart => 1012,
167            Again => 1013,
168            Tls => 1015,
169            Empty => 0,
170            Other(code) => code,
171        }
172    }
173}
174
175impl From<u16> for CloseCode {
176    fn from(code: u16) -> CloseCode {
177        match code {
178            1000 => Normal,
179            1001 => Away,
180            1002 => Protocol,
181            1003 => Unsupported,
182            1005 => Status,
183            1006 => Abnormal,
184            1007 => Invalid,
185            1008 => Policy,
186            1009 => Size,
187            1010 => Extension,
188            1011 => Error,
189            1012 => Restart,
190            1013 => Again,
191            1015 => Tls,
192            0 => Empty,
193            _ => Other(code),
194        }
195    }
196}
197
198mod test {
199    #![allow(unused_imports, unused_variables, dead_code)]
200    use super::*;
201
202    #[test]
203    fn opcode_from_u8() {
204        let byte = 2u8;
205        assert_eq!(OpCode::from(byte), OpCode::Binary);
206    }
207
208    #[test]
209    fn opcode_into_u8() {
210        let text = OpCode::Text;
211        let byte: u8 = text.into();
212        assert_eq!(byte, 1u8);
213    }
214
215    #[test]
216    fn closecode_from_u16() {
217        let byte = 1008u16;
218        assert_eq!(CloseCode::from(byte), CloseCode::Policy);
219    }
220
221    #[test]
222    fn closecode_into_u16() {
223        let text = CloseCode::Away;
224        let byte: u16 = text.into();
225        assert_eq!(byte, 1001u16);
226    }
227}