Revert unsafe from_user removal, use PAI/RPID for per-call outbound CID

PJSIP's From-header username comes exclusively from the endpoint's
static from_user — it never falls back to the channel's CALLERID(num).
With from_user unset, Asterisk fell back to its own hardcoded default
("asterisk"), which the provider doesn't recognize as an account DID
and rejected outright: every outbound call went straight to busy with
the callee never ringing.

Restore the static from_user (required for the provider to accept the
call at all) and instead relay the per-call CALLERID(num) — personal_did
or the shared DID — via send_pai/send_rpid, which populate the
P-Asserted-Identity/Remote-Party-ID headers from the live channel
Caller-ID independent of from_user. This is the standard mechanism for
presenting a per-call Caller-ID over a trunk with one fixed From user.
This commit is contained in:
Claude
2026-07-25 18:08:12 +00:00
parent 95b52d606f
commit c53060ee89
+32 -14
View File
@@ -219,7 +219,7 @@ _pstn_ensure_live_includes() {
# identify/endpoint objects needed per IP, unlike the older chan_sip
# peer-per-source-IP pattern some providers' sample configs still show.
_pstn_write_pjsip_include() {
local FILE="$1" SERVER="$2" SERVER_IPS="$3"
local FILE="$1" SERVER="$2" SERVER_IPS="$3" DID="$4"
cat > "$FILE" << 'EOF'
; SIP PSTN trunk — IP authentication, no password stored (see
; docs/pstn-calling-voipms-plan.md). Regenerated by services/pstn-trunk.sh —
@@ -242,17 +242,32 @@ _pstn_write_pjsip_include() {
; sends (P-Asserted-Identity/Remote-Party-ID, in addition to the From
; header) for this trunk, so real inbound Caller-ID reaches the dialplan.
;
; No static from_user= on the endpoint below either, for the same reason
; on the outbound side. Confirmed live: a static from_user pinned to the
; shared trunk DID silently wins over CALLERID(num) — PJSIP only falls
; back to the channel's caller ID number for the From-header username when
; from_user is unset on the endpoint. With it set, pstn_check_busy's
; per-extension personal_did lookup (see the outbound dialplan below) still
; ran and still set CALLERID(num) correctly, but every outbound call's From
; header — what the provider actually presents as Caller ID — used the
; static DID regardless, so every extension showed the same "original"
; number no matter which personal_did it was supposed to dial out as.
; Leaving from_user unset lets that per-call CALLERID(num) reach the wire.
; from_user=__PSTN_DID__ below IS static and MUST stay that way, unlike
; callerid= above. Confirmed live: removing it (on the theory that PJSIP
; would fall back to the calling channel's CALLERID(num) for the From
; header, mirroring the inbound fix above) instead made Asterisk fall back
; to its own hardcoded default From-header username ("asterisk", from
; res_pjsip.c's sip_dialog_create_from()/DEFAULT_FROM_USER — PJSIP never
; consults CALLERID(num) for the From header, endpoint->fromuser is the
; only input). The provider doesn't recognize "asterisk" as an account
; DID and silently rejects the call outright — every outbound call went
; straight to busy/congestion with the callee's phone never ringing at
; all, regardless of which extension or personal_did placed it. A static,
; provider-recognized From user is required for the call to go out at
; all; from_user is what to pin it to.
;
; send_pai=yes/send_rpid=yes below are what actually carry the per-call
; CALLERID(num) (personal_did if pstn_check_busy set one, the shared DID
; otherwise) to the provider despite from_user being static — Asterisk
; populates the P-Asserted-Identity and Remote-Party-ID headers from the
; calling channel's live Caller-ID at INVITE time, independent of
; from_user, which is the standard mechanism for presenting a per-call
; Caller-ID over a single shared-From trunk. This depends on the provider
; actually honoring one of these headers for outbound Caller-ID selection
; (the same assumption trust_id_inbound above makes for inbound) — if a
; personal_did extension's outbound calls still show the shared trunk DID
; after this, the provider needs the CID delivered a different way (e.g.
; a per-DID sub-account or registration) and this will need revisiting.
[pstn-trunk]
type=aor
@@ -275,11 +290,14 @@ context=from-pstn-trunk
disallow=all
allow=ulaw,alaw
aors=pstn-trunk
from_user=__PSTN_DID__
from_domain=__PSTN_SERVER__
trust_id_inbound=yes
send_pai=yes
send_rpid=yes
direct_media=no
EOF
sed -i "s/__PSTN_SERVER__/${SERVER}/g" "$FILE"
sed -i "s/__PSTN_SERVER__/${SERVER}/g; s/__PSTN_DID__/${DID}/g" "$FILE"
}
# ── Shared: one inbound ring-group member's live permission check ─────────
@@ -1595,7 +1613,7 @@ _pstn_apply_settings() {
_pstn_patch_vendor_files "$EA_DIR" || return 1
mkdir -p "$ASTERISK_DIR"
_pstn_write_pjsip_include "$ASTERISK_DIR/pstn-trunk-pjsip.conf" "$SERVER" "$SERVER_IPS"
_pstn_write_pjsip_include "$ASTERISK_DIR/pstn-trunk-pjsip.conf" "$SERVER" "$SERVER_IPS" "$DID"
_pstn_write_dialplan_include "$ASTERISK_DIR/pstn-trunk-dialplan.conf" "$DID" "$NTFY_URL"
_pstn_write_inbound_dialplan_include "$ASTERISK_DIR/pstn-trunk-inbound-dialplan.conf" "$RING_EXTS" "$NTFY_URL"
_pstn_write_personal_group_ring_script "$ASTERISK_DIR/pstn-personal-group-ring.sh"