Skip to content

res_pjsip_sdp_rtp: Use auto-selected transport bind address for RTP#1848

Open
arcivanov wants to merge 1 commit into
asterisk:22from
arcivanov:issue_1847
Open

res_pjsip_sdp_rtp: Use auto-selected transport bind address for RTP#1848
arcivanov wants to merge 1 commit into
asterisk:22from
arcivanov:issue_1847

Conversation

@arcivanov
Copy link
Copy Markdown
Contributor

@arcivanov arcivanov commented Apr 1, 2026

When a PJSIP endpoint does not explicitly set transport, the RTP
socket binds to [::] (or 0.0.0.0) instead of the transport's bind
address. This is because create_rtp() only resolves the transport
via a sorcery lookup on session->endpoint->transport, which is empty
when the transport is auto-selected.

On a multi-homed host or NAT gateway whose transport binds to a
specific interface, the wildcard-bound RTP socket causes the kernel to
select a source IP that may conflict with conntrack DNAT entries for
inbound RTP, causing MASQUERADE to silently remap the RTP source port.
The remote end receives RTP from an unexpected port and drops it,
resulting in one-way audio with no errors logged by Asterisk.

When no explicit transport is configured and ICE is not in use,
determine the transport type from the dialog's target URI and acquire
the transport via pjsip_tpmgr_acquire_transport(). If the
transport's bind address is a specific (non-wildcard) address, use it
for RTP. When the transport binds to a wildcard address (0.0.0.0 or
[::]), the RTP socket is left on the wildcard as well, matching the
behaviour of the explicit-transport code path and preserving
dual-stack operation.

When ICE is enabled the wildcard bind is left as-is since ICE needs
to discover candidates on all interfaces.

Co-Authored-By: Claude Opus 4.6 (1M context) noreply@anthropic.com

UserNote: When a PJSIP endpoint does not have an explicit transport
configured, ICE is disabled, and the auto-selected transport binds to
a specific (non-wildcard) address, the RTP socket now binds to that
address instead of the wildcard. This fixes one-way audio on
multi-homed hosts and NAT gateways where the wildcard bind caused the
kernel to select an incorrect source address for outbound RTP.

Fixes: #1847

Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Checklist Complete

@github-actions github-actions Bot added the has-pr-checklist A PR Checklist is present on the PR label Apr 1, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

Workflow Check completed successfully

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

Workflow Check completed successfully

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

Workflow Check failed
22-local_iax2_mgr: FAILED TEST: channels/local/local_optimize_away
22-pjs2: FAILED TEST: channels/pjsip/dtmf_info_fallback
22-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_recognition

@arcivanov
Copy link
Copy Markdown
Contributor Author

This has been verified to work with the patch on top of 22.8.2.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 1, 2026

Workflow Check failed
22-ari1: FAILED TEST: rest_api/external_interaction/blind_transfer/stasis_bridge_to_non_stasis_app
22-local_iax2_mgr: FAILED TEST: channels/local/local_optimize_away
22-pjs2: FAILED TEST: channels/pjsip/dtmf_info_fallback
22-pjs2: FAILED TEST: channels/pjsip/dtmf_sdp/dtmf_sdp_recognition

Comment thread res/res_pjsip_sdp_rtp.c Outdated
@arcivanov
Copy link
Copy Markdown
Contributor Author

will do

@arcivanov
Copy link
Copy Markdown
Contributor Author

@gtjoseph why would IAX2 fail with SIP changes is beyond me

@gtjoseph
Copy link
Copy Markdown
Member

gtjoseph commented Apr 9, 2026

@gtjoseph why would IAX2 fail with SIP changes is beyond me

local_iax2_mgr is just the name of the group of tests. In this case, it contains tests for channels/local, channels/iax2 and manager.

When a PJSIP endpoint does not explicitly set `transport`, the RTP
socket binds to `[::]` (or `0.0.0.0`) instead of the transport's bind
address. This is because `create_rtp()` only resolves the transport
via a sorcery lookup on `session->endpoint->transport`, which is empty
when the transport is auto-selected.

On a multi-homed host or NAT gateway whose transport binds to a
specific interface, the wildcard-bound RTP socket causes the kernel to
select a source IP that may conflict with conntrack DNAT entries for
inbound RTP, causing MASQUERADE to silently remap the RTP source port.
The remote end receives RTP from an unexpected port and drops it,
resulting in one-way audio with no errors logged by Asterisk.

