Skip to main content

trojan_client/
error.rs

1//! Client error types.
2
3use std::fmt;
4
5/// Errors that can occur in the trojan client.
6#[derive(Debug, thiserror::Error)]
7pub enum ClientError {
8    #[error("I/O error: {0}")]
9    Io(#[from] std::io::Error),
10
11    #[error("TLS error: {0}")]
12    Tls(#[from] tokio_rustls::rustls::Error),
13
14    #[error("DNS resolution failed for {0}")]
15    Resolve(String),
16
17    #[error("SOCKS5 error: {0}")]
18    Socks5(Socks5Error),
19
20    #[error("Trojan protocol error: {0:?}")]
21    Proto(trojan_proto::WriteError),
22
23    #[error("config error: {0}")]
24    Config(String),
25}
26
27/// SOCKS5 protocol errors.
28#[derive(Debug)]
29pub enum Socks5Error {
30    InvalidVersion(u8),
31    NoAcceptableMethods,
32    UnsupportedCommand(u8),
33    UnsupportedAddressType(u8),
34    FragmentedUdp,
35}
36
37impl fmt::Display for Socks5Error {
38    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39        match self {
40            Self::InvalidVersion(v) => write!(f, "invalid SOCKS version: 0x{v:02x}"),
41            Self::NoAcceptableMethods => write!(f, "no acceptable authentication methods"),
42            Self::UnsupportedCommand(c) => write!(f, "unsupported command: 0x{c:02x}"),
43            Self::UnsupportedAddressType(a) => write!(f, "unsupported address type: 0x{a:02x}"),
44            Self::FragmentedUdp => write!(f, "fragmented UDP not supported"),
45        }
46    }
47}
48
49impl std::error::Error for Socks5Error {}
50
51impl From<Socks5Error> for ClientError {
52    fn from(e: Socks5Error) -> Self {
53        Self::Socks5(e)
54    }
55}
56
57impl From<trojan_proto::WriteError> for ClientError {
58    fn from(e: trojan_proto::WriteError) -> Self {
59        Self::Proto(e)
60    }
61}