Commit f8175505d1 for asterisk.org

commit f8175505d13a247954edea6c9478c67c8cdbace3
Author: wlp2s0 <47446173+wlp2s0@users.noreply.github.com>
Date:   Thu Oct 8 16:40:17 2026 +0200

    chan_pjsip: Don't replace a hangup cause set before the session ends.

    chan_pjsip_session_end() used to map the SIP status of the INVITE
    session to a hangup cause only when the channel didn't have one yet.
    Since the change for #1819 it always takes the cause from the dialed
    cause entry of the last non-2XX response, so a cause that was already
    set on the channel is replaced.

    res_pjsip_rfc3326 sets the hangup cause from the Q.850 Reason header of
    a failed INVITE response, and that cause is now lost: a 480 with
    "Reason: Q.850;cause=127" ends with cause 19.

    The dialed cause entry is now used for the hangup cause only when the
    channel doesn't have one yet. The tech cause is still taken from it, so
    a 302 still ends with cause 23 and tech cause 302.

    Resolves: #2211

    UserNote: Outgoing PJSIP calls rejected with a Reason header carrying a
    Q.850 cause end with that cause again when res_pjsip_rfc3326 is loaded,
    instead of the cause mapped from the SIP response code.

diff --git a/channels/chan_pjsip.c b/channels/chan_pjsip.c
index 517afaec93..af9b18c247 100644
--- a/channels/chan_pjsip.c
+++ b/channels/chan_pjsip.c
@@ -3142,7 +3142,9 @@ static void chan_pjsip_session_end(struct ast_sip_session *session)
 				/* We only want to use non-2XX SIP response codes */
 				if (tech_cause / 100 > 2) {
 					new_tech_cause = tech_cause;
-					new_cause = pvt_cause->ast_cause;
+					if (!existing_cause) {
+						new_cause = pvt_cause->ast_cause;
+					}
 					ast_trace(-1, "%s: %s dialed ast_cause: %d tech_cause: %d used\n", ast_sip_session_get_name(session),
 						pvt_cause->chan_name, new_cause, new_tech_cause);
 				} else {