Skip to content

bug: Internet discovery performed despite static provider/local relay #3741

@jost-s

Description

@jost-s

Describe the bug

When connecting endpoints with a local discovery provider or relay server, the internet discovery is performed anyway, leading to an extended connection time.

Disabling the computer's internet connection produces the expected behavior, where connection succeeds within milliseconds.

Sample code with static provider:

#[tokio::test]
async fn iroh() {
    let protocol = b"test";
    let static_disco = StaticProvider::new();
    let alice_ep = Endpoint::empty_builder(RelayMode::Disabled)
        .discovery(static_disco.clone())
        .alpns(vec![protocol.to_vec()])
        .bind()
        .await
        .unwrap();

    static_disco.add_endpoint_info(alice_ep.addr());

    let bob_ep = Endpoint::empty_builder(RelayMode::Disabled)
        .discovery(static_disco.clone())
        .alpns(vec![protocol.to_vec()])
        .bind()
        .await
        .unwrap();

    static_disco.add_endpoint_info(bob_ep.addr());

    let bob_addr = bob_ep.addr();

    let start = std::time::Instant::now();
    println!("connecting now");
    let accept_task =
        tokio::spawn(
            async move { bob_ep.accept().await.unwrap().await.unwrap() },
        );

    let conn = alice_ep.connect(bob_addr, protocol).await.unwrap();

    accept_task.await.unwrap();
    println!("it took {:?}", start.elapsed());
}

Sample code with local relay server:

#[tokio::test]
async fn iroh_relay() {
    let protocol = b"test";

    let (relay_map, _relay_url, relay_server) =
        run_relay_server().await.unwrap();

    let alice_ep =
        Endpoint::empty_builder(RelayMode::Custom(relay_map.clone()))
            .insecure_skip_relay_cert_verify(true)
            .clear_discovery()
            .alpns(vec![protocol.to_vec()])
            .bind()
            .await
            .unwrap();

    let bob_ep = Endpoint::empty_builder(RelayMode::Custom(relay_map))
        .insecure_skip_relay_cert_verify(true)
        .clear_discovery()
        .alpns(vec![protocol.to_vec()])
        .bind()
        .await
        .unwrap();

    let bob_addr = bob_ep.addr();

    let start = std::time::Instant::now();
    println!("connecting now");
    let accept_task =
        tokio::spawn(
            async move { bob_ep.accept().await.unwrap().await.unwrap() },
        );

    let conn = alice_ep.connect(bob_addr, protocol).await.unwrap();

    accept_task.await.unwrap();
    println!("it took {:?}", start.elapsed());
}

STR:

  • Run tests with access to internet enabled and look at logs and time it took to establish connection
  • Disable internet connection
  • Run tests again and observe different behavior

Relevant Logs

Probing when a local relay server is part of the test:

2025-12-06T03:46:55.439472Z DEBUG actor:reportgen-actor: iroh::net_report::reportgen: reportstate actor starting
2025-12-06T03:46:55.439506Z DEBUG actor:reportgen-actor: iroh::net_report::reportgen: local interface details if_state=IfStateDetails { have_v4: true, have_v6: true }
...
2025-12-06T03:46:55.844243Z DEBUG actor:reportgen-actor: iroh::net_report::reportgen: all regular probes done
2025-12-06T03:46:55.844273Z DEBUG actor:reportgen-actor: iroh::net_report::reportgen: reportgen actor finished
2025-12-06T03:46:55.844376Z DEBUG actor:reportgen-actor:run-probe{proto=Https delay=400ms relay=RelayConfig { url: RelayUrl("http://127.0.0.1:49499/"), quic: Some(RelayQuicConfig { port: 7842 }) }}: hyper_util::client::legacy::pool: pooling idle connection for ("http", 127.0.0.1:49499)
2025-12-06T03:46:55.844487Z DEBUG actor:reportgen-actor: iroh::net_report::reportgen: all regular probes done
2025-12-06T03:46:55.844504Z DEBUG actor:reportgen-actor: iroh::net_report::reportgen: reportgen actor finished
2025-12-06T03:46:58.441095Z DEBUG actor: iroh::net_report: probe v4 timed out
2025-12-06T03:46:58.441204Z DEBUG actor: iroh::net_report: generated report in 3002ms report=Report { udp_v4: false, udp_v6: false, mapping_varies_by_dest_ipv4: None, mapping_varies_by_dest_ipv6: None, preferred_relay: Some(RelayUrl("http://127.0.0.1:49499/")), relay_latency: RelayLatencies { ipv4: {}, ipv6: {}, https: {RelayUrl("http://127.0.0.1:49499/"): 4.859834ms} }, global_v4: None, global_v6: None, captive_portal: None }
2025-12-06T03:46:58.441313Z DEBUG actor: iroh::magicsock: direct addr update done (Periodic)
2025-12-06T03:46:58.441508Z DEBUG actor: iroh::net_report: probe v4 timed out
2025-12-06T03:46:58.441557Z DEBUG actor: iroh::net_report: generated report in 3002ms report=Report { udp_v4: false, udp_v6: false, mapping_varies_by_dest_ipv4: None, mapping_varies_by_dest_ipv6: None, preferred_relay: Some(RelayUrl("http://127.0.0.1:49499/")), relay_latency: RelayLatencies { ipv4: {}, ipv6: {}, https: {RelayUrl("http://127.0.0.1:49499/"): 3.812625ms} }, global_v4: None, global_v6: None, captive_portal: None }
2025-12-06T03:46:58.441579Z DEBUG actor: iroh::magicsock: direct addr update done (Periodic)
...
2025-12-06T03:46:58.441978Z  INFO relay-actor: iroh::magicsock::transports::relay::actor: home is now relay http://127.0.0.1:49499/, was None

Expected behavior

The static discovery provider/local home relay server is used to discover the other endpoint's address and connection establishment proceeds without querying internet discovery services or relay servers.

Iroh

Version:

iroh v0.95.1
├── iroh feature "default"
│   └── kitsune2_transport_iroh v0.4.0-dev.0 (/Users/jost/Desktop/holochain/kitsune2/crates/transport_iroh)
│       └── kitsune2_transport_iroh feature "default" (command-line)
└── iroh feature "metrics"
    └── iroh feature "default" (*)

Endpoint configuration:

Endpoint::empty_builder(RelayMode::Custom(relay_map))

and

Endpoint::empty_builder(RelayMode::Disabled).discovery(discovery)

respectively

Platform(s)
Desktop:

  • OS: macOS/Debian Linux
  • Version macOS 15.7.2/Debian 13

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingc-iroh

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions