Repository navigation
fix(dialog): end the session on a never-ACKed re-INVITE 2xx in ClientInviteDialog - #185
Merged
shenjinti merged 1 commit intoOct 8, 2026
Conversation
…InviteDialog The deprecated ClientInviteDialog has its own handle_reinvite, which missed the teardown that InviteDialog and ServerInviteDialog apply (RFC 3261 13.3.1.4): when the callee re-INVITEs a UAC dialog handled through the wrapper and never ACKs the 2xx, the 2xx was retransmitted until 64*T1 and then nothing happened. The dialog stayed Confirmed, with no event and no BYE. Track the 2xx and the ACK as the other two handlers do and call end_session_without_ack, so the dialog ends with TerminatedReason::Timeout and a BYE.
This was referenced Oct 7, 2026
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 #184.
Problem
#149 added the never-ACKed 2xx teardown to
InviteDialog::handle_reinviteandServerInviteDialog::handle_reinvite, and #169 added theackedguard to both, but the deprecatedClientInviteDialog::handle_reinvite(src/dialog/client_dialog.rs:664-684) has its own copy and got neither. A UAC dialog handled throughClientInviteDialog::handlewhose re-INVITE 2xx is never ACKed retransmits the 2xx until 64*T1 and then staysConfirmed, with noTerminatedand no BYE.Spec
Fix
ClientInviteDialog::handle_reinvitenow does what the other two handlers do (invite_dialog.rs:899-923,server_dialog.rs:852-876): after the application's final response it records whether it was a 2xx, setsackedon the matching ACK, and callsself.inner.end_session_without_ack(tx, answered_2xx && !acked). The helper is the existing one from #149: it does nothing unless a 2xx was sent, the transaction ended and the dialog is not already terminated; otherwise it notifiesTerminated(Timeout)and sends a BYE. +9 lines insrc/dialog/client_dialog.rs, no other src change.Unchanged on purpose:
answered_2xxis false), as in the other two handlers.InviteDialogandServerInviteDialog, the wrapper does not notifyConfirmedwhen the re-INVITE's ACK arrives (its stored state staysConfirmed, sinceUpdatedis event-only). That predates this teardown and is not changed here.Contract / coverage
What a re-INVITE from the peer, handled through
ClientInviteDialog::handle, ends in:Confirmed, no BYETerminated(Timeout)+ BYE after 64*T1, asInviteDialogTests
src/dialog/tests/test_uas_ack_timeout.rs: a helperlegacy_client_dialog_reinvite(ack)sets up a UAC dialog withDialogLayer::do_inviteagainst a raw UDP peer (the file's short timers: T1 20 ms, 64*T1 1.28 s), with an incoming loop that converts each matched dialog withClientInviteDialog::try_fromand calls itshandle. The peer sends a re-INVITE, the application answers 200, and the peer either never ACKs or ACKs once the 2xx arrived.test_unacked_reinvite_2xx_ends_the_session_on_a_legacy_client_dialog: the 2xx is retransmitted, a BYE from the dialog's local tag comes no earlier than 64*T1 - T1 after the answer, and the dialog notifiesTerminated(Timeout).test_acked_reinvite_keeps_a_legacy_client_dialog: no BYE, noTerminated, the dialog is still confirmed.On
main(92cec74) the first fails and the second passes:Checks
cargo test --features bench: 408 lib tests passed, 0 failed (406 onmainplus the two new ones), and 65 doc tests passed. Plaincargo testpasses too. The new tests passed 5 runs in a row.cargo check --no-default-features --features platform-embassy: no warnings, the same as onmain.cargo clippy --features bench --all-targets: the same output as onmain, none in the changed code. (Onmainit stops at aclippy::never_looperror insrc/dialog/tests/test_refer_notify.rs:98, unrelated to this PR; with-A clippy::never_loopthe warnings are the same as onmain.)cargo fmt --check: clean.