1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
// Copyright (c) 2019 Reyk Floeter <contact@reykfloeter.com>
//
// Permission to use, copy, modify, and distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

use std::{error, ffi, fmt, io, num};

/// An error returned by [`Tls`] and [`Config`] methods.
///
/// This error includes the detailed error message of a failed `libtls`
/// operation.
///
/// [`Tls`]: ../tls/struct.Tls.html
/// [`Config`]: ../config/struct.Config.html
#[derive(Debug)]
pub enum Error {
    /// [`Tls`](../tls/struct.Tls.html) error.
    ///
    /// # See also
    ///
    /// [`Tls::last_error`](../tls/struct.Tls.html#method.last_error),
    /// [`tls_error(3)`](https://man.openbsd.org/tls_error.3)
    CtxError(String),
    /// [`Config`](../config/struct.Config.html) error.
    ///
    /// # See also
    ///
    /// [`Config::last_error`](../config/struct.Config.html#method.last_error),
    /// [`tls_config_error(3)`](https://man.openbsd.org/tls_config_error.3)
    ConfigError(String),
    /// Generic operating system or I/O error.
    IoError(io::Error),
    /// An interior nul byte was found.
    NulError(ffi::NulError),
    /// No error was reported.
    NoError,
}

/// An error returned by [`Tls`] and [`Config`] methods.
#[deprecated(since = "1.1.1", note = "Please use `Error` instead of `TlsError`")]
pub type TlsError = Error;

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            Error::CtxError(s) => write!(f, "tls context: {}", s),
            Error::ConfigError(s) => write!(f, "tls config: {}", s),
            Error::IoError(err) => err.fmt(f),
            Error::NulError(err) => err.fmt(f),
            Error::NoError => write!(f, "no error"),
        }
    }
}

impl error::Error for Error {
    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
        None
    }
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Self {
        Error::IoError(err)
    }
}

impl From<ffi::NulError> for Error {
    fn from(err: ffi::NulError) -> Self {
        Error::NulError(err)
    }
}

impl From<num::TryFromIntError> for Error {
    fn from(err: num::TryFromIntError) -> Self {
        Error::IoError(io::Error::new(io::ErrorKind::Other, err))
    }
}

impl From<Error> for io::Error {
    fn from(err: Error) -> Self {
        io::Error::new(io::ErrorKind::Other, err)
    }
}

/// A result type that is returning a [Error](enum.Error.html).
pub type Result<T> = std::result::Result<T, Error>;

/// Returns the last API error.
///
/// The [`Tls`] and [`Config`] structs both provide a way to return
/// the last error as a String from the underlying API.
///
/// [`Tls`]: ../tls/struct.Tls.html
/// [`Config`]: ../tls/struct.Config.html
pub trait LastError {
    /// Return the last error of the underlying API.
    ///
    /// The `last_error` method returns an error if no error occurred
    /// at all, or if memory allocation failed while trying to assemble the
    /// string describing the most recent error related to config.
    fn last_error(&self) -> Result<String>;

    /// Returns the error string as an error object.
    fn to_error<T>(errstr: String) -> Result<T> {
        Err(Error::ConfigError(errstr))
    }
}