Repository navigation
fix(dialog): BYE a forked 2xx's dialog (RFC 3261 §13.2.2.4) - #181
Merged
Merged
Conversation
Every 2xx to the INVITE with a new To tag establishes its own dialog. The transaction already re-ACKs a forked 2xx with its own tag and remote target (#172), but the Accepted-window drainer dropped it: no dialog was created for the branch and no BYE was ever sent, so the forked callee kept retransmitting its 2xx until it gave up. The drainer now inspects every message the client INVITE transaction delivers after confirmation: a 2xx whose To tag differs from the confirmed dialog's is ended with a BYE built from that response's own Contact (remote target) and Record-Route (route set), CSeq continuing the forked dialog's. The confirmed dialog's state is untouched, no dialog is registered for the branch, and no state is notified.
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.
Fixes #150.
Problem
PR #172 fixed the ACK half of #150: a forked 2xx (To tag different from the confirmed dialog's) is now re-ACKed with its tag, remote target and route set. But the issue's second half remained: the Accepted-window drainer (
invitation.rs,do_inviteanddo_invite_async) drainedtx.receive()into the void — no dialog was created for the forked branch and no BYE was ever sent, so the forked callee kept retransmitting its 2xx until it gave up, believing the call was up.Spec
Fix
The drainer inspects every message the client INVITE transaction delivers after confirmation:
InviteDialog::end_forked_branch(src/dialog/invite_dialog.rs) ignores non-2xx and 2xx retransmissions with the confirmed tag, and hands a forked 2xx (different tag) toDialogInner::bye_forked_branch(src/dialog/dialog.rs), which builds the BYE from that response: R-URI = its Contact, route set = its Record-Route (reversed), To = its To (the forked tag), From/Call-ID unchanged, CSeq =increment_local_seq()(INVITE + 1 right after confirmation, unique on the shared counter), and sends it throughdo_request.Unchanged on purpose:
bye_forked_branchbuilds the request standalone instead of going throughmake_request, unlikebye_2xx_after_cancelwhich operates on an abandoned dialog).Behaviour change
A forked callee now receives ACK + BYE and stops retransmitting. An application that previously observed the dangling branch only as 2xx retransmission noise now sees a clean BYE on the wire. No public API change.
Tests
src/dialog/tests/test_forked_2xx_bye.rs:test_forked_2xx_is_byed_without_touching_the_confirmed_dialog— a UAC dialog viado_inviteagainst a raw UDP peer (T1 10 ms, 64*T1 640 ms):tag-a→ dialogConfirmed, notification stream drained.tag-band its own Contact (bob-b).tag-b, R-URI = the forked Contact,CSeq: 2 BYE, same Call-ID.Confirmed, no dialog registered fortag-b, the confirmed dialog stillConfirmed, and a normalbye()still ends it withtag-a.On main (3bdd74c) it fails at the forked-branch BYE:
Checks
cargo test --features bench: 399 lib tests passed, 0 failed (398 on main plus the new one), 65 doc tests passed. Plaincargo testpasses too. The new test passed 5 runs in a row.cargo check --no-default-features --features platform-embassy: same as main.cargo fmt --all -- --check: clean.cargo clippy --features bench --all-targets: no diagnostics in the changed files; the only error is the pre-existingclippy::never_loopintest_refer_notify.rs:98(present on main).