From 2aa5b78514d13f5ac28a7a32bed907803853cc1c Mon Sep 17 00:00:00 2001
From: David Yat Sin <dyatsin@sangoma.com>
Date: Tue, 18 Sep 2012 23:11:05 -0400
Subject: [PATCH] freetdm: Fix for DL re-establishment on NFAS

---
 .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c  |  4 ++--
 .../ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h  |  5 ++++-
 .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c  |  4 ++++
 .../ftmod_sangoma_isdn_stack_out.c                 | 10 +++++++---
 .../ftmod_sangoma_isdn_support.c                   | 14 ++++++++++++++
 5 files changed, 31 insertions(+), 6 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 2483c01094..a3b640f90a 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
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2010, Sangoma Technologies 
  * David Yat Sin <davidy@sangoma.com>
@@ -40,7 +41,6 @@
 #include <sys/mman.h>
 #endif
 
-
 static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj);
 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span);
 static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span);
@@ -696,7 +696,7 @@ static ftdm_status_t ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdm
 					
 					ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Requesting Q.921 Line activation\n");
 					sngisdn_set_flag(sngisdn_info, FLAG_ACTIVATING);
-					sngisdn_snd_info_req(ftdmchan);
+					sngisdn_snd_dl_req(ftdmchan);
 					ftdm_sched_timer(signal_data->sched, "timer_t3", signal_data->timer_t3*1000, sngisdn_t3_timeout, (void*) sngisdn_info, NULL);
 				} else {
 					sngisdn_snd_setup(ftdmchan);
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 cc4d1108f6..47efd941ec 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
@@ -289,6 +289,8 @@ typedef struct sngisdn_span_data {
 	uint8_t			cid_name_method;
 	uint8_t			send_cid_name;	
 	uint8_t 		send_connect_ack;
+	uint8_t                 dl_request_pending; /* Whether we have a DL request pending */
+
 
 	int32_t			timer_t301;
 	int32_t			timer_t302;
@@ -441,7 +443,7 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
 void sngisdn_snd_reset(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan);
-void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
+void sngisdn_snd_dl_req(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_restart(ftdm_channel_t *ftdmchan);
 void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len);
@@ -581,6 +583,7 @@ void sngisdn_delayed_disconnect(void* p_sngisdn_info);
 void sngisdn_facility_timeout(void* p_sngisdn_info);
 void sngisdn_t3_timeout(void* p_sngisdn_info);
 void sngisdn_restart_timeout(void* p_signal_data);
+void sngisdn_delayed_dl_req(void* p_signal_data);
 
 /* Stack management functions */
 ftdm_status_t sngisdn_start_gen_cfg(void);
diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c
index 754aff1187..9cd1a2f42c 100644
--- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c
+++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c
@@ -70,6 +70,10 @@ void sngisdn_set_span_sig_status(ftdm_span_t *span, ftdm_signaling_status_t stat
 
 	((sngisdn_span_data_t*)span->signal_data)->sigstatus = status;
 
+	if (status == FTDM_SIG_STATE_UP) {
+		((sngisdn_span_data_t*)span->signal_data)->dl_request_pending = 0;
+	}	
+
 	chaniter = ftdm_span_get_chan_iterator(span, NULL);
 	for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
 		sngisdn_set_chan_sig_status(((ftdm_channel_t*)ftdm_iterator_current(curr)), status);
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 9055f7006b..02b1ce0be8 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
@@ -307,7 +307,7 @@ void sngisdn_snd_fac_req(ftdm_channel_t *ftdmchan)
 }
 
 /* This is used to request Q.921 to initiate link establishment */
-void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
+void sngisdn_snd_dl_req(ftdm_channel_t *ftdmchan)
 {
 	CnStEvnt cnStEvnt;
 	
@@ -482,6 +482,9 @@ void sngisdn_snd_data(ftdm_channel_t *dchan, uint8_t *data, ftdm_size_t len)
 				len, sizeof(l1_frame.data));
 		return;
 	}
+	if (len <= 2) {
+		return;
+	}
 
 	memset(&l1_frame, 0, sizeof(l1_frame));
 	l1_frame.len = len;
@@ -545,8 +548,9 @@ 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]);
+			
+			ftdm_sched_timer(signal_data->sched, "delayed_dl_req", 8000, sngisdn_delayed_dl_req, (void*) signal_data, NULL);
+			signal_data->dl_request_pending = 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_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c
index 8232d1969f..246c3190ee 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
@@ -1211,6 +1211,20 @@ void sngisdn_t3_timeout(void *p_sngisdn_info)
 	ftdm_mutex_unlock(ftdmchan->mutex);
 }
 
+
+void sngisdn_delayed_dl_req(void *p_signal_data)
+{
+	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t *)p_signal_data;
+	ftdm_span_t *span = signal_data->ftdm_span;
+	
+	if (!signal_data->dl_request_pending) {
+		return;
+	}
+	signal_data->dl_request_pending = 0;
+	sngisdn_snd_dl_req(span->channels[1]);
+	return;
+}
+
 void sngisdn_restart_timeout(void *p_signal_data)
 {
 	sngisdn_span_data_t *signal_data = (sngisdn_span_data_t *)p_signal_data;