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}