diff --git a/src/channels/chan_voicemngr.c b/src/channels/chan_voicemngr.c
index c8f5a59a059e81b3058a95bb65a6902e4bd39f46..351ed77d80e2de4f772f8a10e1ed31e027e0ccf1 100644
--- a/src/channels/chan_voicemngr.c
+++ b/src/channels/chan_voicemngr.c
@@ -148,6 +148,9 @@ static struct ast_format *map_rtpname_to_format(char* name);
 static int is_sip_account_registered(const char *sip_account);
 typedef void *(*check_output_cb)(const char *, const char *data);
 static void *call_cli_command(const char *cmd, check_output_cb check_output, const char *data);
+static void chan_voicemngr_start_calling(struct chan_voicemngr_subchannel *sub, char* context);
+static int register_504_cb(const void *data);
+static int is_sip_account_504_ongoing(const char *sip_account);
 
 /* Global jitter buffer configuration - by default, jb is disabled */
 static struct ast_jb_conf default_jbconf =
@@ -1161,6 +1164,9 @@ static int chan_voicemngr_indicate(struct ast_channel *ast, int condition, const
 		case AST_CAUSE_NETWORK_OUT_OF_ORDER:
 			chan_voicemngr_stop_dialtone(sub->parent); // stop any dialtone exist if disconnection happened due to network/server
 			break;
+		case AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
+			//504
+			break;
 		default:
 			ast_debug(1, "Don't know how to handle cause code %d\n", ast_cause);
 			break;
@@ -1519,7 +1525,12 @@ static int chan_voicemngr_hangup(struct ast_channel *ast)
 		ast_log(LOG_WARNING, "Asked to hangup channel not connected\n");
 		return 0;
 	}
-
+	if (ast_channel_hangupcause(ast) == AST_CAUSE_RECOVERY_ON_TIMER_EXPIRE && is_sip_account_504_ongoing(sub->parent->invoke_context)==1 && sub->register_504_timer_count == 0){
+		//chan_voicemngr_mute_connection(sub);
+		sub->register_504_timer_count++;
+		sub->register_504_timer_id = ast_sched_add(sched, 1000, register_504_cb, sub);
+		ast_log(LOG_NOTICE,"INIVTE got 504 with register request, waiting for response from new register request\n");
+	}
 	p = sub->parent;
 	pvt_lock(p, "TELCHAN hangup");
 	sub_peer = chan_voicemngr_subchannel_get_peer(sub);
@@ -1647,8 +1658,10 @@ static int chan_voicemngr_hangup(struct ast_channel *ast)
 			sub_peer->channel_state = INCALL;
 		}
 	}
-
-	memset(p->ext, 0, sizeof(p->ext));
+	if(!sub->register_504_timer_count){
+		// keep ext for re INVITE after re-register after 504 response with xml
+		memset(p->ext, 0, sizeof(p->ext));
+	}
 	sub->owner = NULL;
 	sub->conference_initiator = 0;
 	ast_free(sub->conference_id);
@@ -1661,7 +1674,7 @@ static int chan_voicemngr_hangup(struct ast_channel *ast)
 
 	/* Check for channel state before dial tone timeout */
 	if (sub->channel_state == CALLENDED && sub_peer->channel_state != INCALL && p->dialtone != DIALTONE_BUSY
-		&& sub->channel_state != TRANSFERING) {
+		&& sub->channel_state != TRANSFERING && !sub->register_504_timer_count) {
 		/* If we hangup but not playing howler or busy, start playing timeout tones */
 		p->dialtone = DIALTONE_ON;
 		handle_dialtone_timeout(p);
@@ -1695,8 +1708,11 @@ static int chan_voicemngr_hangup(struct ast_channel *ast)
 		call_cli_command(cmd, NULL, NULL);
 	}
 	/* reset invoke contexts */
-	ast_copy_string(p->invoke_context, p->context, sizeof(p->invoke_context));
-	ast_copy_string(p->invoke_context_direct, p->context_direct, sizeof(p->invoke_context_direct));
+	if(!sub->register_504_timer_count){
+		// keep while doing 504 re-register
+		ast_copy_string(p->invoke_context, p->context, sizeof(p->invoke_context));
+		ast_copy_string(p->invoke_context_direct, p->context_direct, sizeof(p->invoke_context_direct));
+	}
 
 	pvt_unlock(p);
 	return 0;
@@ -2323,6 +2339,50 @@ static int switch_back_call_cb( const void *data)
 	return 0;
 }
 
