]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: ss7 - bug fixes
authorKonrad Hammel <konrad@sangoma.com>
Thu, 23 Sep 2010 15:04:10 +0000 (11:04 -0400)
committerKonrad Hammel <konrad@sangoma.com>
Fri, 24 Sep 2010 19:18:18 +0000 (15:18 -0400)
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c

index 21ab1d32d247a197980ce1586a329e06dcd53562..21feb4f8fe8962b8ea6e3db091e2e3c5357a78bd 100644 (file)
@@ -85,35 +85,35 @@ int  ft_to_sngss7_cfg_all(void)
 
                if (ftmod_ss7_mtp1_gen_config()) {
                        SS7_CRITICAL("MTP1 General configuration FAILED!\n");
-                       SS7_ASSERT
+                       return 1;
                } else {
                        SS7_INFO("MTP1 General configuration DONE\n");
                }
 
                if (ftmod_ss7_mtp2_gen_config()) {
                        SS7_CRITICAL("MTP2 General configuration FAILED!\n");
-                       SS7_ASSERT
+                       return 1;
                } else {
                        SS7_INFO("MTP2 General configuration DONE\n");
                }
 
                if (ftmod_ss7_mtp3_gen_config()) {
                        SS7_CRITICAL("MTP3 General configuration FAILED!\n");
-                       SS7_ASSERT
+                       return 1;
                } else {
                        SS7_INFO("MTP3 General configuration DONE\n");
                }
 
                if (ftmod_ss7_isup_gen_config()) {
                        SS7_CRITICAL("ISUP General configuration FAILED!\n");
-                       SS7_ASSERT
+                       return 1;
                } else {
                        SS7_INFO("ISUP General configuration DONE\n");
                }
 
                if (ftmod_ss7_cc_gen_config()) {
                        SS7_CRITICAL("CC General configuration FAILED!\n");
-                       SS7_ASSERT
+                       return 1;
                } else {
                        SS7_INFO("CC General configuration DONE\n");
                }
@@ -131,7 +131,7 @@ int  ft_to_sngss7_cfg_all(void)
                        /* configure mtp1 */
                        if (ftmod_ss7_mtp1_psap_config(x)) {
                                SS7_CRITICAL("MTP1 PSAP %d configuration FAILED!\n", x);
-                               SS7_ASSERT;
+                               return 1;;
                        } else {
                                SS7_INFO("MTP1 PSAP %d configuration DONE!\n", x);
                        }
@@ -139,7 +139,7 @@ int  ft_to_sngss7_cfg_all(void)
                        /* configure mtp2 */
                        if (ftmod_ss7_mtp2_dlsap_config(x)) {
                                SS7_CRITICAL("MTP2 DLSAP %d configuration FAILED!\n",x);
-                               SS7_ASSERT;
+                               return 1;;
                        } else {
                                SS7_INFO("MTP2 DLSAP %d configuration DONE!\n", x);
                        }
@@ -147,7 +147,7 @@ int  ft_to_sngss7_cfg_all(void)
                        /* configure mtp3 */
                        if (ftmod_ss7_mtp3_dlsap_config(x)) {
                                SS7_CRITICAL("MTP3 DLSAP %d configuration FAILED!\n", x);
-                               SS7_ASSERT;
+                               return 1;;
                        } else {
                                SS7_INFO("MTP3 DLSAP %d configuration DONE!\n", x);
                        }
@@ -166,14 +166,14 @@ int  ft_to_sngss7_cfg_all(void)
 
                        if (ftmod_ss7_mtp3_nsap_config(x)) {
                                SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!\n", x);
-                               SS7_ASSERT
+                               return 1;
                        } else {
                                SS7_INFO("MTP3 NSAP %d configuration DONE!\n", x);
                        }
 
                        if (ftmod_ss7_isup_nsap_config(x)) {
                                SS7_CRITICAL("ISUP NSAP %d configuration FAILED!\n", x);
-                               SS7_ASSERT
+                               return 1;
                        } else {
                                SS7_INFO("ISUP NSAP %d configuration DONE!\n", x);
                        }
