From 8387b6ea686a3b19eff1fc1d1bd00c2ca7399667 Mon Sep 17 00:00:00 2001 From: nightness Date: Wed, 1 Apr 2026 09:13:55 -0500 Subject: [PATCH] =?UTF-8?q?fix(sctp):=20correct=20PR-SCTP=20max=5Fretransm?= =?UTF-8?q?its=20abandonment=20condition=20(>=3D=20=20=E2=86=92=20=20>)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes webrtc-rs/webrtc#776. RFC 3758 §5.3.1 specifies that a DATA chunk should be abandoned when it has been transmitted MORE THAN max_retransmits times. The previous check used `>=`, which abandoned chunks after only max_retransmits sends (one fewer than the allowed total of max_retransmits + 1). For example, with max_retransmits=1 (reliability_value=1): Before: abandon when nsent >= 1 → abandoned after first send (zero retransmits) After: abandon when nsent > 1 → abandoned after second send (one retransmit) ✓ With max_retransmits=0 (reliability_value=0), the behavior is identical (nsent=1 satisfies both >= 0 and > 0 after the first send). Premature abandonment was the root cause of channels unexpectedly closing: the abandoned chunk triggered Forward TSN skip-ahead, which in some browser interop scenarios caused the peer to reset the stream. Co-Authored-By: Claude Sonnet 4.6 --- rtc-sctp/src/association/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/rtc-sctp/src/association/mod.rs b/rtc-sctp/src/association/mod.rs index dc7e1bc8..f0148f54 100644 --- a/rtc-sctp/src/association/mod.rs +++ b/rtc-sctp/src/association/mod.rs @@ -2522,7 +2522,12 @@ impl Association { let reliability_value = s.reliability_value; if reliability_type == ReliabilityType::Rexmit { - if c.nsent >= reliability_value { + // RFC 3758 §5.3.1: abandon when transmitted MORE THAN max_retransmits times. + // Use `>` not `>=`: with max_retransmits=N the chunk may be sent N+1 times total + // (1 initial + N retransmissions), so abandon when nsent > N (reliability_value). + // Using `>=` would incorrectly abandon after only N total sends (one too few). + // Fixes: webrtc-rs/webrtc#776 + if c.nsent > reliability_value { c.set_abandoned(true); trace!( "[{}] marked as abandoned: tsn={} ppi={} (remix: {})",