circmgr: New API to expose estimate-based timeouts.

This will help create good timeout values for various onion-service
operations.
This commit is contained in:
Nick Mathewson 2023-06-21 11:52:13 -04:00
parent 8948d611bd
commit 2b0d04a5fe
4 changed files with 33 additions and 4 deletions

View File

@ -0,0 +1 @@
ADDED: estimate_timeout function, and public timeouts::Action.

View File

@ -316,7 +316,6 @@ impl<R: Runtime, C: Buildable + Sync + Send + 'static> Builder<R, C> {
}
/// Return a reference to this Builder's timeout estimator.
#[cfg(feature = "hs-common")]
pub(crate) fn estimator(&self) -> &timeouts::Estimator {
&self.timeouts
}
@ -459,7 +458,6 @@ impl<R: Runtime> CircuitBuilder<R> {
}
/// Return a reference to this builder's timeout estimator.
#[cfg(feature = "hs-common")]
pub(crate) fn estimator(&self) -> &timeouts::Estimator {
self.builder.estimator()
}

View File

@ -68,7 +68,7 @@ pub mod isolation;
mod mgr;
pub mod path;
mod preemptive;
mod timeouts;
pub mod timeouts;
mod usage;
pub use err::Error;
@ -548,6 +548,36 @@ impl<R: Runtime> CircMgr<R> {
self.mgr.retire_all_circuits();
}
/// Return an estimate-based delay for how long a given
/// [`Action`](timeouts::Action) should be allowed to complete.
///
/// Note that **you do not need to use this function** in order to get
/// reasonable timeouts for the circuit-building operations provided by the
/// `tor-circmgr` crate: those, unless specifically noted, always use these
/// timeouts to cancel circuit operations that have taken too long.
///
/// Instead, you should only use this function when you need to estimate how
/// long some _other_ operation should take to complete. For example, if
/// you are sending a request over a 3-hop circuit and waiting for a reply,
/// you might choose to wait for `estimate_timeout(Action::RoundTrip {
/// length: 3 })`.
///
/// Note also that this function returns a _timeout_ that the operation
/// should be permitted to complete, not an estimated Duration that the
/// operation _will_ take to complete. Timeouts are chosen to ensure that
/// most operations will complete, but very slow ones will not. So even if
/// we expect that a circuit will complete in (say) 3 seconds, we might
/// still allow a timeout of 4.5 seconds, to ensure that most circuits can
/// complete.
///
/// Estimate-based timeouts may change over time, given observations on the
/// actual amount of time needed for circuits to complete building. If not
/// enough information has been gathered, a reasonable default will be used.
pub fn estimate_timeout(&self, timeout_action: &timeouts::Action) -> std::time::Duration {
let (timeout, _abandon) = self.mgr.peek_builder().estimator().timeouts(timeout_action);
timeout
}
/// Expire every circuit that has been dirty for too long.
///
/// Expired circuits are not closed while they still have users,

View File

@ -66,7 +66,7 @@ pub(crate) trait TimeoutEstimator {
/// A possible action for which we can try to estimate a timeout.
#[non_exhaustive]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum Action {
pub enum Action {
/// Build a circuit of a given length.
BuildCircuit {
/// The length of the circuit to construct.