@@ -192,7 +192,7 @@ int  ft_to_sngss7_cfg_all(void)
 
                        if (ftmod_ss7_mtp3_linkset_config(x)) {
                                SS7_CRITICAL("MTP3 LINKSET %d configuration FAILED!\n", x);
-                               SS7_ASSERT
+                               return 1;
                        } else {
                                SS7_INFO("MTP3 LINKSET %d configuration DONE!\n", x);
                        }
@@ -211,7 +211,7 @@ int  ft_to_sngss7_cfg_all(void)
 
                        if (ftmod_ss7_mtp3_route_config(x)) {
                                SS7_CRITICAL("MTP3 ROUTE %d configuration FAILED!\n", x);
-                               SS7_ASSERT
+                               return 1;
                        } else {
                                SS7_INFO("MTP3 ROUTE %d configuration DONE!\n",x);
                        }
@@ -227,7 +227,7 @@ int  ft_to_sngss7_cfg_all(void)
 
                if (ftmod_ss7_mtp3_route_config(0)) {
                        SS7_CRITICAL("MTP3 ROUTE 0 configuration FAILED!\n");
-                       SS7_ASSERT
+                       return 1;
                } else {
                        SS7_INFO("MTP3 ROUTE 0 configuration DONE!\n");
                }
@@ -244,14 +244,14 @@ int  ft_to_sngss7_cfg_all(void)
                        
                        if (ftmod_ss7_isup_isap_config(x)) {
                                SS7_CRITICAL("ISUP ISAP %d configuration FAILED!\n", x);
-                               SS7_ASSERT
+                               return 1;
                        } else {
                                SS7_INFO("ISUP ISAP %d configuration DONE!\n", x);
                        }
 
                        if (ftmod_ss7_cc_isap_config(x)) {
                                SS7_CRITICAL("CC ISAP %d configuration FAILED!\n", x);
-                               SS7_ASSERT
+                               return 1;
                        } else {
                                SS7_INFO("CC ISAP %d configuration DONE!\n", x);
                        }
@@ -270,9 +270,11 @@ int  ft_to_sngss7_cfg_all(void)
 
                        if (ftmod_ss7_isup_intf_config(x)) {
                                SS7_CRITICAL("ISUP INTF %d configuration FAILED!\n", x);
-                               SS7_ASSERT
+                               return 1;
                        } else {
                                SS7_INFO("ISUP INTF %d configuration DONE!\n", x);
+                               /* set the interface to paused */
+                               sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[x], SNGSS7_PAUSED);
                        }
 
                        /* set the CONFIGURED flag */
@@ -289,7 +291,7 @@ int  ft_to_sngss7_cfg_all(void)
                        if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == 0) {
                                if (ftmod_ss7_isup_ckt_config(x)) {
                                        SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x);
-                                       SS7_ASSERT
+                                       return 1;
                                } else {
                                        SS7_INFO("ISUP CKT %d configuration DONE!\n", x);
                                }
index cf56f51a0a43a2db18c641ad568882d5e674385e..6ccc693478875ef0b0f10a663d7a718f071f3ecf 100644 (file)
@@ -1156,7 +1156,12 @@ static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int c
                                /* check if there is a pending state change|give it a bit to clear */
                                if (check_for_state_change(ftdmchan)) {
                                        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic);
+                                       /* check if we need to die */
                                        SS7_ASSERT;
+                                       /* unlock the channel again before we exit */
+                                       ftdm_mutex_unlock(ftdmchan->mutex);
+                                       /* move to the next channel */
+                                       continue;
                                } else {
                                        /* throw the ckt block flag */
                                        sngss7_set_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
@@ -1217,7 +1222,12 @@ static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int c
                                /* check if there is a pending state change|give it a bit to clear */
                                if (check_for_state_change(ftdmchan)) {
                                        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic);
+                                       /* check if we need to die */
                                        SS7_ASSERT;
+                                       /* unlock the channel again before we exit */
+                                       ftdm_mutex_unlock(ftdmchan->mutex);
+                                       /* move to the next channel */
+                                       continue;
                                } else {
                                        /* throw the ckt block flag */
                                        sngss7_set_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX);
