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::Error as ParsersError;
 11use xmpp_parsers::sasl::DefinedCondition as SaslDefinedCondition;
 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 => write!(fmt, "invalid response to resource binding"),
163            ProtocolError::NoStreamNamespace => write!(fmt, "no xmlns attribute in <stream:stream>"),
164            ProtocolError::NoStreamId => write!(fmt, "no id attribute in <stream:stream>"),
165            ProtocolError::InvalidToken => write!(fmt, "encountered an unexpected XML token"),
166            ProtocolError::InvalidStreamStart => write!(fmt, "unexpected <stream:stream>"),
167        }
168    }
169}
170
171impl From<ParserError> for ProtocolError {
172    fn from(e: ParserError) -> Self {
173        ProtocolError::Parser(e)
174    }
175}
176
177impl From<ParsersError> for ProtocolError {
178    fn from(e: ParsersError) -> Self {
179        ProtocolError::Parsers(e)
180    }
181}
182
183/// Authentication error
184#[derive(Debug)]
185pub enum AuthError {
186    /// No matching SASL mechanism available
187    NoMechanism,
188    /// Local SASL implementation error
189    Sasl(String),
190    /// Failure from server
191    Fail(SaslDefinedCondition),
192    /// Component authentication failure
193    ComponentFail,
194}
195
196impl fmt::Display for AuthError {
197    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
198        match self {
199            AuthError::NoMechanism => write!(fmt, "no matching SASL mechanism available"),
200            AuthError::Sasl(s) => write!(fmt, "local SASL implementation error: {}", s),
201            AuthError::Fail(c) => write!(fmt, "failure from the server: {:?}", c),
202            AuthError::ComponentFail => write!(fmt, "component authentication failure"),
203        }
204    }
205}
206
207/// Error establishing connection
208#[derive(Debug)]
209pub enum ConnecterError {
210    /// All attempts failed, no error available
211    AllFailed,
212    /// DNS protocol error
213    Dns(ProtoError),
214    /// DNS resolution error
215    Resolve(ResolveError),
216}
217
218impl std::error::Error for ConnecterError {}
219
220impl std::fmt::Display for ConnecterError {
221    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
222        write!(fmt, "{:?}", self)
223    }
224}