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("Send queue is full")]
58 SendQueueFull(Message),
59 #[error("UTF-8 encoding error")]
61 Utf8,
62 #[error("URL error: {0}")]
64 Url(#[from] UrlError),
65 #[error("HTTP error: {}", .0.status())]
67 #[cfg(feature = "handshake")]
68 Http(Response<Option<Vec<u8>>>),
69 #[error("HTTP format error: {0}")]
71 #[cfg(feature = "handshake")]
72 HttpFormat(#[from] http::Error),
73}
74
75impl From<str::Utf8Error> for Error {
76 fn from(_: str::Utf8Error) -> Self {
77 Error::Utf8
78 }
79}
80
81impl From<string::FromUtf8Error> for Error {
82 fn from(_: string::FromUtf8Error) -> Self {
83 Error::Utf8
84 }
85}
86
87#[cfg(feature = "handshake")]
88impl From<http::header::InvalidHeaderValue> for Error {
89 fn from(err: http::header::InvalidHeaderValue) -> Self {
90 Error::HttpFormat(err.into())
91 }
92}
93
94#[cfg(feature = "handshake")]
95impl From<http::header::InvalidHeaderName> for Error {
96 fn from(err: http::header::InvalidHeaderName) -> Self {
97 Error::HttpFormat(err.into())
98 }
99}
100
101#[cfg(feature = "handshake")]
102impl From<http::header::ToStrError> for Error {
103 fn from(_: http::header::ToStrError) -> Self {
104 Error::Utf8
105 }
106}
107
108#[cfg(feature = "handshake")]
109impl From<http::uri::InvalidUri> for Error {
110 fn from(err: http::uri::InvalidUri) -> Self {
111 Error::HttpFormat(err.into())
112 }
113}
114
115#[cfg(feature = "handshake")]
116impl From<http::status::InvalidStatusCode> for Error {
117 fn from(err: http::status::InvalidStatusCode) -> Self {
118 Error::HttpFormat(err.into())
119 }
120}
121
122#[cfg(feature = "handshake")]
123impl From<httparse::Error> for Error {
124 fn from(err: httparse::Error) -> Self {
125 match err {
126 httparse::Error::TooManyHeaders => Error::Capacity(CapacityError::TooManyHeaders),
127 e => Error::Protocol(ProtocolError::HttparseError(e)),
128 }
129 }
130}
131
132#[derive(Error, Debug, PartialEq, Eq, Clone, Copy)]
134pub enum CapacityError {
135 #[error("Too many headers")]
137 TooManyHeaders,
138 #[error("Message too long: {size} > {max_size}")]
141 MessageTooLong {
142 size: usize,
144 max_size: usize,
146 },
147}
148
149#[allow(missing_copy_implementations)]
151#[derive(Error, Debug, PartialEq, Eq, Clone)]
152pub enum ProtocolError {
153 #[error("Unsupported HTTP method used - only GET is allowed")]
155 WrongHttpMethod,
156 #[error("HTTP version must be 1.1 or higher")]
158 WrongHttpVersion,
159 #[error("No \"Connection: upgrade\" header")]
161 MissingConnectionUpgradeHeader,
162 #[error("No \"Upgrade: websocket\" header")]
164 MissingUpgradeWebSocketHeader,
165 #[error("No \"Sec-WebSocket-Version: 13\" header")]
167 MissingSecWebSocketVersionHeader,
168 #[error("No \"Sec-WebSocket-Key\" header")]
170 MissingSecWebSocketKey,
171 #[error("Key mismatch in \"Sec-WebSocket-Accept\" header")]
173 SecWebSocketAcceptKeyMismatch,
174 #[error("Junk after client request")]
176 JunkAfterRequest,
177 #[error("Custom response must not be successful")]
179 CustomResponseSuccessful,
180 #[error("Missing, duplicated or incorrect header {0}")]
182 #[cfg(feature = "handshake")]
183 InvalidHeader(HeaderName),
184 #[error("Handshake not finished")]
186 HandshakeIncomplete,
187 #[error("httparse error: {0}")]
189 #[cfg(feature = "handshake")]
190 HttparseError(#[from] httparse::Error),
191 #[error("Sending after closing is not allowed")]
193 SendAfterClosing,
194 #[error("Remote sent after having closed")]
196 ReceivedAfterClosing,
197 #[error("Reserved bits are non-zero")]
199 NonZeroReservedBits,
200 #[error("Received an unmasked frame from client")]
202 UnmaskedFrameFromClient,
203 #[error("Received a masked frame from server")]
205 MaskedFrameFromServer,
206 #[error("Fragmented control frame")]
208 FragmentedControlFrame,
209 #[error("Control frame too big (payload must be 125 bytes or less)")]
211 ControlFrameTooBig,
212 #[error("Unknown control frame type: {0}")]
214 UnknownControlFrameType(u8),
215 #[error("Unknown data frame type: {0}")]
217 UnknownDataFrameType(u8),
218 #[error("Continue frame but nothing to continue")]
220 UnexpectedContinueFrame,
221 #[error("While waiting for more fragments received: {0}")]
223 ExpectedFragment(Data),
224 #[error("Connection reset without closing handshake")]
226 ResetWithoutClosingHandshake,
227 #[error("Encountered invalid opcode: {0}")]
229 InvalidOpcode(u8),
230 #[error("Invalid close sequence")]
232 InvalidCloseSequence,
233}
234
235#[derive(Error, Debug, PartialEq, Eq)]
237pub enum UrlError {
238 #[error("TLS support not compiled in")]
240 TlsFeatureNotEnabled,
241 #[error("No host name in the URL")]
243 NoHostName,
244 #[error("Unable to connect to {0}")]
246 UnableToConnect(String),
247 #[error("URL scheme not supported")]
249 UnsupportedUrlScheme,
250 #[error("URL contains empty host name")]
252 EmptyHostName,
253 #[error("No path/query in URL")]
255 NoPathOrQuery,
256}
257
258#[allow(missing_copy_implementations)]
263#[derive(Error, Debug)]
264#[non_exhaustive]
265pub enum TlsError {
266 #[cfg(feature = "native-tls")]
268 #[error("native-tls error: {0}")]
269 Native(#[from] native_tls_crate::Error),
270 #[cfg(feature = "__rustls-tls")]
272 #[error("rustls error: {0}")]
273 Rustls(#[from] rustls::Error),
274 #[cfg(feature = "__rustls-tls")]
276 #[error("webpki error: {0}")]
277 Webpki(#[from] webpki::Error),
278 #[cfg(feature = "__rustls-tls")]
280 #[error("Invalid DNS name")]
281 InvalidDnsName,
282}