+/* register due to 504 with xml(init-register) handler. */
+static int register_504_cb(const void *data)
+{
+	struct chan_voicemngr_subchannel *sub;
+	sub = (struct chan_voicemngr_subchannel *) data;
+	int res = 0;
+	res = is_sip_account_504_ongoing(sub->parent->invoke_context);
+	switch(res) {
+		case 0:
+			// registered, start calling again
+			ast_log(LOG_NOTICE,"register due to 504 success, start calling\n");
+			sub->register_504_timer_count = 0;
+			sub->register_504_timer_id = -1;
+			ast_copy_string(sub->parent->dtmfbuf, sub->parent->ext, sizeof(sub->parent->ext));
+			chan_voicemngr_start_calling(sub, sub->parent->invoke_context);
+			break;
+		case 1:
+			// ongoing, try again in 1s
+			ast_log(LOG_NOTICE,"register due to 504 ongoing\n");
+			if(sub->register_504_timer_count<=33){
+				// continue waiting while not reaching transaction timeout(32s)+1s delay.
+				sub->channel_state = CALLING;
+				sub->register_504_timer_id = ast_sched_add(sched, 1000, register_504_cb, sub);
+				sub->register_504_timer_count++;
+				break;
+			}
+		case 2:
+			// failed, play congestion tone and waiting for on-hook
+			sub->register_504_timer_count = 0;
+			sub->register_504_timer_id = -1;
+			ast_log(LOG_NOTICE,"register due to 504 failed\n");
+			sub->parent->dialtone = DIALTONE_CONGESTION;
+			sub->channel_state = AWAITONHOOK;
+			sub->parent->dialtone_timeout_timer_id = ast_sched_add(sched, channel_config[sub->parent->line_id].offhook_nu_timeoutmsec, handle_dialtone_timeout, sub->parent);
+			chan_voicemngr_signal_dialtone(sub->parent);
+			memset(sub->parent->ext, 0, sizeof(sub->parent->ext));
+			ast_copy_string(sub->parent->invoke_context, sub->parent->context, sizeof(sub->parent->invoke_context));
+			ast_copy_string(sub->parent->invoke_context_direct, sub->parent->context_direct, sizeof(sub->parent->invoke_context_direct));
+			break;
+	}
+	return 0;
+
+}
+
 /* Hangup incoming call after call waiting times out */
 static int cwtimeout_cb(const void *data)
 {
@@ -3781,6 +3841,26 @@ static int is_sip_account_registered(const char *sip_account)
 	return !!call_cli_command(cmd_registrations, (check_output_cb)&check_is_sip_account_registered, sip_account);
 }
 
+static int check_is_sip_account_504_ongoing(const char *line, const char *sip_account)
+{
+	return ((strstr(line, sip_account) != NULL) && (strstr(line, "504_ongoing") != NULL));
+}
+static int check_is_sip_account_504_failed(const char *line, const char *sip_account)
+{
+	return ((strstr(line, sip_account) != NULL) && (strstr(line, "504_failed") != NULL));
+}
+
+static int is_sip_account_504_ongoing(const char *sip_account)
+{
+	if( !!call_cli_command(cmd_registrations, (check_output_cb)&check_is_sip_account_504_ongoing, sip_account) ){
+		return 1;
+	}
+	if( !!call_cli_command(cmd_registrations, (check_output_cb)&check_is_sip_account_504_failed, sip_account) ){
+		return 2;
+	}
+	return 0;
+}
+
 static int check_endpoint_status(const char *line, const char *sip_account)
 {
 	int ret = 1;
@@ -3990,6 +4070,18 @@ static void chan_voicemngr_process_event(struct endpt_event *ev)
 				p->busy_internal_call_timer_id = -1;
 			}
 
+			if(sub->register_504_timer_id != -1) {
+				// user hangup before 504 register got any final result, cancel the timer and reset the extension/context memory.
+				if (ast_sched_del(sched, sub->register_504_timer_id)) {
+					ast_log(LOG_WARNING, "Failed to remove scheduled 504 register timer\n");
+				}
+				sub->register_504_timer_id = -1;
+				sub->register_504_timer_count = 0;
+				memset(sub->parent->ext, 0, sizeof(sub->parent->ext));
+				ast_copy_string(sub->parent->invoke_context, sub->parent->context, sizeof(sub->parent->invoke_context));
+				ast_copy_string(sub->parent->invoke_context_direct, sub->parent->context_direct, sizeof(sub->parent->invoke_context_direct));
+			}
+
 			if (sub->owner && sub->audio_announcement == AUDIO_ANNOUNCEMENT_STARTED) {
 				ast_stopstream(sub->owner);
 				sub->audio_announcement = AUDIO_ANNOUNCEMENT_STOPPING;
@@ -4243,6 +4335,8 @@ static struct chan_voicemngr_pvt *chan_voicemngr_allocate_pvt(void)
 				sub->congestion_timer_id = -1;
 				sub->audio_announcement_count = 0;
 				sub->audio_announcement = AUDIO_ANNOUNCEMENT_STOPPED;
+				sub->register_504_timer_count = 0;
+				sub->register_504_timer_id = -1;
 				sub->sip_client_id = -1;
 				sub->is_internal = false;
 				sub->period = default_ptime;												// 20 ms
diff --git a/src/channels/chan_voicemngr.h b/src/channels/chan_voicemngr.h
index 898b9abcc7b2b1cc895d223aaa5e2ba62cfb23dc..93fb2ea287f237443f27d2825fdcabfe0725a136 100644
--- a/src/channels/chan_voicemngr.h
+++ b/src/channels/chan_voicemngr.h
@@ -197,6 +197,8 @@ struct chan_voicemngr_subchannel {
 	int congestion_timer_id;
 	int audio_announcement_count;
 	audio_announcement_state audio_announcement;
+	int register_504_timer_count;
+	int register_504_timer_id;
 };
 
 struct chan_voicemngr_channel_tech {