Skip to content

MeshCore bearer: end-to-end reliability over the flood (#26) - #163

Merged
M0LTE merged 1 commit into
masterfrom
meshcore-reliability
Jul 1, 2026
Merged

MeshCore bearer: end-to-end reliability over the flood (#26)#163
M0LTE merged 1 commit into
masterfrom
meshcore-reliability

Conversation

@M0LTE

@M0LTE M0LTE commented Jul 1, 2026

Copy link
Copy Markdown
Collaborator

End-to-end reliability (#26) for the MeshCore bearer. The channel is a fire-and-forget flood with no link ACK, so DAPPS adds its own — datagram-style, not a session (no handshake, no window, no ordered stream).

How it works

  • The receiver ACKs any data message addressed to it (a tiny mc-ack control broadcast).
  • The sender tracks unacked messages and resends on exponential backoff until acked or its lifetime (min(TTL, 5 min)) expires.
  • The receiver dedups by message id, so a resend after a lost ACK is delivered to the app once (idempotent).
  • Resends/ACKs are ordinary channel traffic — governor + adaptive controls apply.
  • Config: DAPPS_MESHCORE_RELIABLE_DELIVERY (default true).

Adversarial-review fixes folded in

  • Idempotency was actually missing — DAPPS's inbox flood-dedup is gated on FloodHopsRemaining, which these messages don't carry, so resends were double-delivering. Added an explicit receiver-side delivered-ids dedup.
  • Resends no longer burn backoff slots when refused by congestion/budget (DueResends peeks; MarkResent advances only on a real send).
  • TxBudget refund is token-based (concurrent sends can't refund each other's reservations); ToFrames nonce made thread-safe (now called concurrently by OMM send + resend loop + inbound ACKs).
  • Transport _compressed map no longer leaks for incomplete reassemblies.
  • ACKs consumed unconditionally; failed ACK sends logged.

Validation

  • 21 MeshCore unit tests; full solution builds clean.
  • On-air soak (two Heltec V3s, 40% induced loss): delivered == distinct (no duplicate app delivery), lost messages recovered by resend+ACK, nothing expired.

Builds on #162. Inert unless MeshCoreEnabled=true.

🤖 Generated with Claude Code

https://claude.ai/code/session_01KLbwvhE2cKCe8WPZNg8k17

Channel messages are fire-and-forget floods with no link ACK, so DAPPS adds its
own datagram-style reliability (NOT a session): the receiver ACKs any data message
addressed to it (a tiny mc-ack control broadcast), the sender resends unacked
messages on exponential backoff until acked or their lifetime expires, and the
receiver dedups by message id so a resend after a lost ACK is delivered to the app
only once. Resends/ACKs are ordinary channel traffic (governor + adaptive apply).

- MeshCoreReliability: pending-table bookkeeping (Track/OnAck/DueResends/MarkResent/
  DropExpired) + ACK build/detect.
- MeshCoreInbound: receiver-side idempotency (delivered-ids dedup), unconditional
  ACK consumption, ACK generation for messages addressed to us.
- MeshCoreCompanionBackhaul: SendCoreAsync + ResendAsync (bypasses coalescing);
  tracks sent data messages.
- MeshCoreBearer: resend loop; DAPPS_MESHCORE_RELIABLE_DELIVERY config.

Fixes from an adversarial review of the reliability code:
- Idempotency was missing (the existing inbox flood-dedup is gated on
  FloodHopsRemaining, which these messages don't carry) -> added receiver dedup.
- Resends no longer burn backoff slots when refused by congestion/budget
  (DueResends peeks; MarkResent advances only on a real send).
- TxBudget refund is now token-based (concurrent sends can't refund each other's
  reservations); ToFrames nonce made thread-safe (now called concurrently).
- Transport _compressed map no longer leaks entries for incomplete reassemblies.
- ACKs consumed unconditionally; failed ACK sends logged.

Tests: 21 MeshCore unit tests. On-air soak with 40% induced loss: delivered==distinct
(no duplicate app delivery), lost messages recovered by resend+ACK, nothing expired.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KLbwvhE2cKCe8WPZNg8k17
@M0LTE
M0LTE merged commit ab0ed85 into master Jul 1, 2026
4 checks passed
@M0LTE
M0LTE deleted the meshcore-reliability branch July 1, 2026 07:09
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.

1 participant