diff --git a/crates/arti/src/dns.rs b/crates/arti/src/dns.rs index 034daa2a0ca7a3a3eb2e8baa4ca752ad81138860..8e3970c9bc14477eda57b64b3b538507331a94aa 100644 --- a/crates/arti/src/dns.rs +++ b/crates/arti/src/dns.rs @@ -19,6 +19,9 @@ use tor_rtcompat::{Runtime, UdpSocket}; use anyhow::{anyhow, Result}; +/// Maximum lenght for receiving a single datagram +const MAX_DATAGRAM_SIZE: usize = 1536; + /// Send an error DNS response with code NotImplemented async fn not_implemented<U: UdpSocket>(id: u16, addr: &SocketAddr, socket: &U) -> Result<()> { let response = Message::error_msg(id, OpCode::Query, ResponseCode::NotImp); @@ -133,7 +136,7 @@ pub(crate) async fn run_dns_resolver<R: Runtime>( // We weren't able to bind any ports: There's nothing to do. if listeners.is_empty() { error!("Couldn't open any DNS listeners."); - return Err(anyhow!("Couldn't open SOCKS listeners")); + return Err(anyhow!("Couldn't open any DNS listeners")); } let mut incoming = futures::stream::select_all( @@ -141,7 +144,7 @@ pub(crate) async fn run_dns_resolver<R: Runtime>( .into_iter() .map(|socket| { futures::stream::unfold(Arc::new(socket), |socket| async { - let mut packet = [0; 1536]; + let mut packet = [0; MAX_DATAGRAM_SIZE]; let packet = socket .recv(&mut packet) .await diff --git a/crates/arti/src/lib.rs b/crates/arti/src/lib.rs index 87dbd7759d42dee38920d3a8ff808c69b851f032..e4d357d7c10dde2026bacd0eb87b963cc85a0d07 100644 --- a/crates/arti/src/lib.rs +++ b/crates/arti/src/lib.rs @@ -131,6 +131,9 @@ use tracing::{info, warn}; use std::convert::TryInto; +/// Shorthand for a boxed and pinned Future. +type PinnedFuture<T> = std::pin::Pin<Box<dyn futures::Future<Output = T>>>; + /// Run the main loop of the proxy. /// /// # Panics @@ -156,21 +159,23 @@ pub async fn run<R: Runtime>( watch_cfg::watch_for_config_changes(config_sources, arti_config, client.clone())?; } - let mut proxy: Vec<std::pin::Pin<Box<dyn futures::Future<Output = Result<()>>>>> = Vec::new(); + let mut proxy: Vec<PinnedFuture<(Result<()>, &str)>> = Vec::new(); if socks_port != 0 { - proxy.push(Box::pin(socks::run_socks_proxy( - runtime.clone(), - client.isolated_client(), - socks_port, - ))); + let runtime = runtime.clone(); + let client = client.isolated_client(); + proxy.push(Box::pin(async move { + let res = socks::run_socks_proxy(runtime, client, socks_port).await; + (res, "SOCKS") + })); } if dns_port != 0 { - proxy.push(Box::pin(dns::run_dns_resolver( - runtime.clone(), - client.isolated_client(), - dns_port, - ))); + let runtime = runtime.clone(); + let client = client.isolated_client(); + proxy.push(Box::pin(async move { + let res = dns::run_dns_resolver(runtime, client, dns_port).await; + (res, "DNS") + })); } if proxy.is_empty() { @@ -179,12 +184,12 @@ pub async fn run<R: Runtime>( return Ok(()); } - let proxy = futures::future::select_all(proxy); + let proxy = futures::future::select_all(proxy).map(|(finished, _index, _others)| finished); futures::select!( r = exit::wait_for_ctrl_c().fuse() => r.context("waiting for termination signal"), r = proxy.fuse() - => r.0.context("SOCKS proxy failure"), + => r.0.context(format!("{} proxy failure", r.1)), r = async { client.bootstrap().await?; info!("Sufficiently bootstrapped; system SOCKS now functional."); diff --git a/crates/tor-rtcompat/src/traits.rs b/crates/tor-rtcompat/src/traits.rs index 6901a891fc79cf807c105c09abc121364a8be932..7c028d57db67dff8cf1d8e4e9d3de0f73f8555ad 100644 --- a/crates/tor-rtcompat/src/traits.rs +++ b/crates/tor-rtcompat/src/traits.rs @@ -204,7 +204,7 @@ pub trait UdpSocket { /// Connect to a remote address. After calling this [`UdpSocket::recv`] may only /// return that same address, and the target provided to [`UdpSocket::send`] must /// be this address. - // rational for taking &mut self: this changes the behavior of the whole socket, + // rationale for taking &mut self: this changes the behavior of the whole socket, // so it should probably only be used when you have ownership of the socket and // not when sharing it. async fn connect(&mut self, addr: &SocketAddr) -> IoResult<()>;