[wip] fix(iroh): survive home relay changes on relay-only connections - #4435
Draft
Frando wants to merge 5 commits into
Draft
[wip] fix(iroh): survive home relay changes on relay-only connections#4435Frando wants to merge 5 commits into
Frando wants to merge 5 commits into
Conversation
|
Documentation for this PR has been generated and is available at: https://n0-computer.github.io/iroh/pr/4435/docs/iroh/ Last updated: 2026-07-27T08:21:38Z |
relay_teardown_failover gives the peers disjoint relay maps: the server holds a fast and a slow relay (homing on the fast one), the client its own unrelated relay. The connection runs over the server's home relay, which is torn down mid-connection. Address lookup runs against an iroh-dns-server in the lab (new linux-only dev-dependency): the server publishes over pkarr HTTP, the client resolves the _iroh TXT records on port 53, the only UDP port its firewall allows. Util grows a named relay spawner and the dns-server spawner. The test needs the failover fixes in the next commits to pass.
Frando
force-pushed
the
fix/relay-failover
branch
2 times, most recently
from
July 24, 2026 12:12
a0f8a26 to
dc90a4e
Compare
When the home relay connection drops, incremental net reports run only QAD probes. If UDP is unavailable those measure nothing, so the report returns no relay latencies and no other configured relay is promoted to home; the endpoint retries the dead relay for up to the full-report interval (5 minutes) instead of failing over. The socket actor now watches the home relay connection. On loss it schedules a full net report, deferred by two seconds so a brief reconnect does not trigger one, and rate-limited so a still-down relay does not force back-to-back reports. A full report re-runs the HTTPS probes and lets a reachable relay be promoted.
active_relay_handle_for_endpoint queries every tracked active relay via HasEndpointRoute before creating a new relay connection. The outer reconnect backoff loop slept via a bare time::sleep that never polled prio_inbox, so a query sent to a relay mid-backoff (e.g. one that just died) sat unanswered until that unrelated backoff elapsed, directly gating unrelated new relay connections. sleep_backoff now answers HasEndpointRoute(false) immediately while still counting down the delay, mirroring run_dialing's existing pattern. Path establishment after a relay teardown is now consistently ~1-1.5s instead of up to 15s+ in traced runs.
The relay path of a connection runs over the remote's home relay; the peers do not share relay maps. When that relay dies, the remote fails over its home relay and republishes its endpoint info, but the client kept retrying the dead relay: nothing re-resolved the remote or opened a path over its new home relay. Opening a path over our own home relay cannot help, since the remote is not connected to it. Detection uses the relay transport's own knowledge: each ActiveRelayActor broadcasts RelayConnEvent::Lost/Restored for its relay. Lost is debounced to skip spurious disconnects: an established connection dropping retries immediately without emitting anything, so the event only fires once a reconnect attempt (several round trips of connect+handshake) has also failed. On Lost, a RemoteStateActor whose connection has no way around that relay forces an address lookup via trigger_address_lookup(true): not running starts it immediately; already running queues a retry for when the current attempt finishes. The retry repeats with backoff (500ms up to 5s) until a replacement path establishes, the relay connection is restored, or the connection closes. Selection also keys on the same transport state: lost relays are passed into the path selection context and their paths marked as transport-down (PathSelectionData::transport_down). The selector only uses such a path as a last resort, so the replacement relay path wins selection despite the dead path's better (stale) RTT, after which the dead path is closed as a redundant relay path (apply_selected_path, generalized from the existing IP-only redundant-path closing). For the case without any transport signal - the remote lost *its* relay connection while ours is fine - the path idles out (keep-alives stop being acknowledged) and noq abandons it; a connection whose last path is abandoned also forces the lookup. Uses noq from the Frando/abandon-retransmit branch (PR pending upstream): closing the dead relay path declares its in-flight data lost so it retransmits over the replacement path, instead of stalling until the PATH_ABANDON round trip completes.
Matches the existing maybe_next pattern for the address lookup stream: the receiver is dropped once the channel reports closed, making the closed state unrepresentable instead of tracked alongside.
7 tasks
Frando
force-pushed
the
fix/relay-failover
branch
from
July 27, 2026 08:19
dc90a4e to
f6fa4b4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
The first commit adds a patchbay test that fails on main: On a relay-only connection with no working IP path, we destroy connectivity to the relay. The test fails on main. However, this doesn't have to be, we can make the connection survive: Breaking the relay connection could trigger a net report, chose a new home relay, and handle the new relay URL to the client over addr lookup, so that it can open a new path over the new relay.
This PR explores how to we can do this.
In its current form, it does this:
Depends on n0-computer/noq#770
Includes #4444
Breaking Changes
Notes & open questions
Draft. The fix was mostly done by an AI tool and still needs to be reviewed.
Change checklist
proposed change and wrote an as clear and concise description as
they could.
intented effect.