From bce826b8f50cd7920c93166d5300f5f1a0a54538 Mon Sep 17 00:00:00 2001
From: Wenpeng Song <wenpeng.song@iopsys.eu>
Date: Thu, 27 Feb 2025 12:46:57 +0000
Subject: [PATCH] Fix some issue with emergency un-register after timeout or
 emergency register failed, REF 16302

---
 res/res_pjsip_outbound_registration.c | 29 ++++++++++++++++++++++-----
 1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/res/res_pjsip_outbound_registration.c b/res/res_pjsip_outbound_registration.c
index b53dd50e6c..44df5800f3 100644
--- a/res/res_pjsip_outbound_registration.c
+++ b/res/res_pjsip_outbound_registration.c
@@ -1881,6 +1881,14 @@ static int handle_registration_response(void *data)
 				client_state->registration_resend_timer_id = ast_sched_add(sched, waiting_time * 1000, registration_resend, response);
 			}
 			return 0;
+		} else if (client_state->Emergency_reg_ongoing) {
+			ast_log(LOG_NOTICE,"===== E-reg failed on all addr before E-unreg being triggered, stop and send normal reg direct=====\n");
+			client_state->Emergency_reg_ongoing=false;
+			client_state->Emergency_unreg_ongoing=true;
+			update_client_state_status(client_state, SIP_REGISTRATION_UNREGISTERED);
+			sip_outbound_registration_send_ubus_event("UNREGISTERED",response->expiration,client_uri);
+			registration_resend(response);
+			return 0;
 		}
 	} else if ((response->code == 401 || response->code == 407)
 		&& (!client_state->auth_attempted
@@ -3241,20 +3249,26 @@ static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
 {
 	struct sip_outbound_registration_state *state;
 	const char *registration_name;
+	bool emergency=false;
 
 	switch (cmd) {
 	case CLI_INIT:
 		e->command = "pjsip send unregister";
 		e->usage =
-			"Usage: pjsip send unregister <registration> | *all\n"
+			"Usage: pjsip send unregister <registration> | *all [e]\n"
 			"       Unregisters the specified (or all) outbound registration(s) "
-			"and stops future registration attempts.\n";
+			"and stops future registration attempts.\n"
+			"       Optional flag e to reset the triggered emergency registration.\n";
 		return NULL;
 	case CLI_GENERATE:
 		return cli_complete_registration(a->line, a->word, a->pos, a->n);
 	}
 
-	if (a->argc != 4) {
+	if (a->argc == 5 && strcmp(a->argv[4], "e") == 0){
+		emergency=true;
+	}
+
+	if (a->argc != 4 && !emergency) {
 		return CLI_SHOWUSAGE;
 	}
 
@@ -3277,6 +3291,10 @@ static char *cli_unregister(struct ast_cli_entry *e, int cmd, struct ast_cli_arg
 		// unregister triggered while 1.emergency registered 2.emergency register still ongoing
 		state->client_state->Emergency_unreg_ongoing = true;
 		ast_log(LOG_NOTICE,"Emergency Registration unregister ongoing\n");
+	} else if (emergency){
+		// E-unregister triggered after registration reset to primary, just return.
+		ao2_ref(state, -1);
+		return CLI_SUCCESS;
 	}
 
 	if (queue_unregister(state)) {
@@ -3297,9 +3315,10 @@ static char *cli_register(struct ast_cli_entry *e, int cmd, struct ast_cli_args
 	case CLI_INIT:
 		e->command = "pjsip send register";
 		e->usage =
-			"Usage: pjsip send register <registration> | *all \n"
+			"Usage: pjsip send register <registration> | *all [e]\n"
 			"       Unregisters the specified (or all) outbound "
-			"registration(s) then starts registration(s) and schedules re-registrations.\n";
+			"registration(s) then starts registration(s) and schedules re-registrations.\n"
+			"       Optional flag e to trigger emergency registration through UDP\n";
 		return NULL;
 	case CLI_GENERATE:
 		return cli_complete_registration(a->line, a->word, a->pos, a->n);
-- 
GitLab