@@ -1466,7 +1476,12 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c
                                /* check if there is a pending state change|give it a bit to clear */
                                if (check_for_state_change(ftdmchan)) {
                                        SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
+                                       /* check if we need to die */
                                        SS7_ASSERT;
+                                       /* unlock the channel again before we exit */
+                                       ftdm_mutex_unlock(ftdmchan->mutex);
+                                       /* move to the next channel */
+                                       continue;
                                } else {
                                        /* throw the grp reset flag */
                                        sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
index 0d76329d25fa349df68887fe83cd25d81434da7f..87733dd59496fc47e26cef79b6c6d55310a03ceb 100644 (file)
@@ -75,7 +75,7 @@ int ft_to_sngss7_activate_all(void)
 
                        if (ftmod_ss7_enable_isap(x)) { 
                                SS7_CRITICAL("ISAP %d Enable: NOT OK\n", x);
-                               SS7_ASSERT;
+                               return 1;
                        } else {
                                SS7_INFO("ISAP %d Enable: OK\n", x);
                        }
@@ -94,7 +94,7 @@ int ft_to_sngss7_activate_all(void)
 
                        if (ftmod_ss7_enable_nsap(x)) { 
                                SS7_CRITICAL("NSAP %d Enable: NOT OK\n", x);
-                               SS7_ASSERT;
+                               return 1;
                        } else {
                                SS7_INFO("NSAP %d Enable: OK\n", x);
                        }
@@ -113,7 +113,7 @@ int ft_to_sngss7_activate_all(void)
 
                        if (ftmod_ss7_enable_mtpLinkSet(x)) {   
                                SS7_CRITICAL("LinkSet \"%s\" Enable: NOT OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
-                               SS7_ASSERT;
+                               return 1;
                        } else {
                                SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
                        }
index 5e6a246ba2035c13b951b138e04d4e278ce17cb5..ac7a61646f6be7b9d0a48335b09d96eee8e314c2 100644 (file)
@@ -1029,6 +1029,9 @@ ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circui
        
        /* extract the affected infId from the circuit structure */
        infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId;
+
+       /* set the interface to paused */
+       sngss7_set_flag(&g_ftdm_sngss7_data.cfg.isupIntf[infId], SNGSS7_PAUSED);
        
        /* go through all the circuits now and find any other circuits on this infId */
        i = 1;
@@ -1050,6 +1053,7 @@ ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circui
        
                        /* check if the circuit is fully started */
                        if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_IN_THREAD)) {
+                               SS7_DEBUG_CHAN(ftdmchan, "Rx PAUSE%s\n", "");
                                /* set the pause flag on the channel */
                                sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
                        }
@@ -1081,6 +1085,9 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu
        /* extract the affect infId from the circuit structure */
        infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId;
 
+       /* set the interface to resumed */
+       sngss7_clear_flag(&g_ftdm_sngss7_data.cfg.isupIntf[infId], SNGSS7_PAUSED);
+
        /* go through all the circuits now and find any other circuits on this infId */
        i = 1;
        while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) {
@@ -1101,6 +1108,8 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu
 
                        /* only resume if we are paused */
                        if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) {
+                               SS7_DEBUG_CHAN(ftdmchan, "Rx RESUME%s\n", "");
+
                                /* set the resume flag on the channel */
                                sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
 
@@ -1527,7 +1536,7 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
        ftdm_channel_t          *ftdmchan = NULL;
        sngss7_span_data_t      *sngss7_span = NULL; 
        int                                     range;
-       int                             x;
+
 
        if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
                SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
@@ -1544,51 +1553,12 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
                return FTDM_FAIL;
        }
 
