1- // TODO: Replace all string errors with this!
2-
3- use std:: { fmt:: Formatter , io} ;
1+ use std:: { fmt:: Formatter , io, net:: SocketAddrV6 , string:: FromUtf8Error } ;
42
53/// Errors from socks2
64#[ derive( Debug ) ]
75#[ non_exhaustive]
86#[ allow( missing_docs) ]
97pub enum Error {
10- // TODO: Add docs for all errors?
11- InvalidSocksAddress {
12- addr : String ,
13- } ,
14- InvalidPortValue {
15- addr : String ,
16- port : String ,
17- } ,
8+ // TargetAddr
9+ /// Domain name and port could not be parsed.
10+ InvalidSocksAddress { addr : String } ,
11+ /// Port could not be parsed or is over `u16::MAX`.
12+ InvalidPortValue { addr : String , port : String } ,
13+
14+ // Socks4/Socks5
15+ /// Response from server had an invalid version byte.
16+ InvalidResponseVersion { version : u8 } ,
17+ /// Unknown response code
18+ UnknownResponseCode { code : u8 } ,
19+ /// Connection refused or the request was rejected or failed.
20+ ConnectionRefused { code : u8 } ,
21+
22+ // Socks4
23+ /// Rejected request due to server not connecting to idnetd on the client.
24+ /// Rejected request due to idnetd and client program not having a matching userid.
25+ RejectedRequestID { code : u8 } ,
26+ /// Socks4 does not support IPv6.
27+ Socks4NoIPv6 { addr : SocketAddrV6 } ,
28+
29+ // Socks5
30+ /// Domain received from server was not valid utf8.
31+ MalformedDomain { err : FromUtf8Error } ,
32+ /// Received an invalid address type from the server.
33+ SOCKS5InvalidAddressType { code : u8 } ,
34+ /// Unknown error from the server.
35+ UnknownServerFailure { code : u8 } ,
36+ /// Server ruleset does not allow connection.
37+ ServerRefusedByRuleSet { } ,
38+ /// Network unreachable.
39+ ServerNetworkUnreachable { } ,
40+ /// Host unreachable.
41+ ServerHostUnreachable { } ,
42+ /// Time to live expired.
43+ ServerTTLExpired { } ,
44+ /// Server does not support the sent command.
45+ ServerCmdNotSupported { } ,
46+ /// Server does not support the address kind.
47+ ServerAddressNotSupported { } ,
48+ /// Reserved byte from server is invalid.
49+ InvalidReservedByte { byte : u8 } ,
50+ /// Domains must have a length between 1 and 255 inclusive.
51+ InvalidDomainLength { domain : String , length : usize } ,
52+ /// No acceptable auth methods.
53+ NoAuthMethods { method : u8 } ,
54+ /// Unknown auth method.
55+ UnknownAuthMethod { method : u8 } ,
56+ /// Invalid username.
57+ InvalidUsername { username : String , length : usize } ,
58+ /// Invalid password.
59+ InvalidPassword { password : ( ) , length : usize } ,
60+ /// Auth with password failed.
61+ FailedPasswordAuth { } ,
62+
63+ // UDP
64+ /// Reserved bytes from server is invalid.
65+ InvalidReservedBytes { bytes : u16 } ,
66+ /// Fragment id from the server is invalid.
67+ InvalidFragmentID { fid : u8 } ,
68+ /// UDP Bind Client has a limit of 4 GiB for buffers.
1869 /// Only occurs when using `Socks5Datagram` on windows.
19- WinUDP4GiBLimit {
20- size : usize ,
21- } ,
70+ WinUDP4GiBLimit { size : usize } ,
71+ }
72+
73+ /// Takes an `std::io::Error` and attempts to unwrap it into a `socks2::Error`.
74+ /// Returns a `Some(&socks2::Error)` on success.
75+ #[ must_use]
76+ pub fn unwrap_io_to_socks2_error ( e : & io:: Error ) -> Option < & Error > {
77+ e. get_ref ( ) . and_then ( |i| i. downcast_ref ( ) )
2278}
2379
2480impl Error {
@@ -39,7 +95,34 @@ impl PartialEq for Error {
3995 } ;
4096 }
4197
42- peq ! ( InvalidSocksAddress , InvalidPortValue , WinUDP4GiBLimit )
98+ peq ! (
99+ InvalidSocksAddress ,
100+ InvalidPortValue ,
101+ InvalidResponseVersion ,
102+ UnknownResponseCode ,
103+ ConnectionRefused ,
104+ RejectedRequestID ,
105+ Socks4NoIPv6 ,
106+ MalformedDomain ,
107+ SOCKS5InvalidAddressType ,
108+ UnknownServerFailure ,
109+ ServerRefusedByRuleSet ,
110+ ServerNetworkUnreachable ,
111+ ServerHostUnreachable ,
112+ ServerTTLExpired ,
113+ ServerCmdNotSupported ,
114+ ServerAddressNotSupported ,
115+ InvalidReservedByte ,
116+ InvalidDomainLength ,
117+ NoAuthMethods ,
118+ UnknownAuthMethod ,
119+ InvalidUsername ,
120+ InvalidPassword ,
121+ FailedPasswordAuth ,
122+ InvalidReservedBytes ,
123+ InvalidFragmentID ,
124+ WinUDP4GiBLimit
125+ )
43126 }
44127}
45128
@@ -56,6 +139,29 @@ impl From<Error> for io::Error {
56139 from_error ! (
57140 ( InvalidSocksAddress , InvalidInput ) ,
58141 ( InvalidPortValue , InvalidInput ) ,
142+ ( InvalidResponseVersion , InvalidData ) ,
143+ ( UnknownResponseCode , Other ) ,
144+ ( ConnectionRefused , ConnectionRefused ) ,
145+ ( RejectedRequestID , PermissionDenied ) ,
146+ ( Socks4NoIPv6 , InvalidInput ) ,
147+ ( MalformedDomain , InvalidData ) ,
148+ ( SOCKS5InvalidAddressType , InvalidData ) ,
149+ ( UnknownServerFailure , Other ) ,
150+ ( ServerRefusedByRuleSet , ConnectionRefused ) ,
151+ ( ServerNetworkUnreachable , ConnectionAborted ) ,
152+ ( ServerHostUnreachable , ConnectionAborted ) ,
153+ ( ServerTTLExpired , Interrupted ) ,
154+ ( ServerCmdNotSupported , Unsupported ) ,
155+ ( ServerAddressNotSupported , Unsupported ) ,
156+ ( InvalidReservedByte , Other ) ,
157+ ( InvalidDomainLength , InvalidInput ) ,
158+ ( NoAuthMethods , Unsupported ) ,
159+ ( UnknownAuthMethod , Unsupported ) ,
160+ ( InvalidUsername , InvalidInput ) ,
161+ ( InvalidPassword , InvalidInput ) ,
162+ ( FailedPasswordAuth , PermissionDenied ) ,
163+ ( InvalidReservedBytes , InvalidData ) ,
164+ ( InvalidFragmentID , InvalidData ) ,
59165 ( WinUDP4GiBLimit , InvalidInput )
60166 )
61167 }
@@ -70,6 +176,29 @@ impl std::fmt::Display for Error {
70176 Self :: InvalidPortValue { addr, port } => {
71177 write ! ( f, "invalid port value '{port}' for '{addr}'" )
72178 } ,
179+ Self :: InvalidResponseVersion { version } => write ! ( f, "invalid response version '{version}'" ) ,
180+ Self :: UnknownResponseCode { code } => write ! ( f, "unknown response code '{code}'" ) ,
181+ Self :: ConnectionRefused { code } => write ! ( f, "connection refused or the request was rejected or failed '{code}'" ) ,
182+ Self :: RejectedRequestID { code } => write ! ( f, "request rejected because of idnetd with code '{code}'" ) ,
183+ Self :: Socks4NoIPv6 { addr } => write ! ( f, "SOCKS4 does not support IPv6 '{addr}'" ) ,
184+ Self :: MalformedDomain { err } => write ! ( f, "malformed domain {err}" ) ,
185+ Self :: SOCKS5InvalidAddressType { code } => write ! ( f, "invalid address type {code}" ) ,
186+ Self :: UnknownServerFailure { code } => write ! ( f, "unknown server failure {code}" ) ,
187+ Self :: ServerRefusedByRuleSet { } => write ! ( f, "connection not allowed by ruleset" ) ,
188+ Self :: ServerNetworkUnreachable { } => write ! ( f, "network unreachable" ) ,
189+ Self :: ServerHostUnreachable { } => write ! ( f, "host unreachable" ) ,
190+ Self :: ServerTTLExpired { } => write ! ( f, "TTL expired" ) ,
191+ Self :: ServerCmdNotSupported { } => write ! ( f, "command not supported" ) ,
192+ Self :: ServerAddressNotSupported { } => write ! ( f, "address kind not supported" ) ,
193+ Self :: InvalidReservedByte { byte } => write ! ( f, "invalid reserved byte '{byte}'" ) ,
194+ Self :: InvalidDomainLength { domain, length } => write ! ( f, "domain '{domain}' with length '{length}' is not between 1-255 inclusive" ) ,
195+ Self :: NoAuthMethods { method } => write ! ( f, "no acceptable authentication methods '{method}'" ) ,
196+ Self :: UnknownAuthMethod { method } => write ! ( f, "unknown authentication method '{method}'" ) ,
197+ Self :: InvalidUsername { username, length} => write ! ( f, "invalid username '{username}' with length '{length}'" ) ,
198+ Self :: InvalidPassword { password, length} => write ! ( f, "invalid password '{password:?}' with length '{length}'" ) ,
199+ Self :: FailedPasswordAuth { } => write ! ( f, "password authentication failed" ) ,
200+ Self :: InvalidReservedBytes { bytes } => write ! ( f, "invalid reserved bytes '{bytes}'" ) ,
201+ Self :: InvalidFragmentID { fid} => write ! ( f, "invalid fragment ID '{fid}'" ) ,
73202 Self :: WinUDP4GiBLimit { size} => write ! ( f, "tried to write '{size}' bytes to UDPSocket, but writev/readv has a 4 GiB limit on windows" ) ,
74203 }
75204 }
0 commit comments