Files
tsunagi/vendor/iroh/src/endpoint/presets.rs
T
Aleksandr Bogomiakov 2b0c938487 Bound iroh path retries to prevent multi-connection OOM
A long-running rc.33 daemon reached OOM with roughly 22 GiB resident and
24 GiB swapped. Live inspection found 40 GiB and 10/20 GiB anonymous
container mappings; the active worker stack and tracing metadata identified
iroh's scheduled path-open retry loop. In iroh 1.2.0 every failed connection
requeues the same path, while each retry visits every connection again.
Separate control and data connections multiply the queue geometrically.

Vendor the published iroh 1.2.0 source and select it with a workspace Cargo
patch. Deduplicate retry admission and cap distinct pending paths at 64,
evicting the oldest before inserting a new candidate. Keep the current and
next retry batches bounded without combining control/data connections or
changing wire protocols, identity derivation, authentication or state.
Document source provenance, the live evidence and removal conditions.
Upstream PR 4551 merged on October 6, but inspection of the official 1.3.0
crate still shows the unconditional enqueue, so that upgrade alone is not
a fix. No version bump, release tag or installed-service change.

The default workspace suite includes the exact vendored admission module.
Three regressions failed with the original enqueue and pass with the fix:
repeated failures across connections, duplicate admission at capacity, and
10,000 distinct candidates with bounded length/capacity and FIFO eviction.
Transport integration tests continue using real endpoints and encryption.

Checks on Linux in nix develop:
- cargo fmt --all -- --check
- cargo clippy --locked --workspace --all-targets -- -D warnings
- cargo test --locked --workspace --all-targets, with only the inherited
  TSUNAGI_CONTROL_SOCKET removed from the test environment
- git diff --cached --check

Initial full-suite runs failed six DNS readiness checks because the inherited
system socket path overrode their temporary state directories. Clearing that
environment variable resolves those failures without changing application code.
Root/network-dependent ignored tests and other operating systems were not run.
2026-10-14 23:28:53 +01:00

185 lines
6.5 KiB
Rust