-       /* loop over the cics starting from circuit until range+1 */
-       for (x = circuit; x < (circuit + range + 1); x++) {
-               if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != VOICE) continue;
-               /* grab the circuit in question */
-               if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
-                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
-                       break;
-               }
-       
-               /* lock the channel */
-               ftdm_mutex_lock(ftdmchan->mutex);
-
-               /* fill in the span structure for this circuit */
-               sngss7_span = ftdmchan->span->mod_data;
-               sngss7_span->rx_grs.circuit = circuit; 
-               sngss7_span->rx_grs.range = range;
-
-               SS7_INFO_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", 
-                                                               g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, 
-                                                               (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range));
-
-               /* flag the channel as having received a reset */
-               sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX);
-
-               switch (ftdmchan->state) {
-               /**************************************************************************/
-               case FTDM_CHANNEL_STATE_RESTART:
-
-                       /* go to idle so that we can redo the restart state*/
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
-
-                       break;
-               /**************************************************************************/
-               default:
-
-                       /* set the state of the channel to restart...the rest is done by the chan monitor */
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
-                       break;
-               /**************************************************************************/
-               }
-
-               /* unlock the channel again before we exit */
-               ftdm_mutex_unlock(ftdmchan->mutex);
+       /* fill in the span structure for this circuit */
+       sngss7_span = ftdmchan->span->mod_data;
+       sngss7_span->rx_grs.circuit = circuit; 
+       sngss7_span->rx_grs.range = range;
 
-       }
+       /* the reset will be started in the main thread by "check_if_rx_grs_started" */
 
        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
        return FTDM_SUCCESS;
@@ -1599,10 +1569,16 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
 {
        SS7_FUNC_TRACE_ENTER(__FUNCTION__);
 
-       sngss7_chan_data_t  *sngss7_info = NULL;
-       ftdm_channel_t    *ftdmchan = NULL;
+       sngss7_chan_data_t      *sngss7_info = NULL;
+       ftdm_channel_t          *ftdmchan = NULL;
+       sngss7_span_data_t      *sngss7_span = NULL; 
        int                                     range;
-       int                             x;
+
+       if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) {
+               SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
+               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               return FTDM_FAIL;
+       }
 
        /* extract the range value from the event structure */
        if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) {
@@ -1613,70 +1589,20 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ
                return FTDM_FAIL;
        }
 
-       /* go through all the circuits in the range */
-       for ( x = circuit; x < (circuit + range + 1); x++) {
-
-               /* grab the circuit in question */
-               if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
-                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit);
-                       break;
-               }
-
-               /* lock the channel */
-               ftdm_mutex_lock(ftdmchan->mutex);
-               
-               SS7_INFO_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", 
-                                                               g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, 
-                                                               (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range));
-
-               switch (ftdmchan->state) {
-               /**********************************************************************/
-               case FTDM_CHANNEL_STATE_RESTART:
-                       
-                       /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
-                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
-
-                       /* go to DOWN */
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
-
-                       break;
-               /**********************************************************************/
-               case FTDM_CHANNEL_STATE_DOWN:
-
-                       /* do nothing, just drop the message */
-                       SS7_DEBUG("Receveived GRA in down state, dropping\n");
-
-                       break;
-               /**********************************************************************/
-               case FTDM_CHANNEL_STATE_TERMINATING:
-               case FTDM_CHANNEL_STATE_HANGUP:
-               case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-                       
-                       /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
-                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
-
-                       break;
-               /**********************************************************************/
-               default:
-                       /* ITU Q764-2.9.5.1.c -> release the circuit */
-                       if ((siStaEvnt != NULL) &&
-                               (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) &&
-                               (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) {
-                               ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val;
-                       } else {
-                               ftdmchan->caller_data.hangup_cause = 98;        /* Message not compatiable with call state */
-                       }
+       /* fill in the span structure for this circuit */
+       sngss7_span = ftdmchan->span->mod_data;
+       sngss7_span->rx_gra.circuit = circuit; 
+       sngss7_span->rx_gra.range = range;
 
-                       /* go to terminating to hang up the call */
-                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
-                       break;
-               /**********************************************************************/
-               }
+       /* check if there is a cause value in the GRA */
+       if ((siStaEvnt != NULL) &&
+               (siStaEvnt->causeDgn.eh.pres == PRSNT_NODEF) &&
+               (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) {
 
-               /* unlock the channel again before we exit */
-               ftdm_mutex_unlock(ftdmchan->mutex);
+               sngss7_span->rx_gra.cause = siStaEvnt->causeDgn.causeVal.val;
+       }
 
-       } /* for (( x = 0; x < (circuit + range); x++) */
+       /* the reset will be started in the main thread by "check_if_rx_gra_started" */
        
        SS7_FUNC_TRACE_EXIT(__FUNCTION__);
        return FTDM_SUCCESS;
index 3ef8db53d1b43d081fbd8b073c04656d534814d4..ce9423cd00bf3f63752f119a60e79fdddc5b069c 100644 (file)
@@ -46,7 +46,7 @@ ftdm_sngss7_data_t g_ftdm_sngss7_data;
 
 /* PROTOTYPES *****************************************************************/
 static void *ftdm_sangoma_ss7_run (ftdm_thread_t * me, void *obj);
-static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan);
+void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan);
 static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event);
 
 static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
