Skip to content

daemon: event-driven path reset on rekey give-up (corrects #415, verified live)#416

Merged
TeoSlayer merged 1 commit into
mainfrom
fix/t2-eventdriven-rekey-giveup-reset
Jul 22, 2026
Merged

daemon: event-driven path reset on rekey give-up (corrects #415, verified live)#416
TeoSlayer merged 1 commit into
mainfrom
fix/t2-eventdriven-rekey-giveup-reset

Conversation

@TeoSlayer

Copy link
Copy Markdown
Collaborator

#415 didn't work — a live test proved it. It polled the rekey-gave-up state from the path watchdog, but a desynced peer isn't Ready, so ReadyPeerIDs() (what the watchdog scans) never includes it → 0 firings across dozens of real give-ups. The unit test passed only on an impossible injected combination.

This is the correct fix: an event-driven onGaveUp hook fired from the keyexchange retransmit loop at the give-up site → daemon resetPeerPath (fresh resolve + re-punch + PILA — the only thing that recovers a desync; plain rekey-retransmit resends to the same stale endpoint forever). Per-peer 30s cooldown; async off the rekey goroutine. Reverts #415's ineffective poll.

Verified LIVE on a real NAT'd laptop: give-up → full path reset in ~1.2s, reproduced across peers 17461 and 16392 — vs the prior indefinite silent drop (the 'no reply' symptom). -race green.

🤖 Generated with Claude Code

…fied live)

#415 tried to recover the T2 desync by polling the rekey-gave-up state
from the path watchdog. A LIVE test (2026-07-22) proved it never fired:
a desynced peer has no usable key, so it is not Ready, so ReadyPeerIDs()
— the set the watchdog scans — excludes it entirely. 0 firings across
dozens of real give-ups. (The unit test passed only because it injected
a Ready peer + gave-up state, a combination that can't occur.)

Correct fix: event-driven. Add an onGaveUp hook fired from the keyexchange
retransmit loop at the exact give-up site, wired through the tunnel to a
daemon handler (onRekeyGaveUp) that runs resetPeerPath — the only thing
that recovers a desync, because it re-resolves a FRESH endpoint and
re-punches (plain rekey-retransmit just resends to the same stale cached
endpoint forever). Per-peer 30s cooldown prevents a persistently-offline
peer from storming resolves; reset runs async (registry I/O) off the
rekey loop goroutine.

Reverts #415's ineffective path-watchdog poll. Verified LIVE on a real
NAT'd laptop: give-up -> full path reset (fresh resolve + punch + PILA)
in ~1.2s, reproduced across peers 17461 and 16392, vs the prior
indefinite silent-drop. This is the 'no reply on whatever' fix.

Tests: TestOnRekeyGaveUpResetsWithCooldown (hook resets + cooldown
suppresses a second give-up). pkg/daemon + keyexchange green under -race.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@TeoSlayer
TeoSlayer merged commit 5b3c3bb into main Jul 22, 2026
15 of 16 checks passed
@TeoSlayer
TeoSlayer deleted the fix/t2-eventdriven-rekey-giveup-reset branch July 22, 2026 20:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants