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