docs: say that RtpWrite's seq_no is extended and drives the SRTP ROC - #1036
Open
AlexanderSerbul wants to merge 1 commit into
Open
AlexanderSerbul wants to merge 1 commit into
AlexanderSerbul wants to merge 1 commit into
Conversation
The upper bits of seq_no become the SRTP rollover counter, which is never transmitted. A receiver seeing a stream for the first time starts at ROC 0 (RFC 3711 3.3.1), so a stream whose first packet is at or above 65_536 is encrypted with a key the receiver will not derive: the packets arrive, the transport counts the bytes, and no inbound RTP stream ever appears. This is easy to hit when forwarding, where it is tempting to pass an incoming stream's extended sequence number straight through: a subscriber joining a publisher that has been sending for over 65_536 packets then starts past the first rollover and hears silence, while everyone who joined earlier is fine. Docs only, no behaviour change. Co-Authored-By: Claude Opus 5 <[email protected]>
Owner
|
Hi! Thanks for bringing this up. This might be problem rather than just a documentation error. I'm a bit unsure. You could easily see SFU situations where you have an incoming, long running source stream forked out to many clients that come and go. The source goes into ROC, and then clients join. The actual wire RTP will course not start at a high ROC, but, do we expect str0m to internally be consistent with the high ROC start or not? @pthatcher what would your gut feeling be? |
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.
Docs only — no behaviour change.
RtpWrite::newdocumentsseq_noas "Sequence number to use for this packet". In direct RTP mode that number is also what str0m hands toprotect_rtpas the SRTP index, so its upper bits become the rollover counter (roc = srtp_index >> 16).The ROC is never transmitted, and a receiver seeing a stream for the first time starts at ROC 0 (RFC 3711 §3.3.1). So a stream whose first packet is at or above 65_536 gets encrypted with a key the receiver will not derive. The failure is silent and looks nothing like a crypto problem: the packets arrive,
candidate-pair/transportbyte counters climb,packetsDiscardedstays 0, andinbound-rtpis simply empty.This is easy to hit in an SFU, where passing an incoming stream's extended sequence number straight through looks like the neutral choice. It isn't: a subscriber joining a publisher that has been sending for more than 65_536 packets starts past the first rollover and gets nothing, while everyone who joined earlier keeps working — so it reads as a routing or NAT bug for a good while. Rebasing the outgoing numbering by a whole number of rollovers fixes it and leaves the wire sequence number untouched.
When str0m generates sequence numbers itself (media API) it starts from
SeqNo::default(), so the contract is met automatically; it is only the direct RTP path where the caller owns it. This patch just writes that down.🤖 Generated with Claude Code