@@ -55,6 +55,7 @@ pub async fn handle_associate(
5555 & settings,
5656 & mut addr_to_cid,
5757 & buf[ ..size] ,
58+ hops,
5859 )
5960 . await
6061 else {
@@ -80,6 +81,7 @@ async fn process_socks5_packet(
8081 settings : & Arc < ArcSwap < TunnelSettings > > ,
8182 addr_to_cid : & mut HashMap < Address , u32 > ,
8283 buf : & [ u8 ] ,
84+ hops : u8 ,
8385) -> Option < ( SocketAddr , Vec < u8 > , u32 ) > {
8486 let header = match UdpHeader :: read_from ( & mut Cursor :: new ( buf) ) . await {
8587 Ok ( header) => header,
@@ -91,16 +93,20 @@ async fn process_socks5_packet(
9193
9294 let pkt = & buf[ header. serialized_len ( ) ..] . to_vec ( ) ;
9395 let address = & header. address ;
94- let Some ( circuit_id) = select_circuit ( address, associated_socket, circuits, addr_to_cid) else {
95- warn ! ( "No circuits available, dropping packet" ) ;
96+ let Some ( circuit_id) = select_circuit ( address, associated_socket, circuits, addr_to_cid, hops)
97+ else {
98+ warn ! ( "No {}-hop circuits available, dropping packet" , hops) ;
9699 return None ;
97100 } ;
98101
99102 match circuits. lock ( ) . unwrap ( ) . get_mut ( & circuit_id) {
100103 Some ( circuit) => {
101104 if circuit. socket . is_none ( ) {
102105 circuit. socket = Some ( associated_socket. clone ( ) ) ;
103- info ! ( "Associated socket for circuit {}" , circuit_id) ;
106+ info ! (
107+ "Associated socket ({} hops) for circuit {} ({})" ,
108+ hops, circuit_id, circuit. goal_hops
109+ ) ;
104110 }
105111
106112 let guard = settings. load ( ) ;
@@ -126,6 +132,7 @@ fn select_circuit(
126132 socket : & Arc < UdpSocket > ,
127133 circuits : & Arc < Mutex < HashMap < u32 , Circuit > > > ,
128134 addr_to_cid : & mut HashMap < Address , u32 > ,
135+ hops : u8 ,
129136) -> Option < u32 > {
130137 // Deal with hidden services
131138 if let Address :: SocketAddress ( SocketAddr :: V4 ( addr) ) = address {
@@ -154,7 +161,7 @@ fn select_circuit(
154161 match addr_to_cid. get ( address) {
155162 Some ( cid) => Some ( * cid) ,
156163 None => {
157- let options = get_options ( & socket, & circuits) ;
164+ let options = get_options ( & socket, & circuits, hops , 2 ) ;
158165 let Some ( & cid) = options. choose ( & mut rand:: rng ( ) ) else {
159166 return None ;
160167 } ;
@@ -164,13 +171,25 @@ fn select_circuit(
164171 }
165172}
166173
167- fn get_options ( socket : & Arc < UdpSocket > , circuits : & Arc < Mutex < HashMap < u32 , Circuit > > > ) -> Vec < u32 > {
174+ fn get_options (
175+ socket : & Arc < UdpSocket > ,
176+ circuits : & Arc < Mutex < HashMap < u32 , Circuit > > > ,
177+ hops : u8 ,
178+ limit : u8 ,
179+ ) -> Vec < u32 > {
168180 let guard = circuits. lock ( ) . unwrap ( ) ;
169- guard
181+ let mut circuits : Vec < & Circuit > = guard
170182 . values ( )
171183 . filter ( |c| {
172- c. data_ready ( ) && ( c. socket . is_none ( ) || Arc :: ptr_eq ( c. socket . as_ref ( ) . unwrap ( ) , & socket) )
184+ c. goal_hops == hops
185+ && c. data_ready ( )
186+ && ( c. socket . is_none ( ) || Arc :: ptr_eq ( c. socket . as_ref ( ) . unwrap ( ) , & socket) )
173187 } )
188+ . collect ( ) ;
189+ circuits. sort_by_key ( |c| c. socket . is_none ( ) as u8 ) ;
190+ circuits
191+ . iter ( )
174192 . map ( |c| c. circuit_id )
193+ . take ( limit as usize )
175194 . collect ( )
176195}
0 commit comments