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#[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("Key mismatch in \"Sec-WebSocket-Accept\" header")]
193 SecWebSocketAcceptKeyMismatch,
194 #[error("SubProtocol error: {0}")]
196 SecWebSocketSubProtocolError(SubProtocolError),
197 #[error("Junk after client request")]
199 JunkAfterRequest,
200 #[error("Custom response must not be successful")]
202 CustomResponseSuccessful,
203 #[error("Missing, duplicated or incorrect header {0}")]
205 #[cfg(feature = "handshake")]
206 InvalidHeader(HeaderName),
207 #[error("Handshake not finished")]
209 HandshakeIncomplete,
210 #[error("httparse error: {0}")]
212 #[cfg(feature = "handshake")]
213 HttparseError(#[from] httparse::Error),
214 #[error("Sending after closing is not allowed")]
216 SendAfterClosing,
217 #[error("Remote sent after having closed")]
219 ReceivedAfterClosing,
220 #[error("Reserved bits are non-zero")]
222 NonZeroReservedBits,
223 #[error("Received an unmasked frame from client")]
225 UnmaskedFrameFromClient,
226 #[error("Received a masked frame from server")]
228 MaskedFrameFromServer,
229 #[error("Fragmented control frame")]
231 FragmentedControlFrame,
232 #[error("Control frame too big (payload must be 125 bytes or less)")]
234 ControlFrameTooBig,
235 #[error("Unknown control frame type: {0}")]
237 UnknownControlFrameType(u8),
238 #[error("Unknown data frame type: {0}")]
240 UnknownDataFrameType(u8),
241 #[error("Continue frame but nothing to continue")]
243 UnexpectedContinueFrame,
244 #[error("While waiting for more fragments received: {0}")]
246 ExpectedFragment(Data),
247 #[error("Connection reset without closing handshake")]
249 ResetWithoutClosingHandshake,
250 #[error("Encountered invalid opcode: {0}")]
252 InvalidOpcode(u8),
253 #[error("Invalid close sequence")]
255 InvalidCloseSequence,
256}
257
258#[derive(Error, Debug, PartialEq, Eq)]
260pub enum UrlError {
261 #[error("TLS support not compiled in")]
263 TlsFeatureNotEnabled,
264 #[error("No host name in the URL")]
266 NoHostName,
267 #[error("Unable to connect to {0}")]
269 UnableToConnect(String),
270 #[error("URL scheme not supported")]
272 UnsupportedUrlScheme,
273 #[error("URL contains empty host name")]
275 EmptyHostName,
276 #[error("No path/query in URL")]
278 NoPathOrQuery,
279}
280
281#[allow(missing_copy_implementations)]
286#[derive(Error, Debug)]
287#[non_exhaustive]
288pub enum TlsError {
289 #[cfg(feature = "native-tls")]
291 #[error("native-tls error: {0}")]
292 Native(#[from] native_tls_crate::Error),
293 #[cfg(feature = "__rustls-tls")]
295 #[error("rustls error: {0}")]
296 Rustls(#[from] rustls::Error),
297 #[cfg(feature = "__rustls-tls")]
299 #[error("Invalid DNS name")]
300 InvalidDnsName,
301}