@@ -342,8 +342,16 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
                /**********************************************************************/
                } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */
 
+               /* check if there is a GRA to proccess on the span */
+               if (sngss7_span->rx_gra.range > 0) {
+                       check_if_rx_gra_started(ftdmspan);
+               } /* if (sngss7->span->rx_gra.range > 0) */
+
                /* check if there is a GRS being processed on the span */
                if (sngss7_span->rx_grs.range > 0) {
+                       /* check if the rx_grs has started */
+                       check_if_rx_grs_started(ftdmspan);
+
                        /* check if the rx_grs has cleared */
                        check_if_rx_grs_processed(ftdmspan);
                } /* if (sngss7_span->rx_grs.range > 0) */
@@ -452,7 +460,7 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
 }
 
 /******************************************************************************/
-static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
+void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 {
        sngss7_chan_data_t      *sngss7_info = ftdmchan->call_data;
        int                             i = 0;
@@ -727,6 +735,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
        /**************************************************************************/
        case FTDM_CHANNEL_STATE_DOWN:   /*the call is finished and removed */
 
+               if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
+                       SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
+                       break;
+               }
+
                /* check if there is a reset response that needs to be sent */
                if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) {
                        /* send a RSC-RLC */
@@ -776,6 +789,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
                        sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX);
                        sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_BASE);
                        sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_SENT);
+                       
+                       /* clean out the spans GRA structure */
+                       sngss7_span_data_t *span = ftdmchan->span->mod_data;
+                       span->rx_gra.circuit = 0;
+                       span->rx_gra.range = 0;
                }
 
                /* check if we came from reset (aka we just processed a reset) */
@@ -965,6 +983,7 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 
                /**********************************************************************/
                if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing RESUME%s\n", "");
 
                        /* clear the RESUME flag */
                        sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME);
@@ -990,6 +1009,7 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
                } /* if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) */
 
                if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) {
+                       SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE%s\n", "");
 
                        /* bring the sig status down */
                        sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
@@ -1165,9 +1185,10 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
        /* check if there is a pending state change, give it a bit to clear */
        if (check_for_state_change(ftdmchan)) {
                SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
-               ftdm_mutex_unlock(ftdmchan->mutex);
-               SS7_FUNC_TRACE_EXIT(__FUNCTION__);
+               /* check if we need to die */
                SS7_ASSERT;
+               /* end the request */
+               goto outgoing_fail;
        };
 
        /* check if the channel sig state is UP */
@@ -1278,6 +1299,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
        ftdm_channel_t          *ftdmchan = NULL;
        sngss7_chan_data_t      *sngss7_info = NULL;
        sngss7_span_data_t      *sngss7_span = NULL;
+       sng_isup_inf_t          *sngss7_intf = NULL;
        int                             x;
 
 
@@ -1290,12 +1312,22 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
                if (ftdmchan->call_data == NULL) continue;
                sngss7_info = ftdmchan->call_data;
                sngss7_span = ftdmchan->span->mod_data;
+               sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
+
 
                /* lock the channel */
                ftdm_mutex_lock(ftdmchan->mutex);
 
-               /* throw the pause flag */
-               sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
+               /* check if the interface is paused or resumed */
+               if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
+                       /* throw the pause flag */
+                       sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME);
+                       sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
+               } else {
+                       /* throw the pause flag */
+                       sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED);
+                       sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
+               }
 #if 0
                /* throw the grp reset flag */
                sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
