error.rs

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