Repository navigation
Conversation
RFC 3261 §15.1.1: the session ends once the BYE is passed to the client transaction, and the dialog ends on a 481, a 408 or no response. `bye_with_headers` notified `Terminated` only after the BYE transaction returned Ok. When it returned an error (the target locator fails, or a 401/407 to the BYE cannot be answered) the dialog stayed `Confirmed`, and callers that remove the dialog on `Terminated` kept it forever. `DialogInner::send_bye`, used by `InviteDialog` and both deprecated wrappers, notifies `Terminated` (`UacBye` / `UasBye`, as before) whatever the transaction returns and still returns its error.
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 #179.
Problem
bye_with_headersreturns early on an error from the BYE's transaction (invite_dialog.rs:448,client_dialog.rs:181,server_dialog.rs:375), before it transitions toTerminated. When the target locator fails (transaction.rs:274, returned atdialog.rs:1160) or a 401/407 to the BYE cannot be answered (dialog.rs:1279-1280),bye()returnsErr, the dialog staysConfirmedand noTerminatedis notified. Applications that remove the dialog onTerminated, as thedo_invitedocs ask (invitation.rs:655-668), keep it forever.Spec
Fix
A new
DialogInner::send_bye(request, reason)(src/dialog/dialog.rs) runs the BYE's transaction, then transitions toTerminated(reason)whatever it returned, then returns the transaction's result.InviteDialog::bye_with_headersand the deprecatedClientInviteDialog/ServerInviteDialog::bye_with_headerscall it instead ofdo_request(..)?followed by the transition. The reasons are the existing ones, unchanged:UacByefor a client dialog,UasByefor a server dialog (InviteDialogpicks by role as before; each wrapper keeps its own).Unchanged on purpose:
Ok.make_request) still returns before any transaction exists; the dialog staysConfirmedand the caller may retry.send_byetransitions only afterdo_requestreturns.end_session_without_ack(fix: end the session when a UAS 2xx to an INVITE is never ACKed #149) transitions toTerminated(Timeout)before its BYE, andbye_2xx_after_cancel/bye_if_2xxrun on an INVITE that was already abandoned.Contract / coverage
What
bye()(andbye_with_headers/bye_with_reason, all three types) does once the BYE is handed to its transaction:bye()returnsOk(())Terminated(UacBye / UasBye)Ok(())TerminatedOk(())TerminatedOk(())TerminatedErr(..)TerminatedErr, staysConfirmedErr(..)TerminatedErr, staysConfirmedThe 481, 408 and no-response rows and the two error rows are in the test below. The write-failure and lookup-failure rows follow from the transaction, which reports them as a local 503 (
transaction.rs:352-361) or entersCallingwith its timers anyway (transaction.rs:336-339); this PR does not touch that path.Behaviour change for callers: an
Errfrombye()no longer means the dialog is still usable. It reports that the BYE could not be completed; the dialog isTerminatedeither way, andTerminatedhas been notified. Code that retriedbye()after anErrnow gets theOkno-op of a terminated dialog. Code that already treated the return ofbye()as the end of the call is not affected.A 401/407 to the BYE without a credential already notifies
Terminated(ProxyAuthRequired)insend_dialog_request, andbye()then notifiesTerminated(UacBye)too. That double notification is onmainalready and is not changed here; #148 drops the second one (checked below).Tests
src/dialog/tests/test_client_dialog.rs:test_bye_terminates_the_dialog_whatever_the_outcome. A UAC dialog is set up withDialogLayer::do_inviteagainst a raw UDP peer (short timers: T1 10 ms, 64*T1 640 ms; aFlakyLocatorthat starts failing on demand). Then onebye()per row, and for each the test asserts theTerminatednotifications (exactly one, with the expected reason), that the dialog is terminated, and whetherbye()returned an error:Ok,[UacBye](pins the current behaviour).Err,[UacBye].InviteDialog,ClientInviteDialogandServerInviteDialog(the deprecated wrappers are driven over the same dialog):Err,[UacBye]/[UasBye].On
main(5ef8ea6) it fails at the first new row:Row by row on
main(assertions turned into prints):Checks
cargo test --features bench: 386 lib tests passed, 0 failed (385 onmainplus the new one), and 65 doc tests passed. Plaincargo testpasses too. The new test passed 20 runs in a row.cargo check --no-default-features --features platform-embassy: the same output 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.)rustfmt --checkon the changed files: clean.Terminatedonce.