tokio_xmpp/
error.rs

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