@@ -8,6 +8,7 @@ use std::{
88 atomic:: { AtomicU64 , AtomicUsize , Ordering } ,
99 Arc ,
1010 } ,
11+ task:: Poll ,
1112} ;
1213
1314use anyhow:: { bail, Context , Result } ;
@@ -173,21 +174,35 @@ pub async fn proxy_main(config: &ProxyConfig, proxy: Proxy) -> Result<()> {
173174 let base_domain = base_domain. strip_prefix ( "." ) . unwrap_or ( base_domain) ;
174175 Arc :: new ( format ! ( ".{base_domain}" ) )
175176 } ;
176- let listener = TcpListener :: bind ( ( config. listen_addr , config. listen_port ) )
177- . await
178- . with_context ( || {
179- format ! (
180- "failed to bind {}:{}" ,
181- config. listen_addr, config. listen_port
182- )
183- } ) ?;
184- info ! (
185- "tcp bridge listening on {}:{}" ,
186- config. listen_addr, config. listen_port
187- ) ;
177+ let mut tcp_listeners = Vec :: new ( ) ;
178+ for & port in & config. listen_port {
179+ let listener = TcpListener :: bind ( ( config. listen_addr , port) )
180+ . await
181+ . with_context ( || format ! ( "failed to bind {}:{}" , config. listen_addr, port) ) ?;
182+ info ! ( "tcp bridge listening on {}:{}" , config. listen_addr, port) ;
183+ tcp_listeners. push ( listener) ;
184+ }
185+ if tcp_listeners. is_empty ( ) {
186+ bail ! ( "no tcp listen ports configured" ) ;
187+ }
188188
189+ let poll_counter = AtomicUsize :: new ( 0 ) ;
189190 loop {
190- match listener. accept ( ) . await {
191+ // Accept from any TCP listener via round-robin poll.
192+ let poll_start = poll_counter. fetch_add ( 1 , Ordering :: Relaxed ) ;
193+ let n = tcp_listeners. len ( ) ;
194+ let accepted: std:: io:: Result < ( TcpStream , std:: net:: SocketAddr ) > =
195+ std:: future:: poll_fn ( |cx| {
196+ for j in 0 ..n {
197+ let i = ( poll_start + j) % n;
198+ if let Poll :: Ready ( result) = tcp_listeners[ i] . poll_accept ( cx) {
199+ return Poll :: Ready ( result) ;
200+ }
201+ }
202+ Poll :: Pending
203+ } )
204+ . await ;
205+ match accepted {
191206 Ok ( ( inbound, from) ) => {
192207 let span = info_span ! ( "conn" , id = next_connection_id( ) ) ;
193208 let _enter = span. enter ( ) ;
@@ -210,7 +225,7 @@ pub async fn proxy_main(config: &ProxyConfig, proxy: Proxy) -> Result<()> {
210225 info ! ( "connection closed" ) ;
211226 }
212227 Ok ( Err ( e) ) => {
213- error ! ( "connection error: {e:? }" ) ;
228+ error ! ( "connection error: {e:# }" ) ;
214229 }
215230 Err ( _) => {
216231 error ! ( "connection kept too long, force closing" ) ;
@@ -245,7 +260,7 @@ pub fn start(config: ProxyConfig, app_state: Proxy) -> Result<()> {
245260 // Run the proxy_main function in this runtime
246261 if let Err ( err) = rt. block_on ( proxy_main ( & config, app_state) ) {
247262 error ! (
248- "error on {}:{}: {err:?}" ,
263+ "error on {}:{:? }: {err:?}" ,
249264 config. listen_addr, config. listen_port
250265 ) ;
251266 }
0 commit comments