1
//! Declare error types for tor-chanmgr
2

            
3
use std::net::SocketAddr;
4
use std::sync::Arc;
5

            
6
use futures::task::SpawnError;
7
use thiserror::Error;
8

            
9
use tor_error::{internal, ErrorKind};
10

            
11
/// An error returned by a channel manager.
12
4
#[derive(Debug, Error, Clone)]
13
#[non_exhaustive]
14
pub enum Error {
15
    /// A ChanTarget was given for which no channel could be built.
16
    #[error("Target was unusable: {0}")]
17
    UnusableTarget(#[source] tor_error::Bug),
18

            
19
    /// We were waiting on a pending channel, but it didn't succeed.
20
    #[error("Pending channel failed to launch")]
21
    PendingFailed,
22

            
23
    /// It took too long for us to establish this connection.
24
    #[error("Channel timed out")]
25
    ChanTimeout,
26

            
27
    /// A protocol error while making a channel
28
    #[error("Protocol error while opening a channel: {0}")]
29
    Proto(#[from] tor_proto::Error),
30

            
31
    /// Network IO error or TLS error
32
    #[error("Network IO error, or TLS error, in {action}, talking to {peer}")]
33
    Io {
34
        /// Who we were talking to
35
        peer: SocketAddr,
36

            
37
        /// What we were doing
38
        action: &'static str,
39

            
40
        /// What happened.  Might be some TLS library error wrapped up in io::Error
41
        #[source]
42
        source: Arc<std::io::Error>,
43
    },
44

            
45
    /// Failed to build a channel, after trying multiple addresses.
46
    #[error("Channel build failed: [(address, error)] = {addresses:?}")]
47
    ChannelBuild {
48
        /// The list of addresses we tried to connect to, coupled with
49
        /// the error we encountered connecting to each one.
50
        addresses: Vec<(SocketAddr, Arc<std::io::Error>)>,
51
    },
52

            
53
    /// Unable to spawn task
54
    #[error("unable to spawn {spawning}")]
55
    Spawn {
56
        /// What we were trying to spawn.
57
        spawning: &'static str,
58
        /// What happened when we tried to spawn it.
59
        #[source]
60
        cause: Arc<SpawnError>,
61
    },
62
    /// An internal error of some kind that should never occur.
63
    #[error("Internal error: {0}")]
64
    Internal(#[from] tor_error::Bug),
65
}
66

            
67
impl From<tor_rtcompat::TimeoutError> for Error {
68
    fn from(_: tor_rtcompat::TimeoutError) -> Error {
69
        Error::ChanTimeout
70
    }
71
}
72

            
73
impl<T> From<std::sync::PoisonError<T>> for Error {
74
    fn from(_: std::sync::PoisonError<T>) -> Error {
75
        Error::Internal(internal!("Thread failed while holding lock"))
76
    }
77
}
78

            
79
impl tor_error::HasKind for Error {
80
    fn kind(&self) -> ErrorKind {
81
        use tor_proto::Error as ProtoErr;
82
        use Error as E;
83
        use ErrorKind as EK;
84
        match self {
85
            E::ChanTimeout | E::Io { .. } | E::Proto(ProtoErr::ChanIoErr(_)) => EK::TorAccessFailed,
86
            E::Spawn { cause, .. } => cause.kind(),
87
            E::Proto(e) => e.kind(),
88
            E::PendingFailed => EK::TorAccessFailed,
89
            E::UnusableTarget(_) | E::Internal(_) => EK::Internal,
90
            Error::ChannelBuild { .. } => EK::TorAccessFailed,
91
        }
92
    }
93
}
94

            
95
impl Error {
96
    /// Construct a new `Error` from a `SpawnError`.
97
    pub(crate) fn from_spawn(spawning: &'static str, err: SpawnError) -> Error {
98
        Error::Spawn {
99
            spawning,
100
            cause: Arc::new(err),
101
        }
102
    }
103
}