summaryrefslogtreecommitdiffstats
path: root/third_party/rust/ws/src/result.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--third_party/rust/ws/src/result.rs204
1 files changed, 204 insertions, 0 deletions
diff --git a/third_party/rust/ws/src/result.rs b/third_party/rust/ws/src/result.rs
new file mode 100644
index 0000000000..eb3c151813
--- /dev/null
+++ b/third_party/rust/ws/src/result.rs
@@ -0,0 +1,204 @@
+use std::borrow::Cow;
+use std::convert::{From, Into};
+use std::error::Error as StdError;
+use std::fmt;
+use std::io;
+use std::result::Result as StdResult;
+use std::str::Utf8Error;
+
+use httparse;
+use mio;
+#[cfg(feature = "ssl")]
+use openssl::ssl::{Error as SslError, HandshakeError as SslHandshakeError};
+#[cfg(feature = "nativetls")]
+use native_tls::{Error as SslError, HandshakeError as SslHandshakeError};
+#[cfg(any(feature = "ssl", feature = "nativetls"))]
+type HandshakeError = SslHandshakeError<mio::tcp::TcpStream>;
+
+use communication::Command;
+
+pub type Result<T> = StdResult<T, Error>;
+
+/// The type of an error, which may indicate other kinds of errors as the underlying cause.
+#[derive(Debug)]
+pub enum Kind {
+ /// Indicates an internal application error.
+ /// If panic_on_internal is true, which is the default, then the application will panic.
+ /// Otherwise the WebSocket will automatically attempt to send an Error (1011) close code.
+ Internal,
+ /// Indicates a state where some size limit has been exceeded, such as an inability to accept
+ /// any more new connections.
+ /// If a Connection is active, the WebSocket will automatically attempt to send
+ /// a Size (1009) close code.
+ Capacity,
+ /// Indicates a violation of the WebSocket protocol.
+ /// The WebSocket will automatically attempt to send a Protocol (1002) close code, or if
+ /// this error occurs during a handshake, an HTTP 400 response will be generated.
+ Protocol,
+ /// Indicates that the WebSocket received data that should be utf8 encoded but was not.
+ /// The WebSocket will automatically attempt to send a Invalid Frame Payload Data (1007) close
+ /// code.
+ Encoding(Utf8Error),
+ /// Indicates an underlying IO Error.
+ /// This kind of error will result in a WebSocket Connection disconnecting.
+ Io(io::Error),
+ /// Indicates a failure to parse an HTTP message.
+ /// This kind of error should only occur during a WebSocket Handshake, and a HTTP 500 response
+ /// will be generated.
+ Http(httparse::Error),
+ /// Indicates a failure to send a signal on the internal EventLoop channel. This means that
+ /// the WebSocket is overloaded. In order to avoid this error, it is important to set
+ /// `Settings::max_connections` and `Settings:queue_size` high enough to handle the load.
+ /// If encountered, retuning from a handler method and waiting for the EventLoop to consume
+ /// the queue may relieve the situation.
+ Queue(mio::channel::SendError<Command>),
+ /// Indicates a failure to perform SSL encryption.
+ #[cfg(any(feature = "ssl", feature = "nativetls"))]
+ Ssl(SslError),
+ /// Indicates a failure to perform SSL encryption.
+ #[cfg(any(feature = "ssl", feature = "nativetls"))]
+ SslHandshake(HandshakeError),
+ /// A custom error kind for use by applications. This error kind involves extra overhead
+ /// because it will allocate the memory on the heap. The WebSocket ignores such errors by
+ /// default, simply passing them to the Connection Handler.
+ Custom(Box<dyn StdError + Send + Sync>),
+}
+
+/// A struct indicating the kind of error that has occurred and any precise details of that error.
+pub struct Error {
+ pub kind: Kind,
+ pub details: Cow<'static, str>,
+}
+
+impl Error {
+ pub fn new<I>(kind: Kind, details: I) -> Error
+ where
+ I: Into<Cow<'static, str>>,
+ {
+ Error {
+ kind,
+ details: details.into(),
+ }
+ }
+
+ pub fn into_box(self) -> Box<dyn StdError> {
+ match self.kind {
+ Kind::Custom(err) => err,
+ _ => Box::new(self),
+ }
+ }
+}
+
+impl fmt::Debug for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if self.details.len() > 0 {
+ write!(f, "WS Error <{:?}>: {}", self.kind, self.details)
+ } else {
+ write!(f, "WS Error <{:?}>", self.kind)
+ }
+ }
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ if self.details.len() > 0 {
+ write!(f, "{}: {}", self.description(), self.details)
+ } else {
+ write!(f, "{}", self.description())
+ }
+ }
+}
+
+impl StdError for Error {
+ fn description(&self) -> &str {
+ match self.kind {
+ Kind::Internal => "Internal Application Error",
+ Kind::Capacity => "WebSocket at Capacity",
+ Kind::Protocol => "WebSocket Protocol Error",
+ Kind::Encoding(ref err) => err.description(),
+ Kind::Io(ref err) => err.description(),
+ Kind::Http(_) => "Unable to parse HTTP",
+ #[cfg(any(feature = "ssl", feature = "nativetls"))]
+ Kind::Ssl(ref err) => err.description(),
+ #[cfg(any(feature = "ssl", feature = "nativetls"))]
+ Kind::SslHandshake(ref err) => err.description(),
+ Kind::Queue(_) => "Unable to send signal on event loop",
+ Kind::Custom(ref err) => err.description(),
+ }
+ }
+
+ fn cause(&self) -> Option<&dyn StdError> {
+ match self.kind {
+ Kind::Encoding(ref err) => Some(err),
+ Kind::Io(ref err) => Some(err),
+ #[cfg(any(feature = "ssl", feature = "nativetls"))]
+ Kind::Ssl(ref err) => Some(err),
+ #[cfg(any(feature = "ssl", feature = "nativetls"))]
+ Kind::SslHandshake(ref err) => err.cause(),
+ Kind::Custom(ref err) => Some(err.as_ref()),
+ _ => None,
+ }
+ }
+}
+
+impl From<io::Error> for Error {
+ fn from(err: io::Error) -> Error {
+ Error::new(Kind::Io(err), "")
+ }
+}
+
+impl From<httparse::Error> for Error {
+ fn from(err: httparse::Error) -> Error {
+ let details = match err {
+ httparse::Error::HeaderName => "Invalid byte in header name.",
+ httparse::Error::HeaderValue => "Invalid byte in header value.",
+ httparse::Error::NewLine => "Invalid byte in new line.",
+ httparse::Error::Status => "Invalid byte in Response status.",
+ httparse::Error::Token => "Invalid byte where token is required.",
+ httparse::Error::TooManyHeaders => {
+ "Parsed more headers than provided buffer can contain."
+ }
+ httparse::Error::Version => "Invalid byte in HTTP version.",
+ };
+
+ Error::new(Kind::Http(err), details)
+ }
+}
+
+impl From<mio::channel::SendError<Command>> for Error {
+ fn from(err: mio::channel::SendError<Command>) -> Error {
+ match err {
+ mio::channel::SendError::Io(err) => Error::from(err),
+ _ => Error::new(Kind::Queue(err), ""),
+ }
+ }
+}
+
+impl From<Utf8Error> for Error {
+ fn from(err: Utf8Error) -> Error {
+ Error::new(Kind::Encoding(err), "")
+ }
+}
+
+#[cfg(any(feature = "ssl", feature = "nativetls"))]
+impl From<SslError> for Error {
+ fn from(err: SslError) -> Error {
+ Error::new(Kind::Ssl(err), "")
+ }
+}
+
+#[cfg(any(feature = "ssl", feature = "nativetls"))]
+impl From<HandshakeError> for Error {
+ fn from(err: HandshakeError) -> Error {
+ Error::new(Kind::SslHandshake(err), "")
+ }
+}
+
+impl<B> From<Box<B>> for Error
+where
+ B: StdError + Send + Sync + 'static,
+{
+ fn from(err: Box<B>) -> Error {
+ Error::new(Kind::Custom(err), "")
+ }
+}