Repository navigation
fix(dialog): get_client_dialog_by_call_id returns only UAC dialogs - #176
Merged
shenjinti merged 1 commit intoOct 7, 2026
Merged
Conversation
Since the unified `Dialog::Invite(InviteDialog)` (0.6.0) the lookup
matches every INVITE dialog with the Call-ID, so a B2BUA that keeps the
Call-ID across its legs gets the inbound (UAS) leg back as a client
dialog. Check the role, as the documentation says ("client-side INVITE
dialogs (UAC)") and as `Dialog::ClientInvite` did in 0.5.x.
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 #175.
Problem
get_client_dialog_by_call_id(src/dialog/dialog_layer.rs:452) is documented to return the client-side (UAC) INVITE dialogs with a Call-ID. Since the unifiedDialog::Invite(InviteDialog)(0.6.0) it matches everyDialog::Invitewith that Call-ID (line 456), so when both legs of a call share the Call-ID (a B2BUA or proxy that keeps it), the inbound UAS leg is returned as a client dialog.Spec
dialog_layer.rs:444): "Returns all client-side INVITE dialogs (UAC) that share the given Call-ID." In 0.5.x it returnedVec<ClientInviteDialog>and matched onlyDialog::ClientInvite.Fix
The lookup also checks
client_dlg.role() == TransactionRole::Client. Nothing else changes.Contract / coverage
get_client_dialog_by_call_id(call_id)returns every INVITE dialog withrole() == TransactionRole::Clientand that Call-ID: early UAC dialogs (registered bydo_invite/do_invite_asyncunder their early id), confirmed ones, and every one of several UAC dialogs with that Call-ID when more than one is registered (the forking case the doc comment describes). Dialogs restored withrestore_from_snapshotkeep their role (Dialog::from_inner(inner.role, ..),dialog_layer.rs:497), so a restored UAC dialog is found and a restored UAS dialog is not. UAS dialogs are still found byget_dialog/match_dialog.Other
DialogLayerlookups, checked and not changed:get_or_create_server_subscription,get_or_create_server_publication,get_or_create_client_publication,get_or_create_client_subscription: they match their own typedDialogvariant, so the role is already part of the match.get_dialog,get_dialog_with,match_dialog,remove_dialog: role-agnostic by contract (they returnDialog), as in 0.5.x.get_or_create_server_invite, for a request with a To tag, returns whichever INVITE dialog is stored under the id derived from the request, which can be a UAC dialog. Left as is on purpose: that id is the request's Call-ID with To tag as local tag and From tag as remote tag (RFC 3261 §12.2.2), so a match on a UAC dialog means the request is an in-dialog request of that dialog (for example a re-INVITE from the callee of an outgoing call), andInviteDialog::handlehandles it for both roles. Refusing it would answer 481 to a valid re-INVITE for code that sends every INVITE throughget_or_create_server_invite(assrc/bin/bench_ua.rs:99does).Behaviour change: a caller that used
get_client_dialog_by_call_idto find the UAS dialog of a call no longer gets it. No caller in the repository, examples orbench_uauses it.Tests
src/dialog/tests/test_dialog_layer.rs:test_get_client_dialog_by_call_id_returns_only_uac_dialogs: oneDialogLayerwith an inbound INVITE answered byget_or_create_server_inviteand an outbounddo_invite_asyncwith the same Call-ID.get_client_dialog_by_call_idreturns exactly the UAC dialog, and the UAS dialog is still found byget_dialog.On
main(5ef8ea6) it fails:Checks
cargo test --features bench: 386 lib tests passed, 0 failed (385 onmainplus the new one), and 65 doc tests passed. Plaincargo testpasses too.cargo check --no-default-features --features platform-embassy: no warnings, 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.)rustfmt --checkon the changed files: clean.