(
globals: Arc<Globals>,
net_udp_socket: std::net::UdpSocket,
)
| 416 | |
| 417 | #[allow(unreachable_code)] |
| 418 | async fn udp_acceptor( |
| 419 | globals: Arc<Globals>, |
| 420 | net_udp_socket: std::net::UdpSocket, |
| 421 | ) -> Result<(), Error> { |
| 422 | let runtime_handle = globals.runtime_handle.clone(); |
| 423 | let tokio_udp_socket = UdpSocket::try_from(net_udp_socket.try_clone()?)?; |
| 424 | let timeout = globals.udp_timeout; |
| 425 | let concurrent_connections = globals.udp_concurrent_connections.clone(); |
| 426 | let active_connections = globals.udp_active_connections.clone(); |
| 427 | loop { |
| 428 | let mut packet = vec![0u8; DNSCRYPT_UDP_QUERY_MAX_SIZE]; |
| 429 | let (packet_len, client_addr) = tokio_udp_socket.recv_from(&mut packet).await?; |
| 430 | if packet_len < DNS_HEADER_SIZE { |
| 431 | continue; |
| 432 | } |
| 433 | |
| 434 | if let Some(ref rate_limiter) = globals.rate_limiter { |
| 435 | if !rate_limiter.is_allowed(client_addr.ip()) { |
| 436 | debug!("Rate limit exceeded for {}", client_addr.ip()); |
| 437 | #[cfg(feature = "metrics")] |
| 438 | globals.varz.client_queries_rate_limited.inc(); |
| 439 | continue; |
| 440 | } |
| 441 | } |
| 442 | |
| 443 | packet.truncate(packet_len); |
| 444 | |
| 445 | let active_count = concurrent_connections.load(Ordering::Relaxed); |
| 446 | if active_count >= globals.udp_max_active_connections { |
| 447 | debug!("UDP connection limit reached, dropping packet"); |
| 448 | continue; |
| 449 | } |
| 450 | |
| 451 | // Clone the socket for this request |
| 452 | let net_udp_socket = match net_udp_socket.try_clone() { |
| 453 | Ok(socket) => socket, |
| 454 | Err(e) => { |
| 455 | error!("Failed to clone UDP socket: {}", e); |
| 456 | // Add a small delay to avoid spinning on socket errors |
| 457 | tokio::time::sleep(Duration::from_millis(100)).await; |
| 458 | continue; |
| 459 | } |
| 460 | }; |
| 461 | |
| 462 | let client_ctx = ClientCtx::Udp(UdpClientCtx { |
| 463 | net_udp_socket, |
| 464 | client_addr, |
| 465 | }); |
| 466 | let (tx, rx) = oneshot::channel::<()>(); |
| 467 | let tx_channel_index = { |
| 468 | let mut active_connections = active_connections.lock(); |
| 469 | if active_connections.is_full() { |
| 470 | let tx_oldest = active_connections.pop_back().unwrap(); |
| 471 | let _ = tx_oldest.send(()); |
| 472 | } |
| 473 | active_connections.push_front(tx)? |
| 474 | }; |
| 475 | let _count = concurrent_connections.fetch_add(1, Ordering::Relaxed); |
no test coverage detected