Skip to content

fix: build the Via of in-dialog requests from the transport they are sent on - #152

Open
tgeorge06 wants to merge 1 commit into
restsend:mainfrom
tgeorge06:fix/in-dialog-via-transport
Open

tgeorge06 wants to merge 1 commit into
restsend:mainfrom
tgeorge06:fix/in-dialog-via-transport

Conversation

@tgeorge06

Copy link
Copy Markdown

Fixes #151.

Problem

DialogInner::make_request builds the Via of every in-dialog request (BYE, re-INVITE, UPDATE, INFO, PRACK, …) with get_via(None), i.e. from the endpoint's first listener. On an endpoint that binds UDP first and TCP as well, a dialog established over TCP sends its BYE and re-INVITE over the TCP flow (RFC 5626 affinity) or towards a ;transport=tcp route / remote target, but with Via: SIP/2.0/UDP …. Peers may drop the mismatched request or send the response over UDP.

The initial INVITE already picks the listener matching the target transport (make_invite_request), and REGISTER does the same since 0c2dcc1. In-dialog requests did not.

Reproduction

New src/dialog/tests/test_in_dialog_via.rs (real UDP + TCP listeners, raw TCP peer; the two failing cases use only the public API, the locator and dial-back guards use crate internals): a UAC endpoint with UDP bound first and TCP second establishes a call over TCP, then sends a re-INVITE and a BYE.

  • over the reused TCP flow (no route set): fails on main with the UDP Via above;
  • towards a ;transport=tcp;lr Record-Route: fails on main the same way;
  • with a TargetLocator configured: the Via stays the default (the locator decides the transport at send time) — passes on main and on this branch;
  • dial-back retry of a server dialog to its recorded source address: the Via follows that address's transport.

Fix

When the caller pins no address, make_request takes the transport of, in order: the affinity connection, the outbound proxy, the first route, the remote target — and uses the matching listener for the Via. UDP, an unknown transport, no matching listener, or a configured target locator keeps the previous behaviour. When a server dialog's request falls back to the dial-back address, its Via is rebuilt with the same branch for that address's transport. EndpointInner::locator becomes pub(crate) so the dialog layer can see whether a locator is set. No public API change.

Checks (on main @ 3ea35cd)

  • Red: with the src/ change reverted and the new test kept, cargo test --lib test_in_dialog_via → 2 failed (a re-INVITE sent over TCP must carry a TCP Via, got: SIP/2.0/UDP …, for the reused-flow and the ;transport=tcp Record-Route cases); the locator and dial-back guards pass.
  • Green: cargo test → 336 lib + 65 doc passed, 0 failed. rustfmt --check clean on the changed files.
  • No public API change (EndpointInner::locator becomes pub(crate) so the dialog layer can see whether a locator is configured).

…sent on

DialogInner::make_request built the Via of every in-dialog request
(BYE, re-INVITE, UPDATE, INFO, PRACK, ...) with get_via(None), i.e. from
the endpoint's first listener. On an endpoint that binds UDP first and
TCP as well, a dialog established over TCP therefore sent its BYE and
re-INVITE over the TCP flow (affinity) or towards a ;transport=tcp route
or remote target, but with a "Via: SIP/2.0/UDP" header. RFC 3261
§18.1.1 requires the Via to name the transport the request is sent
over; peers may drop the mismatched request or answer it over UDP.

The initial INVITE already picks the listener that matches the target
transport (make_invite_request), and REGISTER does the same since
0c2dcc1. Do the same for in-dialog requests when the caller pins no
address: take the transport of the affinity connection, else of the
outbound proxy, else of the first route, else of the remote target,
and use the matching listener. UDP, an unknown transport, or a target
locator (which decides the transport at send time) keeps the previous
behaviour. When a server dialog's request falls back to the dial-back
address, its Via is rebuilt (same branch) for that address's transport.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

In-dialog requests carry a UDP Via when sent over TCP (RFC 3261 §18.1.1)

1 participant