Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion iroh/src/endpoint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,10 @@ pub use self::{
VarIntBoundsExceeded, WriteError, Written,
},
};
pub use crate::portmapper::PortmapperConfig;
#[cfg(not(wasm_browser))]
use crate::socket::transports::IpConfig;
use crate::socket::transports::TransportConfig;
pub use crate::{net_report::NetReportConfig, portmapper::PortmapperConfig};

/// Builder for [`Endpoint`].
///
Expand Down Expand Up @@ -127,6 +127,7 @@ pub struct Builder {
hooks: EndpointHooksList,
transport_bias: socket::transports::TransportBiasMap,
portmapper_config: PortmapperConfig,
net_report_config: NetReportConfig,
crypto_provider: Option<Arc<rustls::crypto::CryptoProvider>>,
}

Expand Down Expand Up @@ -193,6 +194,7 @@ impl Builder {
hooks: Default::default(),
transport_bias: Default::default(),
portmapper_config: Default::default(),
net_report_config: Default::default(),
crypto_provider: None,
}
}
Expand Down Expand Up @@ -255,6 +257,7 @@ impl Builder {
hooks: self.hooks,
transport_bias: self.transport_bias,
portmapper_config: self.portmapper_config,
net_report_config: self.net_report_config,
static_config,
};

Expand Down Expand Up @@ -742,6 +745,18 @@ impl Builder {
self
}

/// Configures the net report.
///
/// The net report component is responsible for figuring out if and how the endpoint is connected to the internet.
/// It does this by doing various probes to the configured relay servers to get public addresses, NAT behaviour, and
/// relay latencies. In addition it tries to detect captive portals.
///
/// Some non-essential features of the net report component can be disabled via this configuration.
pub fn net_report_config(mut self, config: NetReportConfig) -> Self {
self.net_report_config = config;
self
}

