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}