websocket_stream/
util.rs

1// The MIT License (MIT)
2//
3// Copyright (c) 2015 Nathan Sizemore <nathanrsizemore@gmail.com>
4//
5// Permission is hereby granted, free of charge, to any person obtaining a copy
6// of this software and associated documentation files (the "Software"), to deal
7// in the Software without restriction, including without limitation the rights
8// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9// copies of the Software, and to permit persons to whom the Software is
10// furnished to do so, subject to the following conditions:
11//
12// The above copyright notice and this permission notice shall be included in all
13// copies or substantial portions of the Software.
14//
15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21// SOFTWARE.
22
23
24use std::fmt;
25
26
27/// Decodes OpCode
28pub const OP_CODE_UN_MASK: u8 = 0b0000_1111;
29
30/// Encodes OpCode
31pub const OP_CODE_MASK: u8 = 0b1000_0000;
32
33/// Decodes payload
34pub const PAYLOAD_KEY_UN_MASK: u8 = 0b0111_1111;
35
36/// Continuation Op byte
37pub const OP_CONTINUATION: u8 = 0x0;
38
39/// Text Op byte
40pub const OP_TEXT: u8 = 0x1;
41
42/// Binary Op byte
43pub const OP_BINARY: u8 = 0x2;
44
45/// Close Op byte
46pub const OP_CLOSE: u8 = 0x8;
47
48/// Ping Op byte
49pub const OP_PING: u8 = 0x9;
50
51/// Pong Op byte
52pub const OP_PONG: u8 = 0xA;
53
54
55#[derive(Debug, Clone)]
56pub enum OpCode {
57    /// Continuation frame from last packed
58    Continuation,
59
60    /// UTF-8 text data
61    Text,
62
63    /// Binary data as u8
64    Binary,
65
66    /// Indicates client has closed connection
67    Close,
68
69    /// Heartbeat requested from client
70    Ping,
71
72    /// Heartbeat response to ping frame
73    /// Can also be sent without a ping request
74    Pong
75}
76
77#[derive(Debug)]
78pub enum ReadError {
79    /// Non-blocking I/O has been selected using O_NONBLOCK and the
80    /// read would block.
81    EAGAIN,
82
83    /// fd is not a valid file descriptor or is not open for reading
84    EBADF,
85
86    /// buf is outside your accessible address space
87    EFAULT,
88
89    /// The call was interrupted by a signal before any data was read
90    EINTR,
91
92    /// fd is attached to an object which is unsuitable for reading;
93    /// or the file was opened with the O_DIRECT flag, and either the address
94    /// specified in buf, the value specified in count, or the current file
95    /// offset is not suitably aligned
96    EINVAL,
97
98    /// I/O error. This will happen for example when the process is in a
99    /// background process group, tries to read from its controlling tty,
100    /// and either it is ignoring or blocking SIGTTIN or its process group
101    /// is orphaned. It may also occur when there is a low-level I/O error
102    /// while reading from a disk or tape.
103    EIO,
104
105    /// fd refers to a directory.
106    EISDIR,
107
108    /// Insufficient memory is available
109    ENOMEM,
110
111    /// Invalid OpCode.
112    /// According to RFC-6455: "If an unknown opcode is received,
113    /// the receiving endpoint MUST _Fail the WebSocket Connection_"
114    OpCode
115}
116
117#[derive(Debug)]
118pub enum WriteError {
119    /// Non-blocking I/O has been selected using O_NONBLOCK and the
120    /// write would block.
121    EAGAIN,
122
123    /// fd is not a valid file descriptor or is not open for writing.
124    EBADF,
125
126    /// buf is outside your accessible address space.
127    EFAULT,
128
129    /// An attempt was made to write a file that exceeds the
130    /// implementation-defined maximum file size or the process’ file size
131    /// limit, or to write at a position past the maximum allowed offset.
132    EFBIG,
133
134    /// The call was interrupted by a signal before any data was written.
135    EINTR,
136
137    /// fd is attached to an object which is unsuitable for writing; or the
138    /// file was opened with the O_DIRECT flag, and either the address
139    /// specified in buf, the value specified in count, or the current file
140    /// offset is not suitably aligned.
141    EINVAL,
142
143    /// A low-level I/O error occurred while modifying the inode.
144    EIO,
145
146    /// The device containing the file referred to by fd has no room for
147    /// the data.
148    ENOSPC,
149
150    /// fd is connected to a pipe or socket whose reading end is closed.
151    /// When this happens the writing process will also receive a SIGPIPE
152    /// signal. (Thus, the write return value is seen only if the program
153    /// catches, blocks or ignores this signal.)
154    EPIPE
155}
156
157#[derive(Debug)]
158pub enum SetFdError {
159    /// Operation is prohibited by locks held by other processes.
160    EACCES,
161
162    /// Operation is prohibited by locks held by other processes.
163    EAGAIN,
164
165    /// fd is not an open file descriptor, or the command was F_SETLK or
166    /// F_SETLKW and the file descriptor open mode doesn’t match with the
167    /// type of lock requested.
168    EBADF,
169
170    /// It was detected that the specified F_SETLKW command would
171    /// cause a deadlock.
172    EDEADLK,
173
174    /// lock is outside your accessible address space.
175    EFAULT,
176
177    /// For F_SETLKW, the command was interrupted by a signal. For F_GETLK
178    /// and F_SETLK, the command was interrupted by a signal before the lock
179    /// was checked or acquired. Most likely when locking a remote file
180    /// (e.g. locking over NFS), but can sometimes happen locally.
181    EINTR,
182
183    /// For F_DUPFD, arg is negative or is greater than the maximum allowable
184    /// value. For F_SETSIG, arg is not an allowable signal number.
185    EINVAL,
186
187    /// For F_DUPFD, the process already has the maximum number of file
188    /// descriptors open.
189    EMFILE,
190
191    /// Too many segment locks open, lock table is full, or a remote locking
192    /// protocol failed (e.g. locking over NFS).
193    ENOLCK,
194
195    /// Attempted to clear the O_APPEND flag on a file that has the
196    /// append-only attribute set.
197    EPERM
198}
199
200impl fmt::Display for ReadError {
201    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
202        match *self {
203            ReadError::EAGAIN   => "EAGAIN".fmt(f),
204            ReadError::EBADF    => "EBADF".fmt(f),
205            ReadError::EFAULT   => "EFAULT".fmt(f),
206            ReadError::EINTR    => "EINTR".fmt(f),
207            ReadError::EINVAL   => "EINVAL".fmt(f),
208            ReadError::EIO      => "EIO".fmt(f),
209            ReadError::EISDIR   => "EISDIR".fmt(f),
210            ReadError::ENOMEM   => "ENOMEM".fmt(f),
211            ReadError::OpCode   => "OpCode".fmt(f)
212        }
213    }
214}
215
216impl fmt::Display for WriteError {
217    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
218        match *self {
219            WriteError::EAGAIN  => "EAGAIN".fmt(f),
220            WriteError::EBADF   => "EBADF".fmt(f),
221            WriteError::EFAULT  => "EFAULT".fmt(f),
222            WriteError::EFBIG   => "EFBIG".fmt(f),
223            WriteError::EINTR   => "EINTR".fmt(f),
224            WriteError::EINVAL  => "EINVAL".fmt(f),
225            WriteError::EIO     => "EIO".fmt(f),
226            WriteError::ENOSPC  => "ENOSPC".fmt(f),
227            WriteError::EPIPE   => "EPIPE".fmt(f)
228        }
229    }
230}
231
232impl fmt::Display for SetFdError {
233    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
234        match *self {
235            SetFdError::EACCES => "EACCES".fmt(f),
236            SetFdError::EAGAIN => "EAGAIN".fmt(f),
237            SetFdError::EBADF => "EBADF".fmt(f),
238            SetFdError::EDEADLK => "EDEADLK".fmt(f),
239            SetFdError::EFAULT => "EFAULT".fmt(f),
240            SetFdError::EINTR => "EINTR".fmt(f),
241            SetFdError::EINVAL => "EINVAL".fmt(f),
242            SetFdError::EMFILE => "EMFILE".fmt(f),
243            SetFdError::ENOLCK => "ENOLCK".fmt(f),
244            SetFdError::EPERM => "EPERM".fmt(f)
245        }
246    }
247}
248
249impl fmt::Display for OpCode {
250    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
251        match *self {
252            OpCode::Continuation => "Continuation".fmt(f),
253            OpCode::Text => "Text".fmt(f),
254            OpCode::Binary => "Binary".fmt(f),
255            OpCode::Close => "Close".fmt(f),
256            OpCode::Ping => "Ping".fmt(f),
257            OpCode::Pong => "Pong".fmt(f),
258        }
259    }
260}