When no explicit transport is configured and ICE is not in use,
determine the transport type from the dialog's target URI and acquire
the transport via `pjsip_tpmgr_acquire_transport()`. If the
transport's bind address is a specific (non-wildcard) address, use it
for RTP. When the transport binds to a wildcard address (0.0.0.0 or
[::]), the RTP socket is left on the wildcard as well, matching the
behaviour of the explicit-transport code path and preserving
dual-stack operation.

When ICE is enabled the wildcard bind is left as-is since ICE needs
to discover candidates on all interfaces.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

UserNote: When a PJSIP endpoint does not have an explicit `transport`
configured, ICE is disabled, and the auto-selected transport binds to
a specific (non-wildcard) address, the RTP socket now binds to that
address instead of the wildcard. This fixes one-way audio on
multi-homed hosts and NAT gateways where the wildcard bind caused the
kernel to select an incorrect source address for outbound RTP.

Fixes: asterisk#1847
Copy link
Copy Markdown

@github-actions github-actions Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Checklist Complete

@github-actions github-actions Bot added the has-pr-checklist A PR Checklist is present on the PR label Apr 9, 2026
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 9, 2026

Workflow Check completed successfully

@arcivanov
Copy link
Copy Markdown
Contributor Author

Reconfirmed working on top of LTS 22.2.8.

@arcivanov arcivanov requested a review from gtjoseph April 9, 2026 23:45
@gtjoseph gtjoseph dismissed github-actions[bot]’s stale review April 10, 2026 00:21

Pull Request Checklist Complete

@gtjoseph gtjoseph added cherry-pick-test Trigger dry run of cherry-picks and removed has-pr-checklist A PR Checklist is present on the PR labels Apr 10, 2026
@github-actions github-actions Bot added cherry-pick-testing-in-progress Cherry-Pick tests in progress and removed cherry-pick-test Trigger dry run of cherry-picks labels Apr 10, 2026
@gtjoseph gtjoseph dismissed their stale review April 10, 2026 00:21

Test now passing

@github-actions github-actions Bot added cherry-pick-checks-failed Cherry-Pick checks failed and removed cherry-pick-testing-in-progress Cherry-Pick tests in progress labels Apr 10, 2026
@github-actions
Copy link
Copy Markdown

Workflow CPCheck failed
20-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_stasis_app
23-ari1: FAILED TEST: rest_api/external_interaction/blind_transfer/stasis_bridge_to_non_stasis_app
master-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_non_stasis_app

@github-actions
Copy link
Copy Markdown

Workflow CPCheck failed
20-ari1: FAILED TEST: rest_api/external_interaction/attended_transfer/stasis_bridge_to_stasis_app
23-ari1: FAILED TEST: rest_api/external_interaction/blind_transfer/stasis_bridge_to_non_stasis_app

@gtjoseph gtjoseph requested a review from jcolp April 10, 2026 12:35
@github-actions github-actions Bot added the cherry-pick-checks-passed Cherry-Pick checks passed label Apr 10, 2026
@github-actions
Copy link
Copy Markdown

Workflow CPCheck completed successfully

@gtjoseph gtjoseph dismissed jcolp’s stale review April 10, 2026 12:56

Significant changes since last approval.

@arcivanov
Copy link
Copy Markdown
Contributor Author

FYI: Tested the patch with 22.9.0, no problems, no one-way audio: https://copr.fedorainfracloud.org/coprs/karellen/asterisk/

Comment thread res/res_pjsip_sdp_rtp.c
pjsip_sip_uri *sip_uri;
pjsip_transport_type_e type;

sip_uri = pjsip_uri_get_uri(session->inv_session->dlg->target);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has the case been tested with this where a SIP INVITE is sent to a hostname that does SRV/NAPTR and resolves down to multiple targets, and then goes from IPv6 to IPv4 as a result of failure/failover? Would that result in the SDP containing IPv6 despite being an IPv4 target? Or worse - do we update the SDP elsewhere under the assumption that it is wildcard, but it's not so audio would fail?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I definitely didn't test that scenario. Let me see what I can do.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants