From 386d422a1be8f7c28abd6f461944ee609839f95f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 22 Aug 2023 11:33:27 -0400 Subject: [PATCH] hss: Retry rendezvous circuit attempts. Closes #1013. --- Cargo.lock | 1 + crates/tor-hsservice/Cargo.toml | 1 + .../tor-hsservice/src/svc/rend_handshake.rs | 34 ++++++++++++++----- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7a049cb40..b0ba9114c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4639,6 +4639,7 @@ dependencies = [ "postage", "rand 0.8.5", "rand_core 0.6.4", + "retry-error", "safelog", "serde", "serde_json", diff --git a/crates/tor-hsservice/Cargo.toml b/crates/tor-hsservice/Cargo.toml index 3006e60b0..dbd9cd679 100644 --- a/crates/tor-hsservice/Cargo.toml +++ b/crates/tor-hsservice/Cargo.toml @@ -35,6 +35,7 @@ once_cell = "1" postage = { version = "0.5.0", default-features = false, features = ["futures-traits"] } rand = "0.8.5" rand_core = "0.6.2" +retry-error = { version = "0.5.0", path = "../retry-error" } safelog = { path = "../safelog", version = "0.3.3" } serde = { version = "1.0.103", features = ["derive"] } thiserror = "1" diff --git a/crates/tor-hsservice/src/svc/rend_handshake.rs b/crates/tor-hsservice/src/svc/rend_handshake.rs index 0673bc04c..9a6018930 100644 --- a/crates/tor-hsservice/src/svc/rend_handshake.rs +++ b/crates/tor-hsservice/src/svc/rend_handshake.rs @@ -5,6 +5,7 @@ use std::sync::Arc; use futures::{stream::BoxStream, StreamExt as _}; +use retry_error::RetryError; use tor_cell::relaycell::{ hs::intro_payload::{IntroduceHandshakePayload, OnionKey}, msg::{Introduce2, Rendezvous1}, @@ -59,9 +60,9 @@ pub(crate) enum EstablishSessionError { /// Got an onion key with an unrecognized type (not ntor). #[error("Received an unsupported type of onion key")] UnsupportedOnionKey, - /// Encountered an error while trying to build a circuit to the rendezvous point. + /// Unable to build a circuit to the rendezvous point. #[error("Could not establish circuit to rendezvous point")] - RendCirc(#[source] tor_circmgr::Error), + RendCirc(#[source] RetryError), /// Encountered a failure while trying to add a virtual hop to the circuit. #[error("Could not add virtual hop to circuit")] VirtualHop(#[source] tor_proto::Error), @@ -226,13 +227,30 @@ impl IntroRequest { ) }; + let max_n_attempts = netdir.params().hs_service_rendezvous_failures_max; + let mut circuit = None; + let mut retry_err: RetryError = + RetryError::in_attempt_to("Establish a circuit to a rendezvous point"); + // Open circuit to rendezvous point. - let circuit = hs_pool - .get_or_launch_specific(&netdir, HsCircKind::SvcRend, rend_point) - .await - .map_err(E::RendCirc)?; - // TODO HSS: Maybe we should retry a couple of time if the failure is not - // the fault of the rend_point? + for _attempt in 1..=max_n_attempts.into() { + match hs_pool + .get_or_launch_specific(&netdir, HsCircKind::SvcRend, rend_point.clone()) + .await + { + Ok(circ) => { + circuit = Some(circ); + break; + } + Err(e) => { + retry_err.push(e); + // Note that we do not sleep on errors: if there is any + // error that will be solved by waiting, it would probably + // require waiting too long to satisfy the client. + } + } + } + let circuit = circuit.ok_or_else(|| E::RendCirc(retry_err))?; // We'll need parameters to extend the virtual hop. let params = circparameters_from_netparameters(netdir.params());