1+ use super :: proxy:: { socks5, socks5_config:: random_auth} ;
2+ use multiaddr:: { MultiAddr , Protocol } ;
13pub use tokio:: {
24 net:: { TcpListener , TcpStream } ,
35 spawn,
46 task:: { JoinHandle , block_in_place, spawn_blocking, yield_now} ,
57} ;
68
7- use crate :: service:: config:: { TcpSocket , TcpSocketConfig } ;
9+ use crate :: service:: config:: {
10+ TcpSocket , TcpSocketConfig , TcpSocketTransformer , TransformerContext ,
11+ } ;
812use socket2:: { Domain , Protocol as SocketProtocol , Socket , Type } ;
913#[ cfg( unix) ]
1014use std:: os:: unix:: io:: { FromRawFd , IntoRawFd } ;
@@ -88,7 +92,8 @@ pub(crate) fn listen(addr: SocketAddr, tcp_config: TcpSocketConfig) -> io::Resul
8892 // user can disable it on tcp_config
8993 #[ cfg( not( windows) ) ]
9094 socket. set_reuse_address ( true ) ?;
91- let t = tcp_config ( TcpSocket { inner : socket } ) ?;
95+ let transformer_context = TransformerContext :: new_listen ( addr) ;
96+ let t = ( tcp_config. socket_transformer ) ( TcpSocket { inner : socket } , transformer_context) ?;
9297 t. inner . set_nonblocking ( true ) ?;
9398 // safety: fd convert by socket2
9499 unsafe {
@@ -113,15 +118,16 @@ pub(crate) fn listen(addr: SocketAddr, tcp_config: TcpSocketConfig) -> io::Resul
113118 socket. listen ( 1024 )
114119}
115120
116- pub ( crate ) async fn connect (
121+ async fn connect_direct (
117122 addr : SocketAddr ,
118- tcp_config : TcpSocketConfig ,
123+ socket_transformer : TcpSocketTransformer ,
119124) -> io:: Result < TcpStream > {
120125 let domain = Domain :: for_address ( addr) ;
121126 let socket = Socket :: new ( domain, Type :: STREAM , Some ( SocketProtocol :: TCP ) ) ?;
122127
123128 let socket = {
124- let t = tcp_config ( TcpSocket { inner : socket } ) ?;
129+ let transformer_context = TransformerContext :: new_dial ( addr) ;
130+ let t = socket_transformer ( TcpSocket { inner : socket } , transformer_context) ?;
125131 t. inner . set_nonblocking ( true ) ?;
126132 // safety: fd convert by socket2
127133 unsafe {
@@ -135,3 +141,93 @@ pub(crate) async fn connect(
135141
136142 socket. connect ( addr) . await
137143}
144+
145+ async fn connect_by_proxy (
146+ target_addr : String ,
147+ target_port : u16 ,
148+ proxy_url : url:: Url ,
149+ ) -> io:: Result < TcpStream > {
150+ socks5:: connect ( proxy_url. clone ( ) , target_addr. clone ( ) , target_port)
151+ . await
152+ . map_err ( |err| {
153+ io:: Error :: new (
154+ io:: ErrorKind :: Other ,
155+ format ! (
156+ "socks5_connect to target_addr: {}, target_port: {} by proxy_server: {} failed, err: {}" ,
157+ target_addr, target_port, proxy_url, err
158+ ) ,
159+ )
160+ } )
161+ }
162+
163+ pub ( crate ) async fn connect (
164+ target_addr : SocketAddr ,
165+ tcp_config : TcpSocketConfig ,
166+ ) -> io:: Result < TcpStream > {
167+ let TcpSocketConfig {
168+ socket_transformer,
169+ proxy_url,
170+ onion_url : _,
171+ onion_random_socks_auth : _,
172+ } = tcp_config;
173+
174+ match proxy_url {
175+ Some ( proxy_url) => connect_by_proxy (
176+ target_addr. ip ( ) . to_string ( ) ,
177+ target_addr. port ( ) ,
178+ proxy_url. clone ( ) ,
179+ )
180+ . await
181+ . map_err ( |err| {
182+ io:: Error :: new (
183+ io:: ErrorKind :: Other ,
184+ format ! ( "connect_by_proxy: {}, error: {}" , proxy_url, err) ,
185+ )
186+ } ) ,
187+ None => connect_direct ( target_addr, socket_transformer) . await ,
188+ }
189+ }
190+
191+ pub ( crate ) async fn connect_onion (
192+ onion_addr : MultiAddr ,
193+ tcp_config : TcpSocketConfig ,
194+ ) -> io:: Result < TcpStream > {
195+ let TcpSocketConfig {
196+ socket_transformer : _,
197+ proxy_url,
198+ onion_url,
199+ onion_random_socks_auth,
200+ } = tcp_config;
201+ let mut tor_server_url = onion_url. or ( proxy_url) . ok_or ( io:: Error :: other (
202+ "need tor proxy server to connect to onion address" ,
203+ ) ) ?;
204+
205+ if onion_random_socks_auth {
206+ let ( random_username, random_passwd) = random_auth ( ) ;
207+ tor_server_url
208+ . set_username ( & random_username)
209+ . map_err ( |_| io:: Error :: other ( "failed to set username" ) ) ?;
210+ tor_server_url
211+ . set_password ( Some ( & random_passwd) )
212+ . map_err ( |_| io:: Error :: other ( "failed to set password" ) ) ?;
213+ }
214+
215+ let onion_protocol = onion_addr
216+ . iter ( )
217+ . find_map ( |protocol| {
218+ if let Protocol :: Onion3 ( onion_address) = protocol {
219+ Some ( onion_address)
220+ } else {
221+ None
222+ }
223+ } )
224+ . ok_or ( io:: Error :: other ( format ! (
225+ "No Onion3 address found. in {}" ,
226+ onion_addr
227+ ) ) ) ?;
228+
229+ let onion_str = onion_protocol. hash_string ( ) + ".onion" ;
230+ let onion_port = onion_protocol. port ( ) ;
231+
232+ connect_by_proxy ( onion_str, onion_port, tor_server_url) . await
233+ }
0 commit comments