Repository navigation
Port the link watchdog - #101
jamiecounsell wants to merge 2 commits into
Conversation
validate_link_proof() had its signature check stubbed to false, so a proof for a packet sent over a link was never accepted. The packet was never marked delivered and its delivery callback never ran. This restores the check from the Python reference. link is passed as const Link& but Link::validate() isn't const, so it validates through a copy of the link (copies share the same state). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rUgoKJdB4U8fNS9HybY8S
The link watchdog was still marked as TODO. Without it, a link request with no reply stayed pending forever, initiators never sent keepalives, and dead links were never found stale or closed. The watchdog is now one pass of the reference loop per link, run from Transport::jobs() for each pending and active link: pending/handshake links time out, active links send keepalives and go stale, and stale links close after the grace period. The watchdog depends on three values that nothing was setting, so this sets them: - the keepalive interval, derived from the RTT when a link comes up, as in the reference (adds KEEPALIVE_MIN/KEEPALIVE_MAX; KEEPALIVE keeps its value) - the time the last keepalive was sent - the time of the last proof received on the link The watchdogs run after the job loop, not inside it. jobs() sets _jobs_running while its loop runs, and outbound() sleeps until it's cleared. The watchdog sends packets (keepalives, link closes), so calling it inside the loop would deadlock: outbound() waits for the loop to finish, and the loop waits for outbound(). The existing resource watchdogs had the same problem when re-requesting a missing part, so they move after the loop too. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_019rUgoKJdB4U8fNS9HybY8S
|
Thanks for this, and for the detailed write-up and the on-hardware testing against Python RNS. Porting the link watchdog fills a real gap, and running it after the job loop to avoid the Before this can go in, a few things need sorting out:
|
Note: this PR is stacked on #99
The link watchdog was still marked as TODO. Without it, a link request with no reply stayed pending forever, initiators never sent keepalives, and dead links were never found stale or closed.
I ported the reference loop as one pass per link, run from
Transport::jobs()for each pending and active link:The watchdog depends on three values that nothing was setting, so this sets them:
KEEPALIVE_MIN/KEEPALIVE_MAX;KEEPALIVEkeeps its value)The watchdogs run after the job loop, not inside it.
jobs()sets_jobs_runningwhile its loop runs, andoutbound()sleeps until it's cleared. The watchdog sends packets (keepalives, link closes), so calling it inside the loop would deadlock:outbound()waits for the loop to finish, and the loop waits foroutbound(). The existing resource watchdogs had the same problem when re-requesting a missing part, so I moved them after the loop too.Testing: running in SolarOS on a ThinkNode M9 (ESP32-S3, ESP-IDF) against Python RNS nodes over LoRa, exchanging LXMF messages. Native tests pass, and the series builds for
ttgo-lora32-v21andwiscore_rak4631.Fixes #93