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