error.rs

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