From 48a8b26a8d96563a67428669f3f842047d6f543e Mon Sep 17 00:00:00 2001
From: George Yang <g.yang@genexis.eu>
Date: Thu, 19 Dec 2024 14:07:49 +0100
Subject: [PATCH] No transport fallback happens when Status 500 received for
 SIP Invite, REF #15941

- Not trigger re-registration when Status 500 received for outgoing Invite

- The emergency call flow is kept, which may trigger re-registration to
  recover from faulty status.
---
 res/res_pjsip_session.c | 95 +++++++++++++----------------------------
 1 file changed, 30 insertions(+), 65 deletions(-)

diff --git a/res/res_pjsip_session.c b/res/res_pjsip_session.c
index 0b9c22435f..c2c86b2752 100644
--- a/res/res_pjsip_session.c
+++ b/res/res_pjsip_session.c
@@ -3540,9 +3540,6 @@ struct ast_sip_session *ast_sip_session_create_outgoing(struct ast_sip_endpoint
 		if (transport_state && transport_state->type == AST_TRANSPORT_TLS
 				&& !ast_sip_is_X_RDK_NTP_Synchronized())
 			transport_state = NULL;
-
-		if (!transport_state && !ast_strlen_zero(endpoint->transport2))
-			transport_state = ast_sip_get_transport_state(endpoint->transport2);
 	}
 	if (!transport_state) {
 		ast_log(LOG_NOTICE,"===== No Transport! =====\n");
@@ -5054,72 +5051,42 @@ static struct ast_sip_transport_state* get_udp_transport_state()
 	return state;
 }
 
-static int sip_inv_transport2(pjsip_inv_session *inv, pjsip_event *e)
+static void sip_inv_transport_emergency(pjsip_inv_session *inv)
 {
 	struct ast_sip_session *session = inv->mod_data[session_module.id];
-	struct ast_sip_endpoint *endpoint = session->endpoint;
-	struct ast_sip_transport_state *transport2;
-	pjsip_transaction *tsx = e->body.tsx_state.tsx;
-	struct pjsip_msg *msg = tsx->last_tx->msg;
+	struct ast_sip_transport_state *transport_udp;
 	pjsip_tpselector selector = { .type = PJSIP_TPSELECTOR_NONE, };
-	pjsip_sip_uri *target_uri;
-	pjsip_tx_data *tdata;
-
-	if (msg->type != PJSIP_REQUEST_MSG ||
-	    msg->line.req.method.id != PJSIP_INVITE_METHOD)
-		return 0;
-
-	if (endpoint && endpoint->transport2) {
-		transport2 = ast_sip_get_transport_state(endpoint->transport2);
-	}
 
-	if (!transport2) {
-		// for emergency ongoing call, try UDP further, if transport2 is not available
-		if (session->channel && ast_channel_emergency_ongoing_get(session->channel)) {
-			ast_log(LOG_NOTICE, "Try UDP transport for emergency ongoing call\n");
+	ast_log(LOG_NOTICE, "Try UDP transport for emergency ongoing call\n");
 
-			transport2 = get_udp_transport_state();
+	transport_udp = get_udp_transport_state();
 
-			if (!transport2) {
-				ast_log(LOG_NOTICE, "No UDP transport available\n");
-				return 0;
-			}
-		} else {
-			if (endpoint->transport2) {
-				ast_log(LOG_ERROR, "transport2 %s is not available\n", endpoint->transport2);
-			} else {
-				ast_debug(3, "no transport2 available\n");
-			}
+	if (transport_udp && transport_udp != session->transport_state &&
+	    !ast_sip_set_tpselector_from_transport_name(transport_udp->id, &selector)) {
+		pjsip_sip_uri *target_uri;
+		pjsip_tx_data *tdata;
 
-			return 0;
-		}
-	}
+		ast_log(LOG_NOTICE, "Sending SIP INVITE with transport (%s)\n", transport_udp->id);
 
-	if (transport2 == session->transport_state) {
-		ast_debug(3, "Tried transport2 '%s'. No help!\n", transport2->id);
-		return 0;
-	}
+		session->transport_state = transport_udp;
+		pjsip_dlg_set_transport(inv->dlg, &selector);
 
-	if (ast_sip_set_tpselector_from_transport_name(endpoint->transport2, &selector))
-		return 0;
+		pjsip_inv_uac_restart(inv, PJ_FALSE);
+		pjmedia_sdp_neg_cancel_offer(inv->neg);
 
-	pjsip_dlg_set_transport(inv->dlg, &selector);
-	session->transport_state = transport2;
+		target_uri = pjsip_uri_get_uri(inv->dlg->target);
+		if (target_uri)
+			target_uri->port = pj_sockaddr_get_port(&transport_udp->host);
 
-	ast_log(LOG_NOTICE, "Sending SIP INVITE with transport (%s)\n", transport2->id);
+		ast_sip_session_create_invite(session, &tdata);
+		ast_sip_session_send_request(session, tdata);
 
-	pjsip_inv_uac_restart(inv, PJ_FALSE);
-	pjmedia_sdp_neg_cancel_offer(inv->neg);
+	} else if (session->endpoint) {
+		ast_log(LOG_NOTICE, "%s: Failed to INVITE, schedule re-registration\n", ast_sorcery_object_get_id(session->endpoint));
 
-	target_uri = pjsip_uri_get_uri(inv->dlg->target);
-	if (target_uri) {
-		target_uri->port = pj_sockaddr_get_port(&transport2->host);
+		session->endpoint->failover_reg_addr = 1;
+		queue_registration_recovery_flow(ast_sorcery_object_get_id(session->endpoint));
 	}
-
-	ast_sip_session_create_invite(session, &tdata);
-	ast_sip_session_send_request(session, tdata);
-
-	return 1;
 }
 
 static int check_request_status(pjsip_inv_session *inv, pjsip_event *e)
@@ -5136,18 +5103,16 @@ static int check_request_status(pjsip_inv_session *inv, pjsip_event *e)
 	}
 
 	ast_log(LOG_NOTICE, "Failed to send SIP INVITE with transport '%s'\n", session->transport_state->id);
-	// Try if the endpoint has transport2
-	if (!sip_inv_transport2(inv, e)) {
-		// no transport2
-		if (session->endpoint) {
-			ast_log(LOG_NOTICE, "INVITE sent to '%s' failed, schedule re-registrations\n", ast_sorcery_object_get_id(session->endpoint));
-			session->endpoint->failover_reg_addr = 1;
-			queue_registration_recovery_flow(ast_sorcery_object_get_id(session->endpoint));
-		}
-		return 0;
+
+	// Try more for emergency ongoing INVITE
+	if (session->channel && ast_channel_emergency_ongoing_get(session->channel)) {
+		struct pjsip_msg *msg = tsx->last_tx->msg;
+
+		if (msg && msg->type == PJSIP_REQUEST_MSG && msg->line.req.method.id == PJSIP_INVITE_METHOD)
+			sip_inv_transport_emergency(inv);
 	}
-	return 1; // transport2 ongoing
 
+	return 1;
 }
 
 static void handle_incoming_before_media(pjsip_inv_session *inv,
-- 
GitLab