/// Adds a custom transport
#[cfg(feature = "unstable-custom-transports")]
pub fn add_custom_transport(mut self, factory: Arc<dyn CustomTransport>) -> Self {
Expand Down
2 changes: 1 addition & 1 deletion iroh/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ pub use iroh_base::{
pub use iroh_relay::dns;
pub use iroh_relay::{RelayConfig, RelayMap, endpoint_info};
pub use n0_watcher::Watcher;
pub use net_report::{Report as NetReport, TIMEOUT as NET_REPORT_TIMEOUT};
pub use net_report::{NetReportConfig, Report as NetReport, TIMEOUT as NET_REPORT_TIMEOUT};

#[cfg(any(test, feature = "test-utils"))]
pub mod test_utils;
54 changes: 54 additions & 0 deletions iroh/src/net_report.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,56 @@ pub use self::{
};
pub(crate) use self::{options::Options, reportgen::QuicConfig};

/// Configuration for the net report component.
///
/// Controls which probes and checks are performed when generating network reports.
/// All options default to `true`.
#[derive(Debug, Clone)]
#[non_exhaustive]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

pub struct NetReportConfig {
/// Run HTTPS latency probes against relay servers.
///
/// HTTPS latency probes perform an empty HTTPS GET request to each configured
/// relay server and measure latency.
///
/// They are performed in addition to the QUIC address discovery (QAD) probes.
/// They are the only way to detect relay latencies and thus the preferred relay
/// in networks that do not allow QUIC traffic.
///
/// Disabling them is harmless on networks that do allow QUIC traffic, but will
/// completely prevent finding the home relay on networks that do block QUIC.
pub https_probes: bool,

/// Check for captive portals when generating the first report.
///
/// This is done by accessing a well-known URL that is available on each relay
/// server, `/generate_204`. If a GET request to this URL returns anything else
/// but a 204 No Content response, we assume we are behind a captive portal.
///
/// When we have detected that we are behind a captive portal, we try to contact
/// the relay servers more frequently in case the captive portal status changes.
pub captive_portal_check: bool,
}

impl NetReportConfig {
/// Creates a minimal configuration that disables all optional probes and checks.
pub fn minimal() -> Self {
Self {
https_probes: false,
captive_portal_check: false,
}
}
}

impl Default for NetReportConfig {
fn default() -> Self {
Self {
https_probes: true,
captive_portal_check: true,
}
}
}

const FULL_REPORT_INTERVAL: Duration = Duration::from_secs(5 * 60);
const ENOUGH_ENDPOINTS: usize = 3;

Expand All @@ -100,6 +150,8 @@ pub(crate) struct Client {
qad_conns: QadConns,
#[cfg(not(wasm_browser))]
tls_config: rustls::ClientConfig,
/// Whether to check for captive portals.
captive_portal_check: bool,
/// A collection of previously generated reports.
///
/// Sometimes it is useful to look at past reports to decide what to do.
Expand Down Expand Up @@ -239,6 +291,7 @@ impl Client {
qad_conns: QadConns::default(),
#[cfg(not(wasm_browser))]
tls_config: opts.tls_config,
captive_portal_check: opts.user_config.captive_portal_check,
}
}

Expand Down Expand Up @@ -294,6 +347,7 @@ impl Client {
self.reports.last.clone(),
self.relay_map.clone(),
self.probes.clone(),
self.captive_portal_check,
if_state.clone(),
shutdown_token.child_token(),
#[cfg(not(wasm_browser))]
Expand Down
40 changes: 23 additions & 17 deletions iroh/src/net_report/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub(crate) use imp::Options;
mod imp {
use std::collections::BTreeSet;

use crate::net_report::{QuicConfig, probes::Probe};
use crate::net_report::{NetReportConfig, QuicConfig, probes::Probe};

/// Options for running probes
///
Expand All @@ -21,13 +21,16 @@ mod imp {
pub(crate) quic_config: Option<QuicConfig>,
/// TLS config for HTTPS probes.
pub(crate) tls_config: rustls::ClientConfig,
/// User-facing configuration.
pub(crate) user_config: NetReportConfig,
}

impl Options {
pub(crate) fn new(tls_config: rustls::ClientConfig) -> Self {
Self {
quic_config: None,
tls_config,
user_config: NetReportConfig::default(),
}
}
/// Enable quic probes
Expand All @@ -36,6 +39,12 @@ mod imp {
self
}

/// Set the net report configuration.
pub(crate) fn net_report_config(mut self, config: NetReportConfig) -> Self {
self.user_config = config;
self
}

/// Turn the options into set of valid protocols
pub(crate) fn as_protocols(&self) -> BTreeSet<Probe> {
let mut protocols = BTreeSet::new();
Expand All @@ -47,7 +56,9 @@ mod imp {
protocols.insert(Probe::QadIpv6);
}
}
protocols.insert(Probe::Https);
if self.user_config.https_probes {
protocols.insert(Probe::Https);
}
protocols
}
}
Expand All @@ -57,42 +68,37 @@ mod imp {
mod imp {
use std::collections::BTreeSet;

use crate::net_report::Probe;
use crate::net_report::{NetReportConfig, Probe};

/// Options for running probes (in browsers).
///
/// Only HTTPS probes are supported in browsers.
/// These are run by default.
#[derive(Debug, Clone)]
pub(crate) struct Options {
/// Enable https probes
///
/// On by default
pub(crate) https: bool,
/// User-facing configuration.
pub(crate) user_config: NetReportConfig,
}

impl Default for Options {
fn default() -> Self {
Self { https: true }
Self {
user_config: NetReportConfig::default(),
}
}
}

impl Options {
/// Create an [`Options`] that disables all probes
pub(crate) fn disabled() -> Self {
Self { https: false }
}

/// Enable or disable https probe
pub(crate) fn https(mut self, enable: bool) -> Self {
self.https = enable;
/// Set the net report configuration.
pub(crate) fn net_report_config(mut self, config: NetReportConfig) -> Self {
self.user_config = config;
self
}

/// Turn the options into set of valid protocols
pub(crate) fn as_protocols(&self) -> BTreeSet<Probe> {
let mut protocols = BTreeSet::new();
if self.https {
if self.user_config.https_probes {
protocols.insert(Probe::Https);
}
protocols
Expand Down
8 changes: 7 additions & 1 deletion iroh/src/net_report/reportgen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,10 +115,12 @@ impl Client {
///
/// The actor starts running immediately and only generates a single report, after which
/// it shuts down. Dropping this handle will abort the actor.
#[allow(clippy::too_many_arguments)]
pub(super) fn new(
last_report: Option<Report>,
relay_map: RelayMap,
protocols: BTreeSet<Probe>,
captive_portal_check: bool,
if_state: IfStateDetails,
shutdown_token: CancellationToken,
#[cfg(not(wasm_browser))] socket_state: SocketState,
Expand All @@ -130,6 +132,7 @@ impl Client {
last_report,
relay_map,
protocols,
captive_portal_check,
#[cfg(not(wasm_browser))]
socket_state,
#[cfg(not(wasm_browser))]
Expand Down Expand Up @@ -168,6 +171,9 @@ struct Actor {
/// configuration for that protocol.
protocols: BTreeSet<Probe>,

/// Whether to check for captive portals.
captive_portal_check: bool,

/// Any socket-related state that doesn't exist/work in browsers
#[cfg(not(wasm_browser))]
socket_state: SocketState,
Expand Down Expand Up @@ -276,7 +282,7 @@ impl Actor {
// delay by a bit to wait for UDP QAD to finish, to avoid the probe if
// it's unnecessary.
#[cfg(not(wasm_browser))]
if self.last_report.is_none() {
if self.captive_portal_check && self.last_report.is_none() {
// Even if we're doing a non-incremental update, we may want to try our
// preferred relay for captive portal detection.
let preferred_relay = self
Expand Down
10 changes: 8 additions & 2 deletions iroh/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ pub(crate) struct Options {
pub(crate) hooks: EndpointHooksList,
pub(crate) transport_bias: TransportBiasMap,
pub(crate) portmapper_config: portmapper::PortmapperConfig,
pub(crate) net_report_config: crate::net_report::NetReportConfig,

/// Static configuration for the endpoint.
pub(crate) static_config: StaticConfig,
Expand Down Expand Up @@ -812,6 +813,7 @@ impl EndpointInner {
hooks,
transport_bias,
portmapper_config,
net_report_config,
static_config,
} = opts;

Expand Down Expand Up @@ -967,11 +969,13 @@ impl EndpointInner {
ipv4: true,
ipv6: has_ipv6_transport,
});
net_report::Options::new(tls_config.clone()).quic_config(qad_config)
net_report::Options::new(tls_config.clone())
.quic_config(qad_config)
.net_report_config(net_report_config)
};

#[cfg(wasm_browser)]
let net_report_config = net_report::Options::default();
let net_report_config = net_report::Options::default().net_report_config(net_report_config);

let net_reporter = net_report::Client::new(
#[cfg(not(wasm_browser))]
Expand Down Expand Up @@ -1935,6 +1939,7 @@ mod tests {
hooks: Default::default(),
transport_bias: Default::default(),
portmapper_config: Default::default(),
net_report_config: Default::default(),
static_config,
}
}
Expand Down Expand Up @@ -2343,6 +2348,7 @@ mod tests {
hooks: Default::default(),
transport_bias: Default::default(),
portmapper_config: Default::default(),
net_report_config: Default::default(),
static_config,
};
let sock = EndpointInner::bind(opts).await?;
Expand Down
Loading