Skip to main content

eggress_server/
error.rs

1#[derive(Debug, thiserror::Error)]
2pub enum SessionOpenError {
3    #[error("connection timed out")]
4    Timeout,
5    #[error("connection refused")]
6    Refused,
7    #[error("network unreachable")]
8    NetworkUnreachable,
9    #[error("host unreachable")]
10    HostUnreachable,
11    #[error("DNS resolution failed")]
12    Dns,
13    #[error("upstream authentication failed")]
14    UpstreamAuthentication,
15    #[error("request rejected by policy")]
16    PolicyDenied,
17    #[error("route failed at hop {hop}")]
18    Hop {
19        hop: usize,
20        source: Box<SessionOpenError>,
21    },
22    #[error("other connection error: {0}")]
23    Other(String),
24}
25
26impl From<eggress_core::ConnectError> for SessionOpenError {
27    fn from(e: eggress_core::ConnectError) -> Self {
28        match e {
29            eggress_core::ConnectError::ConnectionRefused => SessionOpenError::Refused,
30            eggress_core::ConnectError::Timeout => SessionOpenError::Timeout,
31            eggress_core::ConnectError::DnsResolution(_) => SessionOpenError::Dns,
32            eggress_core::ConnectError::TlsHandshake(_) => {
33                SessionOpenError::Other("TLS handshake failed".into())
34            }
35            eggress_core::ConnectError::Io(io) => SessionOpenError::Other(io.to_string()),
36            eggress_core::ConnectError::ReservedTarget(addr) => {
37                SessionOpenError::Other(format!("reserved target: {addr}"))
38            }
39        }
40    }
41}
42
43impl From<eggress_core::chain::ChainError> for SessionOpenError {
44    fn from(e: eggress_core::chain::ChainError) -> Self {
45        match e {
46            eggress_core::chain::ChainError::ConnectFailed {
47                hop_index, source, ..
48            } => SessionOpenError::Hop {
49                hop: hop_index,
50                source: Box::new(SessionOpenError::from(source)),
51            },
52            eggress_core::chain::ChainError::HandshakeFailed {
53                hop_index, source, ..
54            } => SessionOpenError::Hop {
55                hop: hop_index,
56                source: Box::new(SessionOpenError::Other(source.to_string())),
57            },
58            eggress_core::chain::ChainError::EmptyChain => {
59                SessionOpenError::Other("empty chain".into())
60            }
61            eggress_core::chain::ChainError::InvalidChain { reason } => {
62                SessionOpenError::Other(format!("invalid chain: {reason}"))
63            }
64        }
65    }
66}
67
68impl From<eggress_protocol_http::HttpError> for SessionOpenError {
69    fn from(e: eggress_protocol_http::HttpError) -> Self {
70        match e {
71            eggress_protocol_http::HttpError::AuthRequired
72            | eggress_protocol_http::HttpError::AuthFailed => {
73                SessionOpenError::UpstreamAuthentication
74            }
75            eggress_protocol_http::HttpError::ConnectionRefused => SessionOpenError::Refused,
76            eggress_protocol_http::HttpError::GatewayTimeout => SessionOpenError::Timeout,
77            other => SessionOpenError::Other(other.to_string()),
78        }
79    }
80}
81
82impl From<eggress_protocol_socks::Socks5Error> for SessionOpenError {
83    fn from(e: eggress_protocol_socks::Socks5Error) -> Self {
84        match e {
85            eggress_protocol_socks::Socks5Error::ConnectionRefused => SessionOpenError::Refused,
86            eggress_protocol_socks::Socks5Error::AuthFailed => {
87                SessionOpenError::UpstreamAuthentication
88            }
89            other => SessionOpenError::Other(other.to_string()),
90        }
91    }
92}