1use std::{io, result, str, string};
4
5use crate::protocol::{frame::coding::Data, Message};
6#[cfg(feature = "handshake")]
7use http::{header::HeaderName, Response};
8use thiserror::Error;
9
10pub type Result<T, E = Error> = result::Result<T, E>;
12
13#[derive(Error, Debug)]
15pub enum Error {
16 #[error("Connection closed normally")]
28 ConnectionClosed,
29 #[error("Trying to work with closed connection")]
37 AlreadyClosed,
38 #[error("IO error: {0}")]
41 Io(#[from] io::Error),
42 #[error("TLS error: {0}")]
47 Tls(#[from] TlsError),
48 #[error("Space limit exceeded: {0}")]
52 Capacity(#[from] CapacityError),
53 #[error("WebSocket protocol error: {0}")]
55 Protocol(#[from] ProtocolError),
56 #[error("Write buffer is full")]
58 WriteBufferFull(Box<Message>),
59 #[error("UTF-8 encoding error: {0}")]
61 Utf8(String),
62 #[error("Attack attempt detected")]
64 AttackAttempt,
65 #[error("URL error: {0}")]
67 Url(#[from] UrlError),
68 #[error("HTTP error: {}", .0.status())]
70 #[cfg(feature = "handshake")]
71 Http(Box<Response<Option<Vec<u8>>>>),
72 #[error("HTTP format error: {0}")]
74 #[cfg(feature = "handshake")]
75 HttpFormat(#[from] http::Error),
76}
77
78impl From<str::Utf8Error> for Error {
79 fn from(err: str::Utf8Error) -> Self {
80 Error::Utf8(err.to_string())
81 }
82}
83
84impl From<string::FromUtf8Error> for Error {
85 fn from(err: string::FromUtf8Error) -> Self {
86 Error::Utf8(err.to_string())
87 }
88}
89
90#[cfg(feature = "handshake")]
91impl From<http::header::InvalidHeaderValue> for Error {
92 fn from(err: http::header::InvalidHeaderValue) -> Self {
93 Error::HttpFormat(err.into())
94 }
95}
96
97#[cfg(feature = "handshake")]
98impl From<http::header::InvalidHeaderName> for Error {
99 fn from(err: http::header::InvalidHeaderName) -> Self {
100 Error::HttpFormat(err.into())
101 }
102}
103
104#[cfg(feature = "handshake")]
105impl From<http::header::ToStrError> for Error {
106 fn from(err: http::header::ToStrError) -> Self {
107 Error::Utf8(err.to_string())
108 }
109}
110
111#[cfg(feature = "handshake")]
112impl From<http::uri::InvalidUri> for Error {
113 fn from(err: http::uri::InvalidUri) -> Self {
114 Error::HttpFormat(err.into())
115 }
116}
117
118#[cfg(feature = "handshake")]
119impl From<http::status::InvalidStatusCode> for Error {
120 fn from(err: http::status::InvalidStatusCode) -> Self {
121 Error::HttpFormat(err.into())
122 }
123}
124
125#[cfg(feature = "handshake")]
126impl From<httparse::Error> for Error {
127 fn from(err: httparse::Error) -> Self {
128 match err {
129 httparse::Error::TooManyHeaders => Error::Capacity(CapacityError::TooManyHeaders),
130 e => Error::Protocol(ProtocolError::HttparseError(e)),
131 }
132 }
133}
134
135#[derive(Error, Debug, PartialEq, Eq, Clone, Copy)]
137pub enum CapacityError {
138 #[error("Too many headers")]
140 TooManyHeaders,
141 #[error("Message too long: {size} > {max_size}")]
144 MessageTooLong {
145 size: usize,
147 max_size: usize,
149 },
150}
151
152#[derive(Error, Clone, PartialEq, Eq, Debug, Copy)]
154pub enum SubProtocolError {
155 #[error("Server sent a subprotocol but none was requested")]
157 ServerSentSubProtocolNoneRequested,
158
159 #[error("Server sent an invalid subprotocol")]
161 InvalidSubProtocol,
162
163 #[error("Server sent no subprotocol")]
166 NoSubProtocol,
167}
168
169#[allow(missing_copy_implementations)]
171#[derive(Error, Debug, PartialEq, Eq, Clone)]
172pub enum ProtocolError {
173 #[error("Unsupported HTTP method used - only GET is allowed")]
175 WrongHttpMethod,
176 #[error("HTTP version must be 1.1 or higher")]
178 WrongHttpVersion,
179 #[error("No \"Connection: upgrade\" header")]
181 MissingConnectionUpgradeHeader,
182 #[error("No \"Upgrade: websocket\" header")]
184 MissingUpgradeWebSocketHeader,
185 #[error("No \"Sec-WebSocket-Version: 13\" header")]
187 MissingSecWebSocketVersionHeader,
188 #[error("No \"Sec-WebSocket-Key\" header")]
190 MissingSecWebSocketKey,
191 #[error("Invalid \"Sec-WebSocket-Key\" header value")]
193 InvalidSecWebSocketKey,
194 #[error("Key mismatch in \"Sec-WebSocket-Accept\" header")]
196 SecWebSocketAcceptKeyMismatch,
197 #[error("SubProtocol error: {0}")]
199 SecWebSocketSubProtocolError(SubProtocolError),
200 #[error("Junk after client request")]
202 JunkAfterRequest,
203 #[error("Custom response must not be successful")]
205 CustomResponseSuccessful,
206 #[error("Missing, duplicated or incorrect header {0}")]
208 #[cfg(feature = "handshake")]
209 InvalidHeader(Box<HeaderName>),
210 #[error("Handshake not finished")]
212 HandshakeIncomplete,
213 #[error("httparse error: {0}")]
215 #[cfg(feature = "handshake")]
216 HttparseError(#[from] httparse::Error),
217 #[error("Sending after closing is not allowed")]
219 SendAfterClosing,
220 #[error("Remote sent after having closed")]
222 ReceivedAfterClosing,
223 #[error("Reserved bits are non-zero")]
225 NonZeroReservedBits,
226 #[error("Received an unmasked frame from client")]
228 UnmaskedFrameFromClient,
229 #[error("Received a masked frame from server")]
231 MaskedFrameFromServer,
232 #[error("Fragmented control frame")]
234 FragmentedControlFrame,
235 #[error("Control frame too big (payload must be 125 bytes or less)")]
237 ControlFrameTooBig,
238 #[error("Unknown control frame type: {0}")]
240 UnknownControlFrameType(u8),
241 #[error("Unknown data frame type: {0}")]
243 UnknownDataFrameType(u8),
244 #[error("Continue frame but nothing to continue")]
246 UnexpectedContinueFrame,
247 #[error("While waiting for more fragments received: {0}")]
249 ExpectedFragment(Data),
250 #[error("Connection reset without closing handshake")]
252 ResetWithoutClosingHandshake,
253 #[error("Encountered invalid opcode: {0}")]
255 InvalidOpcode(u8),
256 #[error("Invalid close sequence")]
258 InvalidCloseSequence,
259}
260
261#[derive(Error, Debug, PartialEq, Eq)]
263pub enum UrlError {
264 #[error("TLS support not compiled in")]
266 TlsFeatureNotEnabled,
267 #[error("No host name in the URL")]
269 NoHostName,
270 #[error("Unable to connect to {0}")]
272 UnableToConnect(String),
273 #[error("URL scheme not supported")]
275 UnsupportedUrlScheme,
276 #[error("URL contains empty host name")]
278 EmptyHostName,
279 #[error("No path/query in URL")]
281 NoPathOrQuery,
282}
283
284#[allow(missing_copy_implementations)]
289#[derive(Error, Debug)]
290#[non_exhaustive]
291pub enum TlsError {
292 #[cfg(feature = "native-tls")]
294 #[error("native-tls error: {0}")]
295 Native(Box<native_tls_crate::Error>),
296 #[cfg(feature = "__rustls-tls")]
298 #[error("rustls error: {0}")]
299 Rustls(Box<rustls::Error>),
300 #[cfg(feature = "__rustls-tls")]
302 #[error("Invalid DNS name")]
303 InvalidDnsName,
304}
305
306#[cfg(feature = "native-tls")]
307impl From<native_tls_crate::Error> for TlsError {
308 fn from(e: native_tls_crate::Error) -> Self {
309 Self::Native(e.into())
310 }
311}
312
313#[cfg(feature = "__rustls-tls")]
314impl From<rustls::Error> for TlsError {
315 fn from(e: rustls::Error) -> Self {
316 Self::Rustls(e.into())
317 }
318}
319
320#[cfg(test)]
321mod test {
322 #[test]
323 fn error_size() {
324 let size = std::mem::size_of::<crate::Error>();
325 assert!(size <= 32, "Error is large: {size}");
326 }
327
328 #[test]
329 fn tls_error_size() {
330 let size = std::mem::size_of::<crate::error::TlsError>();
331 assert!(size <= 16, "TlsError is large: {size}");
332 }
333
334 #[test]
335 fn protocol_error_size() {
336 let size = std::mem::size_of::<crate::error::ProtocolError>();
337 assert!(size <= 16, "ProtocolError is large: {size}");
338 }
339}