Repository navigation
Ignore a duplicated server answer - #1047
Open
xianshijing-lk wants to merge 1 commit into
Open
xianshijing-lk wants to merge 1 commit into
xianshijing-lk wants to merge 1 commit into
Conversation
setRemoteDescription rejected answers carrying an older offer id, but a second copy of the answer for the current offer passed straight through. A proxy duplicating the signal message, or a server retry, applied the same answer twice - the second time with no local offer left to answer, an invalid transition that reported an error for a renegotiation that had actually succeeded. Track the offer whose answer was applied and the offer whose answer is being applied, and drop a repeat of either. The in-flight claim is taken before the apply suspends, so a copy arriving mid-apply is caught too, and released however the apply ends so a genuine retry still works. Port of livekit/client-sdk-js#2114. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
xianshijing-lk
requested review from
MaxHeimbrock and
davidliu
as code owners
October 23, 2026 23:10
🦋 Changeset detectedLatest commit: f31dff8 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
|
Diffuse output: AARJAR |
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.
Port of livekit/client-sdk-js#2114.
The bug
PeerConnectionTransport.setRemoteDescriptionalready rejected answers carrying an older offer id:But a second copy of the answer for the current offer satisfies
currentOfferId == offerId, so it fell straight through topeerConnection.setRemoteDescription. A proxy duplicating the signal message, or a server retry, therefore applied the same answer twice. The second apply happens with no local offer left to answer — an invalid transition — so a renegotiation that had actually succeeded came back reporting an error.Repro
Added
duplicateAnswerForTheSameOfferIsIgnoredtoRTCEngineMockE2ETest: complete one publisher renegotiation, then deliver a second answer carrying the same offer id. The payload differs only so the test can tell whether it reached the peer connection.Against the unfixed code:
The fix
Track two things, mirroring upstream:
answeredOfferId— the offer whose answer was applied. Set only after a successful apply, so a retry after a genuine failure still goes through.answerInFlight— the offer whose answer is being applied right now. Claimed before the apply suspends, so a copy arriving mid-apply is caught too, and released in afinallyhowever the apply ends.The decision itself is a pure
isDuplicateAnswerfunction, matching the JS SDK's exported helper, with the legacy unnumbered-answer path falling back to the signaling state (inSTABLEthere is no local offer pending).Verification
:livekit-android-test:testReleaseUnitTestgreen. The new behavioural test fails before the change and passes after;IsDuplicateAnswerTestcovers the eight edge cases (in-flight, already-applied, retry-after-failure, new offer, and the two unnumbered-answer paths). The pre-existingofferIdMismatchIsIgnoredandofferIdMismatchButZeroIsAcceptedtests still pass, so the stale-offer and legacy behaviour are unchanged.Note
This SDK has no deferred-initial-offer (offer-with-join), so the upstream helper's
hasPendingInitialOfferparameter has no analogue here and is omitted — the local offer is always set immediately after it is created.🤖 Generated with Claude Code