From c0e4ca47bce1ff6bba60f2af5c536bfa09fe4ce8 Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Tue, 11 Sep 2012 01:22:31 -0400
Subject: [PATCH] Freetdm: ISDN fix for link not always recovering after T1/E1
 alarm

---
 .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c |  5 ++++-
 .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h |  1 +
 .../ftmod_sangoma_isdn_stack_cfg.c                | 15 ++++++++++-----
 .../ftmod_sangoma_isdn_stack_cntrl.c              |  5 +++++
 .../ftmod_sangoma_isdn_stack_out.c                | 13 ++++---------
 .../ftmod_sangoma_isdn_stack_rcv.c                | 11 +++++++++--
 .../ftmod_sangoma_isdn_support.c                  |  4 ++++
 7 files changed, 37 insertions(+), 17 deletions(-)

diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
index 65f17fa47b..2483c01094 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
@@ -1376,8 +1376,11 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
 	}
 	
 	/* initalize sng_isdn library */
-
 	ftdm_assert_return(!sng_isdn_init(&g_sngisdn_event_interface), FTDM_FAIL, "Failed to initialize stack\n");
+
+	/* Load Stack General Configuration */
+	sngisdn_start_gen_cfg();
+
 	return FTDM_SUCCESS;
 }
 
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
index fc93155ffa..40a89a80c8 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
@@ -583,6 +583,7 @@ void sngisdn_t3_timeout(void* p_sngisdn_info);
 void sngisdn_restart_timeout(void* p_signal_data);
 
 /* Stack management functions */
+ftdm_status_t sngisdn_start_gen_cfg(void);
 ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span);
 ftdm_status_t sngisdn_stack_start(ftdm_span_t *span);
 ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span);
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
index 52daf3ad7b..946b9769b0 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c
@@ -58,12 +58,8 @@ ftdm_status_t sngisdn_stack_cfg_q931_lce(ftdm_span_t *span);
 
 ftdm_status_t sngisdn_stack_cfg_cc_sap(ftdm_span_t *span);
 
-ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span)
+ftdm_status_t sngisdn_start_gen_cfg(void)
 {
-	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
-
-	ftdm_log(FTDM_LOG_DEBUG, "Starting stack configuration for span:%s\n", span->name);
-	
 	if (!g_sngisdn_data.gen_config_done) {
 		g_sngisdn_data.gen_config_done = 1;
 		ftdm_log(FTDM_LOG_DEBUG, "Starting general stack configuration\n");
@@ -92,6 +88,15 @@ ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span)
 		ftdm_log(FTDM_LOG_DEBUG, "General stack CC done\n");
 		ftdm_log(FTDM_LOG_INFO, "General stack configuration done\n");
 	}
+	return FTDM_SUCCESS;
+}
+
+
+ftdm_status_t sngisdn_stack_cfg(ftdm_span_t *span)
+{
+	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
+
+	ftdm_log(FTDM_LOG_DEBUG, "Starting stack configuration for span:%s\n", span->name);
 
 	if (signal_data->dchan) {
 		if (sngisdn_stack_cfg_phy_psap(span) != FTDM_SUCCESS) {
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
index 1cc23ddb8d..d745efed0b 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c
@@ -232,6 +232,11 @@ ftdm_status_t sngisdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trac
 {
 	sngisdn_span_data_t *signal_data = sngisdn_dchan((sngisdn_span_data_t*)span->signal_data);
 
+	if (!signal_data) {
+		ftdm_log(FTDM_LOG_ERROR, "%s:Span is not used by signalling module\n", span->name);
+		return FTDM_FAIL;
+	}
+
 	switch (trace_opt) {
 		case SNGISDN_TRACE_DISABLE:
 			if (sngisdn_test_trace_flag(signal_data, SNGISDN_TRACE_Q921)) {
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
index b05ee41356..9055f7006b 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
@@ -314,19 +314,12 @@ void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
 	sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 
-	if (ftdmchan->span->trunk_type != FTDM_TRUNK_BRI &&
-		ftdmchan->span->trunk_type != FTDM_TRUNK_BRI_PTMP) {
-
-		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring INFO REQ on non-BRI channel\n");
-		return;
-	}
-
 	memset(&cnStEvnt, 0, sizeof(cnStEvnt));
 
-	ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
+	ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Requesting Link establishment (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces);
 
 	if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, sngisdn_dchan(signal_data)->link_id, sngisdn_info->ces)) {
-		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, 	"stack refused INFO request\n");
+		ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, 	"stack refused Link establishment\n");
 	}
 	return;
 }
@@ -552,6 +545,8 @@ void sngisdn_snd_event(sngisdn_span_data_t *signal_data, ftdm_oob_event_t event)
 		case FTDM_OOB_ALARM_CLEAR:
 			l1_event.type = SNG_L1EVENT_ALARM_OFF;
 			sng_isdn_event_ind(signal_data->link_id, &l1_event);
+
+			sngisdn_snd_info_req(signal_data->ftdm_span->channels[1]);
 			break;
 		case FTDM_OOB_ALARM_TRAP:
 			l1_event.type = SNG_L1EVENT_ALARM_ON;
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
index a5ba7c54b9..34b4150ac0 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
@@ -525,10 +525,17 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St
 
 	ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 
+	if (!suInstId && !spInstId) {
+		/* This is a response to a sngisdn_snd_info_req
+		 * that was sent to attempt to re-establish DL link */
+		ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
+		return;
+	}
+
 	/* We sometimes receive a STA CFM after receiving a RELEASE/RELEASE COMPLETE, so we need to lock
 		here in case we are calling clear_call_data at the same time this function is called */
 
-	ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);	
+	ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
 	if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
 		!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
 
@@ -838,7 +845,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
 
 			if (nfas_data && status->t.usta.alarm.event == LCM_EVENT_DOWN) {
 				if (nfas_data->dchan->sigstatus == FTDM_SIG_STATE_DOWN &&
-				   (nfas_data->backup && nfas_data->backup->sigstatus == FTDM_SIG_STATE_DOWN)) {
+				   ((nfas_data->backup && nfas_data->backup->sigstatus == FTDM_SIG_STATE_DOWN) || !nfas_data->backup)) {
 
 					for (i = 0; i < ftdm_array_len(nfas_data->spans); i++) {
 						if (nfas_data->spans[i] && nfas_data->spans[i]->nfas.sigchan == SNGISDN_NFAS_DCHAN_NONE) {
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
index 5f63f384d7..8232d1969f 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
@@ -1595,6 +1595,10 @@ void sngisdn_send_signal(sngisdn_chan_data_t *sngisdn_info, ftdm_signal_event_t
 
 sngisdn_span_data_t *sngisdn_dchan(sngisdn_span_data_t *signal_data)
 {
+	if (!signal_data) {
+		return NULL;
+	}
+
 	if (!signal_data->nfas.trunk) {
 		return signal_data;
 	}