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