1 //! Error handling. 2 3 use std::{io, result, str, string}; 4 5 use crate::protocol::{frame::coding::Data, Message}; 6 #[cfg(feature = "handshake")] 7 use http::{header::HeaderName, Response}; 8 use thiserror::Error; 9 10 /// Result type of all Tungstenite library calls. 11 pub type Result<T, E = Error> = result::Result<T, E>; 12 13 /// Possible WebSocket errors. 14 #[derive(Error, Debug)] 15 pub enum Error { 16 /// WebSocket connection closed normally. This informs you of the close. 17 /// It's not an error as such and nothing wrong happened. 18 /// 19 /// This is returned as soon as the close handshake is finished (we have both sent and 20 /// received a close frame) on the server end and as soon as the server has closed the 21 /// underlying connection if this endpoint is a client. 22 /// 23 /// Thus when you receive this, it is safe to drop the underlying connection. 24 /// 25 /// Receiving this error means that the WebSocket object is not usable anymore and the 26 /// only meaningful action with it is dropping it. 27 #[error("Connection closed normally")] 28 ConnectionClosed, 29 /// Trying to work with already closed connection. 30 /// 31 /// Trying to read or write after receiving `ConnectionClosed` causes this. 32 /// 33 /// As opposed to `ConnectionClosed`, this indicates your code tries to operate on the 34 /// connection when it really shouldn't anymore, so this really indicates a programmer 35 /// error on your part. 36 #[error("Trying to work with closed connection")] 37 AlreadyClosed, 38 /// Input-output error. Apart from WouldBlock, these are generally errors with the 39 /// underlying connection and you should probably consider them fatal. 40 #[error("IO error: {0}")] 41 Io(#[from] io::Error), 42 /// TLS error. 43 /// 44 /// Note that this error variant is enabled unconditionally even if no TLS feature is enabled, 45 /// to provide a feature-agnostic API surface. 46 #[error("TLS error: {0}")] 47 Tls(#[from] TlsError), 48 /// - When reading: buffer capacity exhausted. 49 /// - When writing: your message is bigger than the configured max message size 50 /// (64MB by default). 51 #[error("Space limit exceeded: {0}")] 52 Capacity(#[from] CapacityError), 53 /// Protocol violation. 54 #[error("WebSocket protocol error: {0}")] 55 Protocol(#[from] ProtocolError), 56 /// Message write buffer is full. 57 #[error("Write buffer is full")] 58 WriteBufferFull(Message), 59 /// UTF coding error. 60 #[error("UTF-8 encoding error")] 61 Utf8, 62 /// Attack attempt detected. 63 #[error("Attack attempt detected")] 64 AttackAttempt, 65 /// Invalid URL. 66 #[error("URL error: {0}")] 67 Url(#[from] UrlError), 68 /// HTTP error. 69 #[error("HTTP error: {}", .0.status())] 70 #[cfg(feature = "handshake")] 71 Http(Response<Option<Vec<u8>>>), 72 /// HTTP format error. 73 #[error("HTTP format error: {0}")] 74 #[cfg(feature = "handshake")] 75 HttpFormat(#[from] http::Error), 76 } 77 78 impl From<str::Utf8Error> for Error { from(_: str::Utf8Error) -> Self79 fn from(_: str::Utf8Error) -> Self { 80 Error::Utf8 81 } 82 } 83 84 impl From<string::FromUtf8Error> for Error { from(_: string::FromUtf8Error) -> Self85 fn from(_: string::FromUtf8Error) -> Self { 86 Error::Utf8 87 } 88 } 89 90 #[cfg(feature = "handshake")] 91 impl From<http::header::InvalidHeaderValue> for Error { from(err: http::header::InvalidHeaderValue) -> Self92 fn from(err: http::header::InvalidHeaderValue) -> Self { 93 Error::HttpFormat(err.into()) 94 } 95 } 96 97 #[cfg(feature = "handshake")] 98 impl From<http::header::InvalidHeaderName> for Error { from(err: http::header::InvalidHeaderName) -> Self99 fn from(err: http::header::InvalidHeaderName) -> Self { 100 Error::HttpFormat(err.into()) 101 } 102 } 103 104 #[cfg(feature = "handshake")] 105 impl From<http::header::ToStrError> for Error { from(_: http::header::ToStrError) -> Self106 fn from(_: http::header::ToStrError) -> Self { 107 Error::Utf8 108 } 109 } 110 111 #[cfg(feature = "handshake")] 112 impl From<http::uri::InvalidUri> for Error { from(err: http::uri::InvalidUri) -> Self113 fn from(err: http::uri::InvalidUri) -> Self { 114 Error::HttpFormat(err.into()) 115 } 116 } 117 118 #[cfg(feature = "handshake")] 119 impl From<http::status::InvalidStatusCode> for Error { from(err: http::status::InvalidStatusCode) -> Self120 fn from(err: http::status::InvalidStatusCode) -> Self { 121 Error::HttpFormat(err.into()) 122 } 123 } 124 125 #[cfg(feature = "handshake")] 126 impl From<httparse::Error> for Error { from(err: httparse::Error) -> Self127 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 /// Indicates the specific type/cause of a capacity error. 136 #[derive(Error, Debug, PartialEq, Eq, Clone, Copy)] 137 pub enum CapacityError { 138 /// Too many headers provided (see [`httparse::Error::TooManyHeaders`]). 139 #[error("Too many headers")] 140 TooManyHeaders, 141 /// Received header is too long. 142 /// Message is bigger than the maximum allowed size. 143 #[error("Message too long: {size} > {max_size}")] 144 MessageTooLong { 145 /// The size of the message. 146 size: usize, 147 /// The maximum allowed message size. 148 max_size: usize, 149 }, 150 } 151 152 /// Indicates the specific type/cause of a subprotocol header error. 153 #[derive(Error, Clone, PartialEq, Eq, Debug, Copy)] 154 pub enum SubProtocolError { 155 /// The server sent a subprotocol to a client handshake request but none was requested 156 #[error("Server sent a subprotocol but none was requested")] 157 ServerSentSubProtocolNoneRequested, 158 159 /// The server sent an invalid subprotocol to a client handhshake request 160 #[error("Server sent an invalid subprotocol")] 161 InvalidSubProtocol, 162 163 /// The server sent no subprotocol to a client handshake request that requested one or more 164 /// subprotocols 165 #[error("Server sent no subprotocol")] 166 NoSubProtocol, 167 } 168 169 /// Indicates the specific type/cause of a protocol error. 170 #[allow(missing_copy_implementations)] 171 #[derive(Error, Debug, PartialEq, Eq, Clone)] 172 pub enum ProtocolError { 173 /// Use of the wrong HTTP method (the WebSocket protocol requires the GET method be used). 174 #[error("Unsupported HTTP method used - only GET is allowed")] 175 WrongHttpMethod, 176 /// Wrong HTTP version used (the WebSocket protocol requires version 1.1 or higher). 177 #[error("HTTP version must be 1.1 or higher")] 178 WrongHttpVersion, 179 /// Missing `Connection: upgrade` HTTP header. 180 #[error("No \"Connection: upgrade\" header")] 181 MissingConnectionUpgradeHeader, 182 /// Missing `Upgrade: websocket` HTTP header. 183 #[error("No \"Upgrade: websocket\" header")] 184 MissingUpgradeWebSocketHeader, 185 /// Missing `Sec-WebSocket-Version: 13` HTTP header. 186 #[error("No \"Sec-WebSocket-Version: 13\" header")] 187 MissingSecWebSocketVersionHeader, 188 /// Missing `Sec-WebSocket-Key` HTTP header. 189 #[error("No \"Sec-WebSocket-Key\" header")] 190 MissingSecWebSocketKey, 191 /// The `Sec-WebSocket-Accept` header is either not present or does not specify the correct key value. 192 #[error("Key mismatch in \"Sec-WebSocket-Accept\" header")] 193 SecWebSocketAcceptKeyMismatch, 194 /// The `Sec-WebSocket-Protocol` header was invalid 195 #[error("SubProtocol error: {0}")] 196 SecWebSocketSubProtocolError(SubProtocolError), 197 /// Garbage data encountered after client request. 198 #[error("Junk after client request")] 199 JunkAfterRequest, 200 /// Custom responses must be unsuccessful. 201 #[error("Custom response must not be successful")] 202 CustomResponseSuccessful, 203 /// Invalid header is passed. Or the header is missing in the request. Or not present at all. Check the request that you pass. 204 #[error("Missing, duplicated or incorrect header {0}")] 205 #[cfg(feature = "handshake")] 206 InvalidHeader(HeaderName), 207 /// No more data while still performing handshake. 208 #[error("Handshake not finished")] 209 HandshakeIncomplete, 210 /// Wrapper around a [`httparse::Error`] value. 211 #[error("httparse error: {0}")] 212 #[cfg(feature = "handshake")] 213 HttparseError(#[from] httparse::Error), 214 /// Not allowed to send after having sent a closing frame. 215 #[error("Sending after closing is not allowed")] 216 SendAfterClosing, 217 /// Remote sent data after sending a closing frame. 218 #[error("Remote sent after having closed")] 219 ReceivedAfterClosing, 220 /// Reserved bits in frame header are non-zero. 221 #[error("Reserved bits are non-zero")] 222 NonZeroReservedBits, 223 /// The server must close the connection when an unmasked frame is received. 224 #[error("Received an unmasked frame from client")] 225 UnmaskedFrameFromClient, 226 /// The client must close the connection when a masked frame is received. 227 #[error("Received a masked frame from server")] 228 MaskedFrameFromServer, 229 /// Control frames must not be fragmented. 230 #[error("Fragmented control frame")] 231 FragmentedControlFrame, 232 /// Control frames must have a payload of 125 bytes or less. 233 #[error("Control frame too big (payload must be 125 bytes or less)")] 234 ControlFrameTooBig, 235 /// Type of control frame not recognised. 236 #[error("Unknown control frame type: {0}")] 237 UnknownControlFrameType(u8), 238 /// Type of data frame not recognised. 239 #[error("Unknown data frame type: {0}")] 240 UnknownDataFrameType(u8), 241 /// Received a continue frame despite there being nothing to continue. 242 #[error("Continue frame but nothing to continue")] 243 UnexpectedContinueFrame, 244 /// Received data while waiting for more fragments. 245 #[error("While waiting for more fragments received: {0}")] 246 ExpectedFragment(Data), 247 /// Connection closed without performing the closing handshake. 248 #[error("Connection reset without closing handshake")] 249 ResetWithoutClosingHandshake, 250 /// Encountered an invalid opcode. 251 #[error("Encountered invalid opcode: {0}")] 252 InvalidOpcode(u8), 253 /// The payload for the closing frame is invalid. 254 #[error("Invalid close sequence")] 255 InvalidCloseSequence, 256 } 257 258 /// Indicates the specific type/cause of URL error. 259 #[derive(Error, Debug, PartialEq, Eq)] 260 pub enum UrlError { 261 /// TLS is used despite not being compiled with the TLS feature enabled. 262 #[error("TLS support not compiled in")] 263 TlsFeatureNotEnabled, 264 /// The URL does not include a host name. 265 #[error("No host name in the URL")] 266 NoHostName, 267 /// Failed to connect with this URL. 268 #[error("Unable to connect to {0}")] 269 UnableToConnect(String), 270 /// Unsupported URL scheme used (only `ws://` or `wss://` may be used). 271 #[error("URL scheme not supported")] 272 UnsupportedUrlScheme, 273 /// The URL host name, though included, is empty. 274 #[error("URL contains empty host name")] 275 EmptyHostName, 276 /// The URL does not include a path/query. 277 #[error("No path/query in URL")] 278 NoPathOrQuery, 279 } 280 281 /// TLS errors. 282 /// 283 /// Note that even if you enable only the rustls-based TLS support, the error at runtime could still 284 /// be `Native`, as another crate in the dependency graph may enable native TLS support. 285 #[allow(missing_copy_implementations)] 286 #[derive(Error, Debug)] 287 #[non_exhaustive] 288 pub enum TlsError { 289 /// Native TLS error. 290 #[cfg(feature = "native-tls")] 291 #[error("native-tls error: {0}")] 292 Native(#[from] native_tls_crate::Error), 293 /// Rustls error. 294 #[cfg(feature = "__rustls-tls")] 295 #[error("rustls error: {0}")] 296 Rustls(#[from] rustls::Error), 297 /// DNS name resolution error. 298 #[cfg(feature = "__rustls-tls")] 299 #[error("Invalid DNS name")] 300 InvalidDnsName, 301 } 302