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(Message),
59 #[error("UTF-8 encoding error")]
61 Utf8,
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(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(_: str::Utf8Error) -> Self {
80 Error::Utf8
81 }
82}
83
84impl From<string::FromUtf8Error> for Error {
85 fn from(_: string::FromUtf8Error) -> Self {
86 Error::Utf8
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(_: http::header::ToStrError) -> Self {
107 Error::Utf8
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#[allow(missing_copy_implementations)]
154#[derive(Error, Debug, PartialEq, Eq, Clone)]
155pub enum ProtocolError {
156 #[error("Unsupported HTTP method used - only GET is allowed")]
158 WrongHttpMethod,
159 #[error("HTTP version must be 1.1 or higher")]
161 WrongHttpVersion,
162 #[error("No \"Connection: upgrade\" header")]
164 MissingConnectionUpgradeHeader,
165 #[error("No \"Upgrade: websocket\" header")]
167 MissingUpgradeWebSocketHeader,
168 #[error("No \"Sec-WebSocket-Version: 13\" header")]
170 MissingSecWebSocketVersionHeader,
171 #[error("No \"Sec-WebSocket-Key\" header")]
173 MissingSecWebSocketKey,
174 #[error("Key mismatch in \"Sec-WebSocket-Accept\" header")]
176 SecWebSocketAcceptKeyMismatch,
177 #[error("Junk after client request")]
179 JunkAfterRequest,
180 #[error("Custom response must not be successful")]
182 CustomResponseSuccessful,
183 #[error("Missing, duplicated or incorrect header {0}")]
185 #[cfg(feature = "handshake")]
186 InvalidHeader(HeaderName),
187 #[error("Handshake not finished")]
189 HandshakeIncomplete,
190 #[error("httparse error: {0}")]
192 #[cfg(feature = "handshake")]
193 HttparseError(#[from] httparse::Error),
194 #[error("Sending after closing is not allowed")]
196 SendAfterClosing,
197 #[error("Remote sent after having closed")]
199 ReceivedAfterClosing,
200 #[error("Reserved bits are non-zero")]
202 NonZeroReservedBits,
203 #[error("Received an unmasked frame from client")]
205 UnmaskedFrameFromClient,
206 #[error("Received a masked frame from server")]
208 MaskedFrameFromServer,
209 #[error("Fragmented control frame")]
211 FragmentedControlFrame,
212 #[error("Control frame too big (payload must be 125 bytes or less)")]
214 ControlFrameTooBig,
215 #[error("Unknown control frame type: {0}")]
217 UnknownControlFrameType(u8),
218 #[error("Unknown data frame type: {0}")]
220 UnknownDataFrameType(u8),
221 #[error("Continue frame but nothing to continue")]
223 UnexpectedContinueFrame,
224 #[error("While waiting for more fragments received: {0}")]
226 ExpectedFragment(Data),
227 #[error("Connection reset without closing handshake")]
229 ResetWithoutClosingHandshake,
230 #[error("Encountered invalid opcode: {0}")]
232 InvalidOpcode(u8),
233 #[error("Invalid close sequence")]
235 InvalidCloseSequence,
236}
237
238#[derive(Error, Debug, PartialEq, Eq)]
240pub enum UrlError {
241 #[error("TLS support not compiled in")]
243 TlsFeatureNotEnabled,
244 #[error("No host name in the URL")]
246 NoHostName,
247 #[error("Unable to connect to {0}")]
249 UnableToConnect(String),
250 #[error("URL scheme not supported")]
252 UnsupportedUrlScheme,
253 #[error("URL contains empty host name")]
255 EmptyHostName,
256 #[error("No path/query in URL")]
258 NoPathOrQuery,
259}
260
261#[allow(missing_copy_implementations)]
266#[derive(Error, Debug)]
267#[non_exhaustive]
268pub enum TlsError {
269 #[cfg(feature = "native-tls")]
271 #[error("native-tls error: {0}")]
272 Native(#[from] native_tls_crate::Error),
273 #[cfg(feature = "__rustls-tls")]
275 #[error("rustls error: {0}")]
276 Rustls(#[from] rustls::Error),
277 #[cfg(feature = "__rustls-tls")]
279 #[error("Invalid DNS name")]
280 InvalidDnsName,
281}