1use sasl::client::MechanismError as SaslMechanismError;
2use std::error::Error as StdError;
3use std::fmt;
4use std::io::Error as IoError;
5use std::str::Utf8Error;
6
7use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition;
8use xmpp_parsers::{jid::Error as JidParseError, Error as ParsersError};
9
10use crate::connect::ServerConnectorError;
11
12/// Top-level error type
13#[derive(Debug)]
14pub enum Error {
15 /// I/O error
16 Io(IoError),
17 /// Error parsing Jabber-Id
18 JidParse(JidParseError),
19 /// Protocol-level error
20 Protocol(ProtocolError),
21 /// Authentication error
22 Auth(AuthError),
23 /// Connection closed
24 Disconnected,
25 /// Should never happen
26 InvalidState,
27 /// Fmt error
28 Fmt(fmt::Error),
29 /// Utf8 error
30 Utf8(Utf8Error),
31 /// Error resolving DNS and/or establishing a connection, returned by a ServerConnector impl
32 Connection(Box<dyn ServerConnectorError>),
33}
34
35impl fmt::Display for Error {
36 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
37 match self {
38 Error::Io(e) => write!(fmt, "IO error: {}", e),
39 Error::Connection(e) => write!(fmt, "connection error: {}", e),
40 Error::JidParse(e) => write!(fmt, "jid parse error: {}", e),
41 Error::Protocol(e) => write!(fmt, "protocol error: {}", e),
42 Error::Auth(e) => write!(fmt, "authentication error: {}", e),
43 Error::Disconnected => write!(fmt, "disconnected"),
44 Error::InvalidState => write!(fmt, "invalid state"),
45 Error::Fmt(e) => write!(fmt, "Fmt error: {}", e),
46 Error::Utf8(e) => write!(fmt, "Utf8 error: {}", e),
47 }
48 }
49}
50
51impl StdError for Error {}
52
53impl From<IoError> for Error {
54 fn from(e: IoError) -> Self {
55 Error::Io(e)
56 }
57}
58
59impl<T: ServerConnectorError + 'static> From<T> for Error {
60 fn from(e: T) -> Self {
61 Error::Connection(Box::new(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<fmt::Error> for Error {
84 fn from(e: fmt::Error) -> Self {
85 Error::Fmt(e)
86 }
87}
88
89impl From<Utf8Error> for Error {
90 fn from(e: Utf8Error) -> Self {
91 Error::Utf8(e)
92 }
93}
94
95/// XMPP protocol-level error
96#[derive(Debug)]
97pub enum ProtocolError {
98 /// XML parser error
99 Parser(minidom::Error),
100 /// Error with expected stanza schema
101 Parsers(ParsersError),
102 /// No TLS available
103 NoTls,
104 /// Invalid response to resource binding
105 InvalidBindResponse,
106 /// No xmlns attribute in <stream:stream>
107 NoStreamNamespace,
108 /// No id attribute in <stream:stream>
109 NoStreamId,
110 /// Encountered an unexpected XML token
111 InvalidToken,
112 /// Unexpected <stream:stream> (shouldn't occur)
113 InvalidStreamStart,
114}
115
116impl fmt::Display for ProtocolError {
117 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
118 match self {
119 ProtocolError::Parser(e) => write!(fmt, "XML parser error: {}", e),
120 ProtocolError::Parsers(e) => write!(fmt, "error with expected stanza schema: {}", e),
121 ProtocolError::NoTls => write!(fmt, "no TLS available"),
122 ProtocolError::InvalidBindResponse => {
123 write!(fmt, "invalid response to resource binding")
124 }
125 ProtocolError::NoStreamNamespace => {
126 write!(fmt, "no xmlns attribute in <stream:stream>")
127 }
128 ProtocolError::NoStreamId => write!(fmt, "no id attribute in <stream:stream>"),
129 ProtocolError::InvalidToken => write!(fmt, "encountered an unexpected XML token"),
130 ProtocolError::InvalidStreamStart => write!(fmt, "unexpected <stream:stream>"),
131 }
132 }
133}
134
135impl StdError for ProtocolError {}
136
137impl From<minidom::Error> for ProtocolError {
138 fn from(e: minidom::Error) -> Self {
139 ProtocolError::Parser(e)
140 }
141}
142
143impl From<minidom::Error> for Error {
144 fn from(e: minidom::Error) -> Self {
145 ProtocolError::Parser(e).into()
146 }
147}
148
149impl From<ParsersError> for ProtocolError {
150 fn from(e: ParsersError) -> Self {
151 ProtocolError::Parsers(e)
152 }
153}
154
155/// Authentication error
156#[derive(Debug)]
157pub enum AuthError {
158 /// No matching SASL mechanism available
159 NoMechanism,
160 /// Local SASL implementation error
161 Sasl(SaslMechanismError),
162 /// Failure from server
163 Fail(SaslDefinedCondition),
164 /// Component authentication failure
165 ComponentFail,
166}
167
168impl StdError for AuthError {}
169
170impl fmt::Display for AuthError {
171 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
172 match self {
173 AuthError::NoMechanism => write!(fmt, "no matching SASL mechanism available"),
174 AuthError::Sasl(s) => write!(fmt, "local SASL implementation error: {}", s),
175 AuthError::Fail(c) => write!(fmt, "failure from the server: {:?}", c),
176 AuthError::ComponentFail => write!(fmt, "component authentication failure"),
177 }
178 }
179}