error.rs

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