index 850bbf0d1a3d51934e9676567d886f24b0402596..ae2412381cb29515bb64050e4c75a43a87b51373 100644 (file)
@@ -79,7 +79,8 @@ typedef enum {
 
 typedef enum {
        CONFIGURED              = (1 << 0),
-       ACTIVE                  = (1 << 1)
+       ACTIVE                  = (1 << 1),
+       SNGSS7_PAUSED   = (1 << 7)
 } sng_flag_t;
 
 typedef struct sng_mtp_link {
@@ -335,6 +336,7 @@ typedef struct sngss7_group_data {
        uint32_t                                range;
        uint8_t                                 status[255];
        uint8_t                                 type;
+       uint8_t                                 cause;
 }sngss7_group_data_t;
 
 typedef struct sngss7_chan_data {
@@ -353,6 +355,7 @@ typedef struct sngss7_chan_data {
 typedef struct sngss7_span_data {
        ftdm_sched_t                    *sched;
        sngss7_group_data_t             rx_grs;
+       sngss7_group_data_t             rx_gra;
        sngss7_group_data_t             tx_grs;
        sngss7_group_data_t             rx_cgb;
        sngss7_group_data_t             tx_cgb;
@@ -427,6 +430,8 @@ extern int                          cmbLinkSetId;
 /******************************************************************************/
 
 /* PROTOTYPES *****************************************************************/
+void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan);
+
 void handle_sng_log(uint8_t level, char *fmt,...);
 void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta);
 void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
@@ -546,7 +551,9 @@ void handle_isup_t35(void *userdata);
 
 ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data);
 
+ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan);
 ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan);
+ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan);
 ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan);
 /******************************************************************************/
 
@@ -678,7 +685,14 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan);
 #define sngss7_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
 #define sngss7_set_flag(obj, flag)   ((obj)->flags |= (flag))
 
-# define SS7_ASSERT    *(int*)0=0;
+#ifdef SS7_PRODUCTION
+# define SS7_ASSERT \
+       SS7_INFO_CHAN(ftdmchan,"Production Mode, continuing%s\n", "");
+#else
+# define SS7_ASSERT    \
+       SS7_ERROR_CHAN(ftdmchan, "Debugging Mode, ending%s\n", ""); \
+       *(int*)0=0;
+#endif
 /******************************************************************************/
 
 /******************************************************************************/
index aaffeb0a3697879b394313047bfbce12e0a8c152..8e7c6496aaef6d1594c1c88ab1ee7047d164dc7e 100644 (file)
@@ -57,7 +57,9 @@ unsigned long get_unique_id(void);
 
 ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
 
+ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan);
 ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan);
+ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan);
 ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan);
 /******************************************************************************/
 
@@ -445,6 +447,68 @@ unsigned long get_unique_id(void)
        return(sngss7_id);
 }
 
+/******************************************************************************/
+ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan)
+{
+       ftdm_channel_t          *ftdmchan = NULL;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       sngss7_span_data_t      *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
+       int                             i;
+
+       for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) {
+
+               /* extract the channel in question */
+               if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+                       continue;
+               }
+
+               /* check if the GRP_RESET_RX flag is already up */
+               if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) {
+                       /* we have already processed this channel...move along */
+                       continue;
+               }
+
+               /* lock the channel */
+               ftdm_mutex_lock(ftdmchan->mutex);
+
+               /* clear up any pending state changes */
+               while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+                       ftdm_sangoma_ss7_process_state_change (ftdmchan);
+               }
+
+               SS7_INFO_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", 
+                               g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic, 
+                               (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic + sngss7_span->rx_grs.range));
+
+               /* flag the channel as having received a reset */
+               sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX);
+
+               switch (ftdmchan->state) {
+               /**************************************************************************/
+               case FTDM_CHANNEL_STATE_RESTART:
+
+                       /* go to idle so that we can redo the restart state*/
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
+
+                       break;
+               /**************************************************************************/
+               default:
+
+                       /* set the state of the channel to restart...the rest is done by the chan monitor */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
+                       break;
+               /**************************************************************************/
+               } /* switch (ftdmchan->state) */
+
+               /* unlock the channel again before we exit */
+               ftdm_mutex_unlock(ftdmchan->mutex);
+
+       } /* for (chans in GRS */
+
+       return FTDM_SUCCESS;
+}
+
 /******************************************************************************/
 ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
 {
@@ -493,7 +557,10 @@ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan)
                /* extract the channel in question */
                if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
                        SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i);
