error.rs

  1use sasl::client::MechanismError as SaslMechanismError;
  2use std::error::Error as StdError;
  3use std::fmt;
  4use std::io::Error as IoError;
  5use std::str::Utf8Error;
  6
  7use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition;
  8use xmpp_parsers::{jid::Error as JidParseError, Error as ParsersError};
  9
 10use crate::connect::ServerConnectorError;
 11
 12/// Top-level error type
 13#[derive(Debug)]
 14pub enum Error {
 15    /// I/O error
 16    Io(IoError),
 17    /// Error parsing Jabber-Id
 18    JidParse(JidParseError),
 19    /// Protocol-level error
 20    Protocol(ProtocolError),
 21    /// Authentication error
 22    Auth(AuthError),
 23    /// Connection closed
 24    Disconnected,
 25    /// Should never happen
 26    InvalidState,
 27    /// Fmt error
 28    Fmt(fmt::Error),
 29    /// Utf8 error
 30    Utf8(Utf8Error),
 31    /// Error resolving DNS and/or establishing a connection, returned by a ServerConnector impl
 32    Connection(Box<dyn ServerConnectorError>),
 33}
 34
 35impl fmt::Display for Error {
 36    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 37        match self {
 38            Error::Io(e) => write!(fmt, "IO error: {}", e),
 39            Error::Connection(e) => write!(fmt, "connection error: {}", e),
 40            Error::JidParse(e) => write!(fmt, "jid parse error: {}", e),
 41            Error::Protocol(e) => write!(fmt, "protocol error: {}", e),
 42            Error::Auth(e) => write!(fmt, "authentication error: {}", e),
 43            Error::Disconnected => write!(fmt, "disconnected"),
 44            Error::InvalidState => write!(fmt, "invalid state"),
 45            Error::Fmt(e) => write!(fmt, "Fmt error: {}", e),
 46            Error::Utf8(e) => write!(fmt, "Utf8 error: {}", e),
 47        }
 48    }
 49}
 50
 51impl StdError for Error {}
 52
 53impl From<IoError> for Error {
 54    fn from(e: IoError) -> Self {
 55        Error::Io(e)
 56    }
 57}
 58
 59impl<T: ServerConnectorError + 'static> From<T> for Error {
 60    fn from(e: T) -> Self {
 61        Error::Connection(Box::new(e))
 62    }
 63}
 64
 65impl From<JidParseError> for Error {
 66    fn from(e: JidParseError) -> Self {
 67        Error::JidParse(e)
 68    }
 69}
 70
 71impl From<ProtocolError> for Error {
 72    fn from(e: ProtocolError) -> Self {
 73        Error::Protocol(e)
 74    }
 75}
 76
 77impl From<AuthError> for Error {
 78    fn from(e: AuthError) -> Self {
 79        Error::Auth(e)
 80    }
 81}
 82
 83impl From<fmt::Error> for Error {
 84    fn from(e: fmt::Error) -> Self {
 85        Error::Fmt(e)
 86    }
 87}
 88
 89impl From<Utf8Error> for Error {
 90    fn from(e: Utf8Error) -> Self {
 91        Error::Utf8(e)
 92    }
 93}
 94
 95/// XMPP protocol-level error
 96#[derive(Debug)]
 97pub enum ProtocolError {
 98    /// XML parser error
 99    Parser(minidom::Error),
100    /// Error with expected stanza schema
101    Parsers(ParsersError),
102    /// No TLS available
103    NoTls,
104    /// Invalid response to resource binding
105    InvalidBindResponse,
106    /// No xmlns attribute in <stream:stream>
107    NoStreamNamespace,
108    /// No id attribute in <stream:stream>
109    NoStreamId,
110    /// Encountered an unexpected XML token
111    InvalidToken,
112    /// Unexpected <stream:stream> (shouldn't occur)
113    InvalidStreamStart,
114}
115
116impl fmt::Display for ProtocolError {
117    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
118        match self {
119            ProtocolError::Parser(e) => write!(fmt, "XML parser error: {}", e),
120            ProtocolError::Parsers(e) => write!(fmt, "error with expected stanza schema: {}", e),
121            ProtocolError::NoTls => write!(fmt, "no TLS available"),
122            ProtocolError::InvalidBindResponse => {
123                write!(fmt, "invalid response to resource binding")
124            }
125            ProtocolError::NoStreamNamespace => {
126                write!(fmt, "no xmlns attribute in <stream:stream>")
127            }
128            ProtocolError::NoStreamId => write!(fmt, "no id attribute in <stream:stream>"),
129            ProtocolError::InvalidToken => write!(fmt, "encountered an unexpected XML token"),
130            ProtocolError::InvalidStreamStart => write!(fmt, "unexpected <stream:stream>"),
131        }
132    }
133}
134
135impl StdError for ProtocolError {}
136
137impl From<minidom::Error> for ProtocolError {
138    fn from(e: minidom::Error) -> Self {
139        ProtocolError::Parser(e)
140    }
141}
142
143impl From<minidom::Error> for Error {
144    fn from(e: minidom::Error) -> Self {
145        ProtocolError::Parser(e).into()
146    }
147}
148
149impl From<ParsersError> for ProtocolError {
150    fn from(e: ParsersError) -> Self {
151        ProtocolError::Parsers(e)
152    }
153}
154
155/// Authentication error
156#[derive(Debug)]
157pub enum AuthError {
158    /// No matching SASL mechanism available
159    NoMechanism,
160    /// Local SASL implementation error
161    Sasl(SaslMechanismError),
162    /// Failure from server
163    Fail(SaslDefinedCondition),
164    /// Component authentication failure
165    ComponentFail,
166}
167
168impl StdError for AuthError {}
169
170impl fmt::Display for AuthError {
171    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
172        match self {
173            AuthError::NoMechanism => write!(fmt, "no matching SASL mechanism available"),
174            AuthError::Sasl(s) => write!(fmt, "local SASL implementation error: {}", s),
175            AuthError::Fail(c) => write!(fmt, "failure from the server: {:?}", c),
176            AuthError::ComponentFail => write!(fmt, "component authentication failure"),
177        }
178    }
179}