//! Presets allow configuring an endpoint quickly with a chosen set of defaults.
//!
//! # Example
//!
//! ```no_run
//! # #[cfg(with_crypto_provider)]
//! # {
//! # async fn wrapper() -> n0_error::Result {
//! use iroh::{Endpoint, RelayMode, Watcher, endpoint::presets};
//!
//! let endpoint = Endpoint::builder(presets::N0).bind().await?;
//! # let _ = endpoint;
//! # Ok(())
//! # }
//! # }
//! ```
use crate::endpoint::Builder;
/// A reusable bundle of endpoint [`Builder`] configuration.
pub trait Preset {
/// Applies the configuration to the passed in [`Builder`].
fn apply(self, builder: Builder) -> Builder;
}
/// An empty preset that doesn't set anything on the builder.
///
/// This doesn't set mandatory builder options, so using this in
/// `Endpoint::bind(presets::Empty)` will always fail.
///
/// However, it can be useful, if you want control over all mandatory options
/// yourself, by using `Endpoint::builder(presets::Empty)`.
///
/// If you prefer a minimal version that is guaranteed to work, see the
/// [`Minimal`] preset.
#[derive(Debug, Copy, Clone, Default)]
pub struct Empty;
impl Preset for Empty {
fn apply(self, builder: Builder) -> Builder {
builder
}
}
/// A preset that is almost empty, besides setting mandatory options.
///
/// At the moment the only mandatory option to set on the endpoint builder is
/// [`Builder::crypto_provider`]. This preset makes a choice for that based on
/// the current set of enabled features in iroh, which is why it's only available
/// with the `tls-ring` or `tls-aws-lc-rs` feature flag.
///
/// It uses either [ring] or [aws-lc-rs], depending on which feature is enabled
/// on iroh (preferring ring if both are enabled).
///
/// [ring]: rustls::crypto::ring::default_provider
/// [aws-lc-rs]: rustls::crypto::aws_lc_rs::default_provider
#[cfg(with_crypto_provider)]
#[derive(Debug, Copy, Clone, Default)]
pub struct Minimal;
#[cfg(with_crypto_provider)]
impl Preset for Minimal {
fn apply(self, mut builder: Builder) -> Builder {
use std::sync::Arc;
#[cfg(feature = "tls-ring")]
{
builder = builder.crypto_provider(Arc::new(rustls::crypto::ring::default_provider()));
}
#[cfg(all(feature = "tls-aws-lc-rs", not(feature = "tls-ring")))]
{
builder =
builder.crypto_provider(Arc::new(rustls::crypto::aws_lc_rs::default_provider()));
}
builder
}
}
/// Configures the endpoint to use the n0 defaults
///
/// Currently this consists of
/// - the DNS Address Lookup service.
/// - the default relay servers provided by Number 0.
/// - setting the [`rustls::crypto::CryptoProvider`] to [ring] or [aws-lc-rs], depending
/// on which feature is enabled in iroh (preferring ring if both are enabled).
///
/// Due to the last point, this preset is only available with the `tls-ring` or
/// `tls-aws-lc-rs` feature enabled.
/// If you want to set your own crypto provider, we recommend copying the
/// implementation of this preset into your own and setting the appropriate crypto
/// provider there.
///
/// The default address lookup service publishes to and resolves from the
/// n0.computer dns server `iroh.link`.
///
/// This is equivalent to adding a [`crate::address_lookup::PkarrPublisher`],
/// a [`crate::address_lookup::PkarrResolver`], and (outside browsers) a
/// [`crate::address_lookup::DnsAddressLookup`], all configured to use the
/// n0.computer dns server.
///
/// This will by default use [`N0_DNS_PKARR_RELAY_PROD`].
/// When in tests, or when the `test-utils` feature is enabled, this will use the
/// [`N0_DNS_PKARR_RELAY_STAGING`].
///
/// [ring]: rustls::crypto::ring::default_provider
/// [aws-lc-rs]: rustls::crypto::aws_lc_rs::default_provider
/// [`N0_DNS_PKARR_RELAY_PROD`]: crate::address_lookup::N0_DNS_PKARR_RELAY_PROD
/// [`N0_DNS_PKARR_RELAY_STAGING`]: crate::address_lookup::N0_DNS_PKARR_RELAY_STAGING
#[cfg(with_crypto_provider)]
#[derive(Debug, Copy, Clone, Default)]
pub struct N0;
#[cfg(with_crypto_provider)]
impl Preset for N0 {
fn apply(self, mut builder: Builder) -> Builder {
use crate::{
address_lookup::{PkarrPublisher, PkarrResolver},
endpoint::default_relay_mode,
};
builder = Minimal.apply(builder);
builder = builder.address_lookup(PkarrPublisher::n0_dns());
// Resolve using HTTPS requests to our DNS server's /pkarr path.
builder = builder.address_lookup(PkarrResolver::n0_dns());
// Additionally resolve using DNS queries outside browsers.
#[cfg(not(wasm_browser))]
{
builder = builder.address_lookup(crate::address_lookup::DnsAddressLookup::n0_dns());
}
builder = builder.relay_mode(default_relay_mode());
builder
}
}
/// Configures the endpoint to use the n0 defaults, but with relay mode disabled.
///
/// Currently this consists of
/// - setting `RelayMode::Disabled`
/// - the DNS Address Lookup service, that publishes IP addresses rather than
/// relay urls.
/// - setting the [`rustls::crypto::CryptoProvider`] to [ring] or [aws-lc-rs], depending
/// on which feature is enabled in iroh (preferring ring if both are enabled).
///
/// Due to the last point, this preset is only available with the `tls-ring` or
/// `tls-aws-lc-rs` feature enabled.
/// If you want to set your own crypto provider, we recommend copying the
/// implementation of this preset into your own and setting the appropriate crypto
/// provider there.
///
/// The default address lookup service publishes to and resolves from the
/// n0.computer dns server `iroh.link`.
///
/// This is equivalent to adding a [`crate::address_lookup::PkarrPublisher`],
/// a [`crate::address_lookup::PkarrResolver`], and (outside browsers) a
/// [`crate::address_lookup::DnsAddressLookup`], all configured to use the
/// n0.computer dns server.
///
/// This will by default use [`N0_DNS_PKARR_RELAY_PROD`].
/// When in tests, or when the `test-utils` feature is enabled, this will use the
/// [`N0_DNS_PKARR_RELAY_STAGING`].
///
/// [ring]: rustls::crypto::ring::default_provider
/// [aws-lc-rs]: rustls::crypto::aws_lc_rs::default_provider
/// [`N0_DNS_PKARR_RELAY_PROD`]: crate::address_lookup::N0_DNS_PKARR_RELAY_PROD
/// [`N0_DNS_PKARR_RELAY_STAGING`]: crate::address_lookup::N0_DNS_PKARR_RELAY_STAGING
#[cfg(with_crypto_provider)]
#[derive(Debug, Copy, Clone, Default)]
pub struct N0DisableRelay;
#[cfg(with_crypto_provider)]
impl Preset for N0DisableRelay {
fn apply(self, builder: Builder) -> Builder {
use crate::RelayMode;
N0.apply(builder).relay_mode(RelayMode::Disabled)
}
}