1use std::fmt;
4
5#[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#[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}