fix: harden NACK send/receive (bounded index, resend cooldown, recovery)#33
Open
langhuihui wants to merge 1 commit into
Open
fix: harden NACK send/receive (bounded index, resend cooldown, recovery)#33langhuihui wants to merge 1 commit into
langhuihui wants to merge 1 commit into
Conversation
Bound the NACK send buffer with a seq index, suppress duplicate resends within 25ms, cap receiver NACK gaps at 128 newest holes, and only count previously NACKed seqs as recovered. RTX wrap path remains unchanged. Co-authored-by: Cursor <cursoragent@cursor.com>
langhuihui
force-pushed
the
feat/nack-hardening
branch
from
July 20, 2026 02:01
2ee7961 to
9551184
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.
Motivation
NACK recovery worked but had several sharp edges under lossy browser WHEP:
VecDequeand scanned linearly on every NACK seq.get_recovered_count()counted any late packet, not only ones we had NACKed.This PR hardens those paths without changing the A2 RTX wrap/unwrap behavior (already on
mainvia #32 / 0.3.92). Rebased onto currentmainso it keeps the lock-freertx_ssrc_fasthot path.Design
Sender (
DefaultRtpSenderNackHandler)NackSendBuffer: FIFO order +HashMap<u16, RtpPacket>bounded by
nack_buffer_size/ buildernack(buffer_size).packets_for_nack(seqs, now)applies:NACK_RESEND_COOLDOWN)wrap_rtx_packetwhen
set_rtx(Some(...))is active; otherwise clone-resend. Still usesrtx_config+rtx_ssrc_fastfrom 0.3.92.Receiver (
DefaultRtpReceiverNackHandler)MAX_RECEIVER_NACK_GAP(128), keeping the most recentmissing sequences when the gap is larger.
pending_nacks; only those seqs incrementnack_recovered_countwhen they arrive.Behavior when RTX is not negotiated
Unchanged aside from the hardening above: still clone-resends original RTP from the
bounded buffer.
Test coverage
max_size; evicted seqs are not retransmittablecargo test --lib -- nack_→ 10;-- rtx→ 24)Open questions for maintainers
Limitations / follow-ups
std::time::Instant), not RTT-adaptive.