|
|
@ -2,7 +2,7 @@ |
|
|
|
|
|
|
|
|
|
|
|
use std::{borrow::Cow, error::Error as ErrorTrait, fmt, io, result, str, string}; |
|
|
|
use std::{borrow::Cow, error::Error as ErrorTrait, fmt, io, result, str, string}; |
|
|
|
|
|
|
|
|
|
|
|
use crate::protocol::Message; |
|
|
|
use crate::protocol::{frame::coding::Data, Message}; |
|
|
|
use http::Response; |
|
|
|
use http::Response; |
|
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "tls")] |
|
|
|
#[cfg(feature = "tls")] |
|
|
@ -41,14 +41,14 @@ pub enum Error { |
|
|
|
/// underlying connection and you should probably consider them fatal.
|
|
|
|
/// underlying connection and you should probably consider them fatal.
|
|
|
|
Io(io::Error), |
|
|
|
Io(io::Error), |
|
|
|
#[cfg(feature = "tls")] |
|
|
|
#[cfg(feature = "tls")] |
|
|
|
/// TLS error
|
|
|
|
/// TLS error.
|
|
|
|
Tls(tls::Error), |
|
|
|
Tls(tls::Error), |
|
|
|
/// - When reading: buffer capacity exhausted.
|
|
|
|
/// - When reading: buffer capacity exhausted.
|
|
|
|
/// - When writing: your message is bigger than the configured max message size
|
|
|
|
/// - When writing: your message is bigger than the configured max message size
|
|
|
|
/// (64MB by default).
|
|
|
|
/// (64MB by default).
|
|
|
|
Capacity(Cow<'static, str>), |
|
|
|
Capacity(Cow<'static, str>), |
|
|
|
/// Protocol violation.
|
|
|
|
/// Protocol violation.
|
|
|
|
Protocol(Cow<'static, str>), |
|
|
|
Protocol(ProtocolErrorType), |
|
|
|
/// Message send queue full.
|
|
|
|
/// Message send queue full.
|
|
|
|
SendQueueFull(Message), |
|
|
|
SendQueueFull(Message), |
|
|
|
/// UTF coding error
|
|
|
|
/// UTF coding error
|
|
|
@ -147,13 +147,13 @@ impl From<httparse::Error> for Error { |
|
|
|
fn from(err: httparse::Error) -> Self { |
|
|
|
fn from(err: httparse::Error) -> Self { |
|
|
|
match err { |
|
|
|
match err { |
|
|
|
httparse::Error::TooManyHeaders => Error::Capacity("Too many headers".into()), |
|
|
|
httparse::Error::TooManyHeaders => Error::Capacity("Too many headers".into()), |
|
|
|
e => Error::Protocol(e.to_string().into()), |
|
|
|
e => Error::Protocol(ProtocolErrorType::HttparseError(e)), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/// Indicates the specific type/cause of URL error.
|
|
|
|
/// Indicates the specific type/cause of URL error.
|
|
|
|
#[derive(Debug)] |
|
|
|
#[derive(Debug, PartialEq, Eq)] |
|
|
|
pub enum UrlErrorType { |
|
|
|
pub enum UrlErrorType { |
|
|
|
/// TLS is used despite not being compiled with the TLS feature enabled.
|
|
|
|
/// TLS is used despite not being compiled with the TLS feature enabled.
|
|
|
|
TlsFeatureNotEnabled, |
|
|
|
TlsFeatureNotEnabled, |
|
|
@ -166,7 +166,7 @@ pub enum UrlErrorType { |
|
|
|
/// The URL host name, though included, is empty.
|
|
|
|
/// The URL host name, though included, is empty.
|
|
|
|
EmptyHostName, |
|
|
|
EmptyHostName, |
|
|
|
/// The URL does not include a path/query.
|
|
|
|
/// The URL does not include a path/query.
|
|
|
|
NoPathOrQuery |
|
|
|
NoPathOrQuery, |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for UrlErrorType { |
|
|
|
impl fmt::Display for UrlErrorType { |
|
|
@ -177,7 +177,128 @@ impl fmt::Display for UrlErrorType { |
|
|
|
UrlErrorType::UnableToConnect(uri) => write!(f, "Unable to connect to {}", uri), |
|
|
|
UrlErrorType::UnableToConnect(uri) => write!(f, "Unable to connect to {}", uri), |
|
|
|
UrlErrorType::UnsupportedUrlScheme => write!(f, "URL scheme not supported"), |
|
|
|
UrlErrorType::UnsupportedUrlScheme => write!(f, "URL scheme not supported"), |
|
|
|
UrlErrorType::EmptyHostName => write!(f, "URL contains empty host name"), |
|
|
|
UrlErrorType::EmptyHostName => write!(f, "URL contains empty host name"), |
|
|
|
UrlErrorType::NoPathOrQuery => write!(f, "No path/query in URL") |
|
|
|
UrlErrorType::NoPathOrQuery => write!(f, "No path/query in URL"), |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/// Indicates the specific type/cause of a protocol error.
|
|
|
|
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Copy)] |
|
|
|
|
|
|
|
pub enum ProtocolErrorType { |
|
|
|
|
|
|
|
/// Use of the wrong HTTP method (the WebSocket protocol requires the GET method be used).
|
|
|
|
|
|
|
|
WrongHttpMethod, |
|
|
|
|
|
|
|
/// Wrong HTTP version used (the WebSocket protocol requires version 1.1 or higher).
|
|
|
|
|
|
|
|
WrongHttpVersion, |
|
|
|
|
|
|
|
/// Missing `Connection: upgrade` HTTP header.
|
|
|
|
|
|
|
|
MissingConnectionUpgradeHeader, |
|
|
|
|
|
|
|
/// Missing `Upgrade: websocket` HTTP header.
|
|
|
|
|
|
|
|
MissingUpgradeWebSocketHeader, |
|
|
|
|
|
|
|
/// Missing `Sec-WebSocket-Version: 13` HTTP header.
|
|
|
|
|
|
|
|
MissingSecWebSocketVersionHeader, |
|
|
|
|
|
|
|
/// Missing `Sec-WebSocket-Key` HTTP header.
|
|
|
|
|
|
|
|
MissingSecWebSocketKey, |
|
|
|
|
|
|
|
/// The `Sec-WebSocket-Accept` header is either not present or does not specify the correct key value.
|
|
|
|
|
|
|
|
SecWebSocketAcceptKeyMismatch, |
|
|
|
|
|
|
|
/// Garbage data encountered after client request.
|
|
|
|
|
|
|
|
JunkAfterRequest, |
|
|
|
|
|
|
|
/// Custom responses must be unsuccessful.
|
|
|
|
|
|
|
|
CustomResponseSuccessful, |
|
|
|
|
|
|
|
/// No more data while still performing handshake.
|
|
|
|
|
|
|
|
HandshakeIncomplete, |
|
|
|
|
|
|
|
/// Wrapper around a [`httparse::Error`] value.
|
|
|
|
|
|
|
|
HttparseError(httparse::Error), |
|
|
|
|
|
|
|
/// Not allowed to send after having sent a closing frame.
|
|
|
|
|
|
|
|
SendAfterClosing, |
|
|
|
|
|
|
|
/// Remote sent data after sending a closing frame.
|
|
|
|
|
|
|
|
ReceivedAfterClosing, |
|
|
|
|
|
|
|
/// Reserved bits in frame header are non-zero.
|
|
|
|
|
|
|
|
NonZeroReservedBits, |
|
|
|
|
|
|
|
/// The server must close the connection when an unmasked frame is received.
|
|
|
|
|
|
|
|
UnmaskedFrameFromClient, |
|
|
|
|
|
|
|
/// The client must close the connection when a masked frame is received.
|
|
|
|
|
|
|
|
MaskedFrameFromServer, |
|
|
|
|
|
|
|
/// Control frames must not be fragmented.
|
|
|
|
|
|
|
|
FragmentedControlFrame, |
|
|
|
|
|
|
|
/// Control frames must have a payload of 125 bytes or less.
|
|
|
|
|
|
|
|
ControlFrameTooBig, |
|
|
|
|
|
|
|
/// Type of control frame not recognised.
|
|
|
|
|
|
|
|
UnknownControlFrameType(u8), |
|
|
|
|
|
|
|
/// Type of data frame not recognised.
|
|
|
|
|
|
|
|
UnknownDataFrameType(u8), |
|
|
|
|
|
|
|
/// Received a continue frame despite there being nothing to continue.
|
|
|
|
|
|
|
|
UnexpectedContinueFrame, |
|
|
|
|
|
|
|
/// Received data while waiting for more fragments.
|
|
|
|
|
|
|
|
ExpectedFragment(Data), |
|
|
|
|
|
|
|
/// Connection closed without performing the closing handshake.
|
|
|
|
|
|
|
|
ResetWithoutClosingHandshake, |
|
|
|
|
|
|
|
/// Encountered an invalid opcode.
|
|
|
|
|
|
|
|
InvalidOpcode(u8), |
|
|
|
|
|
|
|
/// The payload for the closing frame is invalid.
|
|
|
|
|
|
|
|
InvalidCloseSequence, |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
impl fmt::Display for ProtocolErrorType { |
|
|
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
|
|
|
|
|
|
match self { |
|
|
|
|
|
|
|
ProtocolErrorType::WrongHttpMethod => { |
|
|
|
|
|
|
|
write!(f, "Unsupported HTTP method used, only GET is allowed") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::WrongHttpVersion => write!(f, "HTTP version must be 1.1 or higher"), |
|
|
|
|
|
|
|
ProtocolErrorType::MissingConnectionUpgradeHeader => { |
|
|
|
|
|
|
|
write!(f, "No \"Connection: upgrade\" header") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::MissingUpgradeWebSocketHeader => { |
|
|
|
|
|
|
|
write!(f, "No \"Upgrade: websocket\" header") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::MissingSecWebSocketVersionHeader => { |
|
|
|
|
|
|
|
write!(f, "No \"Sec-WebSocket-Version: 13\" header") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::MissingSecWebSocketKey => { |
|
|
|
|
|
|
|
write!(f, "No \"Sec-WebSocket-Key\" header") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::SecWebSocketAcceptKeyMismatch => { |
|
|
|
|
|
|
|
write!(f, "Key mismatch in \"Sec-WebSocket-Accept\" header") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::JunkAfterRequest => write!(f, "Junk after client request"), |
|
|
|
|
|
|
|
ProtocolErrorType::CustomResponseSuccessful => { |
|
|
|
|
|
|
|
write!(f, "Custom response must not be successful") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::HandshakeIncomplete => write!(f, "Handshake not finished"), |
|
|
|
|
|
|
|
ProtocolErrorType::HttparseError(e) => write!(f, "httparse error: {}", e), |
|
|
|
|
|
|
|
ProtocolErrorType::SendAfterClosing => { |
|
|
|
|
|
|
|
write!(f, "Sending after closing is not allowed") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::ReceivedAfterClosing => write!(f, "Remote sent after having closed"), |
|
|
|
|
|
|
|
ProtocolErrorType::NonZeroReservedBits => write!(f, "Reserved bits are non-zero"), |
|
|
|
|
|
|
|
ProtocolErrorType::UnmaskedFrameFromClient => { |
|
|
|
|
|
|
|
write!(f, "Received an unmasked frame from client") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::MaskedFrameFromServer => { |
|
|
|
|
|
|
|
write!(f, "Received a masked frame from server") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::FragmentedControlFrame => write!(f, "Fragmented control frame"), |
|
|
|
|
|
|
|
ProtocolErrorType::ControlFrameTooBig => { |
|
|
|
|
|
|
|
write!(f, "Control frame too big (payload must be 125 bytes or less)") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::UnknownControlFrameType(i) => { |
|
|
|
|
|
|
|
write!(f, "Unknown control frame type: {}", i) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::UnknownDataFrameType(i) => { |
|
|
|
|
|
|
|
write!(f, "Unknown data frame type: {}", i) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::UnexpectedContinueFrame => { |
|
|
|
|
|
|
|
write!(f, "Continue frame but nothing to continue") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::ExpectedFragment(c) => { |
|
|
|
|
|
|
|
write!(f, "While waiting for more fragments received: {}", c) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::ResetWithoutClosingHandshake => { |
|
|
|
|
|
|
|
write!(f, "Connection reset without closing handshake") |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::InvalidOpcode(opcode) => { |
|
|
|
|
|
|
|
write!(f, "Encountered invalid opcode: {}", opcode) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
ProtocolErrorType::InvalidCloseSequence => write!(f, "Invalid close sequence"), |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|