| 169 | |
| 170 | #[inline(never)] |
| 171 | pub async fn proxy_main(rt: &Runtime, config: &ProxyConfig, proxy: Proxy) -> Result<()> { |
| 172 | let mut tcp_listeners = Vec::new(); |
| 173 | for &port in &config.listen_port { |
| 174 | let listener = TcpListener::bind((config.listen_addr, port)) |
| 175 | .await |
| 176 | .with_context(|| format!("failed to bind {}:{}", config.listen_addr, port))?; |
| 177 | info!("tcp bridge listening on {}:{}", config.listen_addr, port); |
| 178 | tcp_listeners.push(listener); |
| 179 | } |
| 180 | if tcp_listeners.is_empty() { |
| 181 | bail!("no tcp listen ports configured"); |
| 182 | } |
| 183 | |
| 184 | let poll_counter = AtomicUsize::new(0); |
| 185 | loop { |
| 186 | // Accept from any TCP listener via round-robin poll. |
| 187 | let poll_start = poll_counter.fetch_add(1, Ordering::Relaxed); |
| 188 | let n = tcp_listeners.len(); |
| 189 | let accepted: std::io::Result<(TcpStream, std::net::SocketAddr)> = |
| 190 | std::future::poll_fn(|cx| { |
| 191 | for j in 0..n { |
| 192 | let i = (poll_start + j) % n; |
| 193 | if let Poll::Ready(result) = tcp_listeners[i].poll_accept(cx) { |
| 194 | return Poll::Ready(result); |
| 195 | } |
| 196 | } |
| 197 | Poll::Pending |
| 198 | }) |
| 199 | .await; |
| 200 | match accepted { |
| 201 | Ok((inbound, from)) => { |
| 202 | let span = info_span!("conn", id = next_connection_id()); |
| 203 | let _enter = span.enter(); |
| 204 | let conn_entered = EnteredCounter::new(&NUM_CONNECTIONS); |
| 205 | |
| 206 | info!(%from, "new connection"); |
| 207 | let proxy = proxy.clone(); |
| 208 | rt.spawn( |
| 209 | async move { |
| 210 | let _conn_entered = conn_entered; |
| 211 | let timeouts = &proxy.config.proxy.timeouts; |
| 212 | let result = |
| 213 | timeout(timeouts.total, handle_connection(inbound, proxy)).await; |
| 214 | match result { |
| 215 | Ok(Ok(_)) => { |
| 216 | info!("connection closed"); |
| 217 | } |
| 218 | Ok(Err(e)) => { |
| 219 | error!("connection error: {e:#}"); |
| 220 | } |
| 221 | Err(_) => { |
| 222 | error!("connection kept too long, force closing"); |
| 223 | } |
| 224 | } |
| 225 | } |
| 226 | .in_current_span(), |
| 227 | ); |
| 228 | } |