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}