+                       /* check if we need to die */
                        SS7_ASSERT;
+                       /* move along */
+                       continue;
                }
 
                /* throw the GRP reset flag complete flag */
@@ -534,6 +601,91 @@ GRS_UNLOCK_ALL:
        return FTDM_SUCCESS;
 }
 
+/******************************************************************************/
+ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan)
+{
+       ftdm_channel_t          *ftdmchan = NULL;
+       sngss7_chan_data_t  *sngss7_info = NULL;
+       sngss7_span_data_t      *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
+       int                             i;
+
+       for ( i = sngss7_span->rx_gra.circuit; i < (sngss7_span->rx_gra.circuit + sngss7_span->rx_gra.range + 1); i++) {
+
+               /* extract the channel in question */
+               if (extract_chan_data(i, &sngss7_info, &ftdmchan)) {
+                       SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i);
+                       continue;
+               }
+
+               /* check if the channel is already procoessing the GRA */
+               if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
+                       /* move along */
+                       continue;
+               }
+
+               /* lock the channel */
+               ftdm_mutex_lock(ftdmchan->mutex);
+
+               /* clear up any pending state changes */
+               while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+                       ftdm_sangoma_ss7_process_state_change (ftdmchan);
+               }
+
+               SS7_INFO_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", 
+                               g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic, 
+                               (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic + sngss7_span->rx_gra.range));
+
+               switch (ftdmchan->state) {
+               /**********************************************************************/
+               case FTDM_CHANNEL_STATE_RESTART:
+                       
+                       /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
+                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+
+                       /* go to DOWN */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
+
+                       break;
+               /**********************************************************************/
+               case FTDM_CHANNEL_STATE_DOWN:
+
+                       /* do nothing, just drop the message */
+                       SS7_DEBUG("Receveived GRA in down state, dropping\n");
+
+                       break;
+               /**********************************************************************/
+               case FTDM_CHANNEL_STATE_TERMINATING:
+               case FTDM_CHANNEL_STATE_HANGUP:
+               case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                       
+                       /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */
+                       sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP);
+
+                       break;
+               /**********************************************************************/
+               default:
+                       /* ITU Q764-2.9.5.1.c -> release the circuit */
+                       if (sngss7_span->rx_gra.cause != 0) {
+                               ftdmchan->caller_data.hangup_cause = sngss7_span->rx_gra.cause;
+                       } else {
+                               ftdmchan->caller_data.hangup_cause = 98;        /* Message not compatiable with call state */
+                       }
+
+                       /* go to terminating to hang up the call */
+                       ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
+                       break;
+               /**********************************************************************/
+               }
+
+               /* unlock the channel again before we exit */
+               ftdm_mutex_unlock(ftdmchan->mutex);
+
+       } /* for ( circuits in request */
+
+
+       return FTDM_SUCCESS;
+}
+
 /******************************************************************************/
 ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan)
 {
@@ -564,6 +716,11 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan)
                /* if we have the PAUSED flag and the sig status is still UP */
                if ((sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) &&
                        (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP))) {
+
+                       /* clear up any pending state changes */
+                       while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+                               ftdm_sangoma_ss7_process_state_change (ftdmchan);
+                       }
                        
                        /* throw the channel into SUSPENDED to process the flag */
                        /* after doing this once the sig status will be down */
@@ -573,6 +730,13 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan)
                /* if the RESUME flag is up go to SUSPENDED to process the flag */
                /* after doing this the flag will be cleared */
                if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) {
+
+                       /* clear up any pending state changes */
+                       while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
+                               ftdm_sangoma_ss7_process_state_change (ftdmchan);
+                       }
+
+                       /* got SUSPENDED state to clear the flag */
                        ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
                }