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