1use core::{error::Error as StdError, fmt, net::AddrParseError, str::Utf8Error};
2#[cfg(feature = "dns")]
3use hickory_resolver::{
4 error::ResolveError as DnsResolveError, proto::error::ProtoError as DnsProtoError,
5};
6use sasl::client::MechanismError as SaslMechanismError;
7use std::io;
8
9use xmpp_parsers::stream_error::ReceivedStreamError;
10
11use crate::{
12 connect::ServerConnectorError, jid, minidom,
13 parsers::sasl::DefinedCondition as SaslDefinedCondition, xmlstream::RecvFeaturesError,
14};
15
16#[derive(Debug)]
18pub enum Error {
19 Io(io::Error),
21 JidParse(jid::Error),
23 Protocol(ProtocolError),
25 Auth(AuthError),
27 Disconnected,
29 InvalidState,
31 Fmt(fmt::Error),
33 Utf8(Utf8Error),
35 Connection(Box<dyn ServerConnectorError>),
37 #[cfg(feature = "dns")]
39 Dns(DnsProtoError),
40 #[cfg(feature = "dns")]
42 Resolve(DnsResolveError),
43 #[cfg(feature = "dns")]
46 Idna,
47 Addr(AddrParseError),
49 StreamError(ReceivedStreamError),
51}
52
53impl fmt::Display for Error {
54 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
55 match self {
56 Error::Io(e) => write!(fmt, "IO error: {}", e),
57 Error::Connection(e) => write!(fmt, "connection error: {}", e),
58 Error::JidParse(e) => write!(fmt, "jid parse error: {}", e),
59 Error::Protocol(e) => write!(fmt, "protocol error: {}", e),
60 Error::Auth(e) => write!(fmt, "authentication error: {}", e),
61 Error::Disconnected => write!(fmt, "disconnected"),
62 Error::InvalidState => write!(fmt, "invalid state"),
63 Error::Fmt(e) => write!(fmt, "Fmt error: {}", e),
64 Error::Utf8(e) => write!(fmt, "Utf8 error: {}", e),
65 #[cfg(feature = "dns")]
66 Error::Dns(e) => write!(fmt, "{:?}", e),
67 #[cfg(feature = "dns")]
68 Error::Resolve(e) => write!(fmt, "{:?}", e),
69 #[cfg(feature = "dns")]
70 Error::Idna => write!(fmt, "IDNA error"),
71 Error::Addr(e) => write!(fmt, "Wrong network address: {e}"),
72 Error::StreamError(e) => write!(fmt, "{e}"),
73 }
74 }
75}
76
77impl StdError for Error {}
78
79impl From<io::Error> for Error {
80 fn from(e: io::Error) -> Self {
81 Error::Io(e)
82 }
83}
84
85impl<T: ServerConnectorError + 'static> From<T> for Error {
86 fn from(e: T) -> Self {
87 Error::Connection(Box::new(e))
88 }
89}
90
91impl From<jid::Error> for Error {
92 fn from(e: jid::Error) -> Self {
93 Error::JidParse(e)
94 }
95}
96
97impl From<ProtocolError> for Error {
98 fn from(e: ProtocolError) -> Self {
99 Error::Protocol(e)
100 }
101}
102
103impl From<AuthError> for Error {
104 fn from(e: AuthError) -> Self {
105 Error::Auth(e)
106 }
107}
108
109impl From<fmt::Error> for Error {
110 fn from(e: fmt::Error) -> Self {
111 Error::Fmt(e)
112 }
113}
114
115impl From<Utf8Error> for Error {
116 fn from(e: Utf8Error) -> Self {
117 Error::Utf8(e)
118 }
119}
120
121#[cfg(feature = "dns")]
122impl From<idna::Errors> for Error {
123 fn from(_e: idna::Errors) -> Self {
124 Error::Idna
125 }
126}
127
128#[cfg(feature = "dns")]
129impl From<DnsResolveError> for Error {
130 fn from(e: DnsResolveError) -> Error {
131 Error::Resolve(e)
132 }
133}
134
135#[cfg(feature = "dns")]
136impl From<DnsProtoError> for Error {
137 fn from(e: DnsProtoError) -> Error {
138 Error::Dns(e)
139 }
140}
141
142impl From<AddrParseError> for Error {
143 fn from(e: AddrParseError) -> Error {
144 Error::Addr(e)
145 }
146}
147
148impl From<RecvFeaturesError> for Error {
149 fn from(e: RecvFeaturesError) -> Self {
150 match e {
151 RecvFeaturesError::Io(e) => e.into(),
152 RecvFeaturesError::StreamError(e) => Self::StreamError(e),
153 }
154 }
155}
156
157#[derive(Debug)]
159pub enum ProtocolError {
160 Parser(minidom::Error),
162 Parsers(xso::error::Error),
164 NoTls,
166 InvalidBindResponse,
168 NoStreamNamespace,
170 NoStreamId,
172 InvalidToken,
174 InvalidStreamStart,
176}
177
178impl fmt::Display for ProtocolError {
179 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
180 match self {
181 ProtocolError::Parser(e) => write!(fmt, "XML parser error: {}", e),
182 ProtocolError::Parsers(e) => write!(fmt, "error with expected stanza schema: {}", e),
183 ProtocolError::NoTls => write!(fmt, "no TLS available"),
184 ProtocolError::InvalidBindResponse => {
185 write!(fmt, "invalid response to resource binding")
186 }
187 ProtocolError::NoStreamNamespace => {
188 write!(fmt, "no xmlns attribute in <stream:stream>")
189 }
190 ProtocolError::NoStreamId => write!(fmt, "no id attribute in <stream:stream>"),
191 ProtocolError::InvalidToken => write!(fmt, "encountered an unexpected XML token"),
192 ProtocolError::InvalidStreamStart => write!(fmt, "unexpected <stream:stream>"),
193 }
194 }
195}
196
197impl StdError for ProtocolError {}
198
199impl From<minidom::Error> for ProtocolError {
200 fn from(e: minidom::Error) -> Self {
201 ProtocolError::Parser(e)
202 }
203}
204
205impl From<minidom::Error> for Error {
206 fn from(e: minidom::Error) -> Self {
207 ProtocolError::Parser(e).into()
208 }
209}
210
211impl From<xso::error::Error> for ProtocolError {
212 fn from(e: xso::error::Error) -> Self {
213 ProtocolError::Parsers(e)
214 }
215}
216
217#[derive(Debug)]
219pub enum AuthError {
220 NoMechanism,
222 Sasl(SaslMechanismError),
224 Fail(SaslDefinedCondition),
226 ComponentFail,
228}
229
230impl StdError for AuthError {}
231
232impl fmt::Display for AuthError {
233 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
234 match self {
235 AuthError::NoMechanism => write!(fmt, "no matching SASL mechanism available"),
236 AuthError::Sasl(s) => write!(fmt, "local SASL implementation error: {}", s),
237 AuthError::Fail(c) => write!(fmt, "failure from the server: {:?}", c),
238 AuthError::ComponentFail => write!(fmt, "component authentication failure"),
239 }
240 }
241}