use super::core::HandshakeError;
use rama_core::error::BoxError;
use rama_net::client::{ConnectionError, ConnectionErrorKind};
use std::fmt;
#[derive(Debug)]
pub enum Socks5ProxyError {
Handshake(HandshakeError),
Transport(BoxError),
}
impl fmt::Display for Socks5ProxyError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Handshake(error) => {
write!(f, "socks5 proxy error: handshake error [{error}]")
}
Self::Transport(error) => {
write!(f, "socks5 proxy error: transport error: I/O [{error}]")
}
}
}
}
impl From<std::io::Error> for Socks5ProxyError {
fn from(value: std::io::Error) -> Self {
Self::Transport(value.into())
}
}
impl std::error::Error for Socks5ProxyError {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
match self {
Self::Handshake(err) => match err.source() {
Some(err_src) if !err_src.is::<std::io::Error>() => Some(err_src),
_ => Some(err as &dyn std::error::Error),
},
Self::Transport(err) => {
let err_ref = err.source().unwrap_or_else(|| err.as_ref());
if err_ref.is::<std::io::Error>() {
Some(self)
} else {
Some(err_ref)
}
}
}
}
}
impl From<Socks5ProxyError> for ConnectionError {
fn from(error: Socks5ProxyError) -> Self {
let kind = match &error {
Socks5ProxyError::Handshake(error) => error.connection_error_kind(),
Socks5ProxyError::Transport(_) => ConnectionErrorKind::Unavailable,
};
Self::transport(error, kind)
}
}