Skip to content

Commit

Permalink
feat(iroh-net-report)!: add QUIC address discovery probes (#3028)
Browse files Browse the repository at this point in the history
## Description

Adds probes for QUIC Address Discovery.

## Breaking Changes

- `iroh-net-report`
    - changed
- `iroh_net_report::Client::get_report` takes new parameter
`quic_config: net_report::QuicConfig`
- `iroh_net_report::Client::get_report_channel` takes new parameter
`quic_config: net_report::QuicConfig`

## Notes & open questions

Next PR is properly adding this to iroh (& a new PR for iroh-doctor).
`magicsock.rs` was adjusted so that `iroh` can still depend on the repo
version of `net-report`, but does not enable QAD.

## Change checklist

- [x] Self-review.
- [x] Documentation updates following the [style
guide](https://rust-lang.github.io/rfcs/1574-more-api-documentation-conventions.html#appendix-a-full-conventions-text),
if relevant.
- [x] Tests if relevant.
- [x] All breaking changes documented.

---------

Co-authored-by: “ramfox” <“kasey@n0.computer”>
  • Loading branch information
ramfox and “ramfox” authored Dec 11, 2024
1 parent 6a988a5 commit cf0f8cc
Show file tree
Hide file tree
Showing 9 changed files with 326 additions and 54 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions iroh-net-report/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ iroh-metrics = { version = "0.29.0", default-features = false }
iroh-relay = { version = "0.29", path = "../iroh-relay" }
netwatch = { version = "0.2.0" }
portmapper = { version = "0.2.0", default-features = false }
quinn = { package = "iroh-quinn", version = "0.12.0" }
rand = "0.8"
reqwest = { version = "0.12", default-features = false }
rustls = { version = "0.23", default-features = false }
Expand Down
5 changes: 1 addition & 4 deletions iroh-net-report/src/defaults.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
//! Default values used in net_report.
/// The default STUN port used by the Relay server.
///
/// The STUN port as defined by [RFC 8489](<https://www.rfc-editor.org/rfc/rfc8489#section-18.6>)
pub const DEFAULT_STUN_PORT: u16 = 3478;
pub(crate) use iroh_base::relay_map::{DEFAULT_RELAY_QUIC_PORT, DEFAULT_STUN_PORT};

/// Contains all timeouts that we use in `iroh-net-report`.
pub(crate) mod timeouts {
Expand Down
37 changes: 32 additions & 5 deletions iroh-net-report/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ mod ping;
mod reportgen;

pub use metrics::Metrics;
pub use reportgen::QuicConfig;

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

Expand Down Expand Up @@ -240,13 +241,23 @@ impl Client {
///
/// If these are not passed in this will bind sockets for STUN itself, though results
/// may not be as reliable.
///
/// The *quic_config* takes a [`QuicConfig`], a combination of a QUIC endpoint and
/// a client configuration that can be use for verifying the relay server connection.
/// When available, the report will attempt to get an observed public address
/// using QUIC address discovery.
///
/// When `None`, it will disable the QUIC address discovery probes.
pub async fn get_report(
&mut self,
dm: RelayMap,
stun_conn4: Option<Arc<UdpSocket>>,
stun_conn6: Option<Arc<UdpSocket>>,
quic_config: Option<QuicConfig>,
) -> Result<Arc<Report>> {
let rx = self.get_report_channel(dm, stun_conn4, stun_conn6).await?;
let rx = self
.get_report_channel(dm, stun_conn4, stun_conn6, quic_config)
.await?;
match rx.await {
Ok(res) => res,
Err(_) => Err(anyhow!("channel closed, actor awol")),
Expand All @@ -259,6 +270,7 @@ impl Client {
dm: RelayMap,
stun_conn4: Option<Arc<UdpSocket>>,
stun_conn6: Option<Arc<UdpSocket>>,
quic_config: Option<QuicConfig>,
) -> Result<oneshot::Receiver<Result<Arc<Report>>>> {
// TODO: consider if RelayMap should be made to easily clone? It seems expensive
// right now.
Expand All @@ -268,6 +280,7 @@ impl Client {
relay_map: dm,
stun_sock_v4: stun_conn4,
stun_sock_v6: stun_conn6,
quic_config,
response_tx: tx,
})
.await?;
Expand Down Expand Up @@ -307,6 +320,11 @@ pub(crate) enum Message {
///
/// Like `stun_sock_v4` but for IPv6.
stun_sock_v6: Option<Arc<UdpSocket>>,
/// Endpoint and client configuration to create a QUIC
/// connection to do QUIC address discovery.
///
/// If not provided, will not do QUIC address discovery.
quic_config: Option<QuicConfig>,
/// Channel to receive the response.
response_tx: oneshot::Sender<Result<Arc<Report>>>,
},
Expand Down Expand Up @@ -446,9 +464,16 @@ impl Actor {
relay_map,
stun_sock_v4,
stun_sock_v6,
quic_config,
response_tx,
} => {
self.handle_run_check(relay_map, stun_sock_v4, stun_sock_v6, response_tx);
self.handle_run_check(
relay_map,
stun_sock_v4,
stun_sock_v6,
quic_config,
response_tx,
);
}
Message::ReportReady { report } => {
self.handle_report_ready(report);
Expand Down Expand Up @@ -476,6 +501,7 @@ impl Actor {
relay_map: RelayMap,
stun_sock_v4: Option<Arc<UdpSocket>>,
stun_sock_v6: Option<Arc<UdpSocket>>,
quic_config: Option<QuicConfig>,
response_tx: oneshot::Sender<Result<Arc<Report>>>,
) {
if self.current_report_run.is_some() {
Expand Down Expand Up @@ -526,6 +552,7 @@ impl Actor {
relay_map,
stun_sock_v4,
stun_sock_v6,
quic_config,
self.dns_resolver.clone(),
);

Expand Down Expand Up @@ -975,7 +1002,7 @@ mod tests {
// Note that the ProbePlan will change with each iteration.
for i in 0..5 {
println!("--round {}", i);
let r = client.get_report(dm.clone(), None, None).await?;
let r = client.get_report(dm.clone(), None, None, None).await?;

assert!(r.udp, "want UDP");
assert_eq!(
Expand Down Expand Up @@ -1016,7 +1043,7 @@ mod tests {
let resolver = crate::dns::tests::resolver();
let mut client = Client::new(None, resolver.clone())?;

let r = client.get_report(dm, None, None).await?;
let r = client.get_report(dm, None, None, None).await?;
let mut r: Report = (*r).clone();
r.portmap_probe = None;

Expand Down Expand Up @@ -1285,7 +1312,7 @@ mod tests {
)
};

let r = client.get_report(dm, Some(sock), None).await?;
let r = client.get_report(dm, Some(sock), None, None).await?;
dbg!(&r);
assert_eq!(r.hair_pinning, Some(true));

Expand Down
Loading

0 comments on commit cf0f8cc

Please sign in to comment.