error.rs

  1#[cfg(feature = "tls-native")]
  2use native_tls::Error as TlsError;
  3use sasl::client::MechanismError as SaslMechanismError;
  4use std::borrow::Cow;
  5use std::error::Error as StdError;
  6use std::fmt;
  7use std::io::Error as IoError;
  8use std::str::Utf8Error;
  9#[cfg(feature = "tls-rust")]
 10use tokio_rustls::rustls::client::InvalidDnsNameError;
 11#[cfg(feature = "tls-rust")]
 12use tokio_rustls::rustls::Error as TlsError;
 13use trust_dns_proto::error::ProtoError;
 14use trust_dns_resolver::error::ResolveError;
 15
 16use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition;
 17use xmpp_parsers::{Error as ParsersError, JidParseError};
 18
 19/// Top-level error type
 20#[derive(Debug)]
 21pub enum Error {
 22    /// I/O error
 23    Io(IoError),
 24    /// Error resolving DNS and establishing a connection
 25    Connection(ConnecterError),
 26    /// DNS label conversion error, no details available from module
 27    /// `idna`
 28    Idna,
 29    /// Error parsing Jabber-Id
 30    JidParse(JidParseError),
 31    /// Protocol-level error
 32    Protocol(ProtocolError),
 33    /// Authentication error
 34    Auth(AuthError),
 35    /// TLS error
 36    Tls(TlsError),
 37    #[cfg(feature = "tls-rust")]
 38    /// DNS name parsing error
 39    DnsNameError(InvalidDnsNameError),
 40    /// Connection closed
 41    Disconnected,
 42    /// Shoud never happen
 43    InvalidState,
 44    /// Fmt error
 45    Fmt(fmt::Error),
 46    /// Utf8 error
 47    Utf8(Utf8Error),
 48}
 49
 50impl fmt::Display for Error {
 51    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 52        match self {
 53            Error::Io(e) => write!(fmt, "IO error: {}", e),
 54            Error::Connection(e) => write!(fmt, "connection error: {}", e),
 55            Error::Idna => write!(fmt, "IDNA error"),
 56            Error::JidParse(e) => write!(fmt, "jid parse error: {}", e),
 57            Error::Protocol(e) => write!(fmt, "protocol error: {}", e),
 58            Error::Auth(e) => write!(fmt, "authentication error: {}", e),
 59            Error::Tls(e) => write!(fmt, "TLS error: {}", e),
 60            #[cfg(feature = "tls-rust")]
 61            Error::DnsNameError(e) => write!(fmt, "DNS name error: {}", e),
 62            Error::Disconnected => write!(fmt, "disconnected"),
 63            Error::InvalidState => write!(fmt, "invalid state"),
 64            Error::Fmt(e) => write!(fmt, "Fmt error: {}", e),
 65            Error::Utf8(e) => write!(fmt, "Utf8 error: {}", e),
 66        }
 67    }
 68}
 69
 70impl StdError for Error {}
 71
 72impl From<IoError> for Error {
 73    fn from(e: IoError) -> Self {
 74        Error::Io(e)
 75    }
 76}
 77
 78impl From<ConnecterError> for Error {
 79    fn from(e: ConnecterError) -> Self {
 80        Error::Connection(e)
 81    }
 82}
 83
 84impl From<JidParseError> for Error {
 85    fn from(e: JidParseError) -> Self {
 86        Error::JidParse(e)
 87    }
 88}
 89
 90impl From<ProtocolError> for Error {
 91    fn from(e: ProtocolError) -> Self {
 92        Error::Protocol(e)
 93    }
 94}
 95
 96impl From<AuthError> for Error {
 97    fn from(e: AuthError) -> Self {
 98        Error::Auth(e)
 99    }
100}
101
102impl From<TlsError> for Error {
103    fn from(e: TlsError) -> Self {
104        Error::Tls(e)
105    }
106}
107
108impl From<fmt::Error> for Error {
109    fn from(e: fmt::Error) -> Self {
110        Error::Fmt(e)
111    }
112}
113
114impl From<Utf8Error> for Error {
115    fn from(e: Utf8Error) -> Self {
116        Error::Utf8(e)
117    }
118}
119
120#[cfg(feature = "tls-rust")]
121impl From<InvalidDnsNameError> for Error {
122    fn from(e: InvalidDnsNameError) -> Self {
123        Error::DnsNameError(e)
124    }
125}
126
127/// XML parse error wrapper type
128#[derive(Debug)]
129pub struct ParseError(pub Cow<'static, str>);
130
131impl StdError for ParseError {
132    fn description(&self) -> &str {
133        self.0.as_ref()
134    }
135    fn cause(&self) -> Option<&dyn StdError> {
136        None
137    }
138}
139
140impl fmt::Display for ParseError {
141    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
142        write!(f, "{}", self.0)
143    }
144}
145
146/// XMPP protocol-level error
147#[derive(Debug)]
148pub enum ProtocolError {
149    /// XML parser error
150    Parser(minidom::Error),
151    /// Error with expected stanza schema
152    Parsers(ParsersError),
153    /// No TLS available
154    NoTls,
155    /// Invalid response to resource binding
156    InvalidBindResponse,
157    /// No xmlns attribute in <stream:stream>
158    NoStreamNamespace,
159    /// No id attribute in <stream:stream>
160    NoStreamId,
161    /// Encountered an unexpected XML token
162    InvalidToken,
163    /// Unexpected <stream:stream> (shouldn't occur)
164    InvalidStreamStart,
165}
166
167impl fmt::Display for ProtocolError {
168    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
169        match self {
170            ProtocolError::Parser(e) => write!(fmt, "XML parser error: {}", e),
171            ProtocolError::Parsers(e) => write!(fmt, "error with expected stanza schema: {}", e),
172            ProtocolError::NoTls => write!(fmt, "no TLS available"),
173            ProtocolError::InvalidBindResponse => {
174                write!(fmt, "invalid response to resource binding")
175            }
176            ProtocolError::NoStreamNamespace => {
177                write!(fmt, "no xmlns attribute in <stream:stream>")
178            }
179            ProtocolError::NoStreamId => write!(fmt, "no id attribute in <stream:stream>"),
180            ProtocolError::InvalidToken => write!(fmt, "encountered an unexpected XML token"),
181            ProtocolError::InvalidStreamStart => write!(fmt, "unexpected <stream:stream>"),
182        }
183    }
184}
185
186impl StdError for ProtocolError {}
187
188impl From<minidom::Error> for ProtocolError {
189    fn from(e: minidom::Error) -> Self {
190        ProtocolError::Parser(e)
191    }
192}
193
194impl From<minidom::Error> for Error {
195    fn from(e: minidom::Error) -> Self {
196        ProtocolError::Parser(e).into()
197    }
198}
199
200impl From<ParsersError> for ProtocolError {
201    fn from(e: ParsersError) -> Self {
202        ProtocolError::Parsers(e)
203    }
204}
205
206/// Authentication error
207#[derive(Debug)]
208pub enum AuthError {
209    /// No matching SASL mechanism available
210    NoMechanism,
211    /// Local SASL implementation error
212    Sasl(SaslMechanismError),
213    /// Failure from server
214    Fail(SaslDefinedCondition),
215    /// Component authentication failure
216    ComponentFail,
217}
218
219impl StdError for AuthError {}
220
221impl fmt::Display for AuthError {
222    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
223        match self {
224            AuthError::NoMechanism => write!(fmt, "no matching SASL mechanism available"),
225            AuthError::Sasl(s) => write!(fmt, "local SASL implementation error: {}", s),
226            AuthError::Fail(c) => write!(fmt, "failure from the server: {:?}", c),
227            AuthError::ComponentFail => write!(fmt, "component authentication failure"),
228        }
229    }
230}
231
232/// Error establishing connection
233#[derive(Debug)]
234pub enum ConnecterError {
235    /// All attempts failed, no error available
236    AllFailed,
237    /// DNS protocol error
238    Dns(ProtoError),
239    /// DNS resolution error
240    Resolve(ResolveError),
241}
242
243impl StdError for ConnecterError {}
244
245impl std::fmt::Display for ConnecterError {
246    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
247        write!(fmt, "{:?}", self)
248    }
249}