root/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ftdm_sangoma_ss7_run
  2. ftdm_sangoma_ss7_process_stack_event
  3. ftdm_sangoma_ss7_process_state_change
  4. FIO_CHANNEL_OUTGOING_CALL_FUNCTION
  5. FIO_CHANNEL_REQUEST_FUNCTION
  6. FIO_CHANNEL_GET_SIG_STATUS_FUNCTION
  7. FIO_CHANNEL_SET_SIG_STATUS_FUNCTION
  8. ftdm_sangoma_ss7_start
  9. ftdm_sangoma_ss7_stop
  10. FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION
  11. FIO_SIG_LOAD_FUNCTION
  12. FIO_SIG_UNLOAD_FUNCTION
  13. FIO_API_FUNCTION
  14. FIO_IO_LOAD_FUNCTION

   1 /*
   2  * Copyright (c) 2009, Konrad Hammel <konrad@sangoma.com>
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  *
   9  * * Redistributions of source code must retain the above copyright
  10  * notice, this list of conditions and the following disclaimer.
  11  *
  12  * * Redistributions in binary form must reproduce the above copyright
  13  * notice, this list of conditions and the following disclaimer in the
  14  * documentation and/or other materials provided with the distribution.
  15  *
  16  * * Neither the name of the original author; nor the names of any contributors
  17  * may be used to endorse or promote products derived from this software
  18  * without specific prior written permission.
  19  *
  20  *
  21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  24  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  25  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  26  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  27  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  28  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  29  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  30  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 
  34 /* INCLUDE ********************************************************************/
  35 #include "ftmod_sangoma_ss7_main.h"
  36 /******************************************************************************/
  37 
  38 /* DEFINES ********************************************************************/
  39 /******************************************************************************/
  40 
  41 /* GLOBALS ********************************************************************/
  42 static sng_isup_event_interface_t sng_event;
  43 static ftdm_io_interface_t g_ftdm_sngss7_interface;
  44 ftdm_sngss7_data_t g_ftdm_sngss7_data;
  45 /******************************************************************************/
  46 
  47 /* PROTOTYPES *****************************************************************/
  48 static void *ftdm_sangoma_ss7_run (ftdm_thread_t * me, void *obj);
  49 void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan);
  50 static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event);
  51 
  52 static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
  53 static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span);
  54 /******************************************************************************/
  55 
  56 /* STATE MAP ******************************************************************/
  57 ftdm_state_map_t sangoma_ss7_state_map = {
  58   {
  59    {
  60         ZSD_INBOUND,
  61         ZSM_UNACCEPTABLE,
  62         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
  63         {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_DOWN,
  64          FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_COLLECT,
  65          FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_PROGRESS,
  66          FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP,
  67          FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING,
  68          FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
  69         },
  70    {
  71         ZSD_INBOUND,
  72         ZSM_UNACCEPTABLE,
  73         {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
  74         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING,
  75          FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
  76          FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_IDLE, FTDM_END}
  77         },
  78         {
  79         ZSD_INBOUND,
  80         ZSM_UNACCEPTABLE,
  81         {FTDM_CHANNEL_STATE_IDLE, FTDM_END},
  82         {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
  83         },
  84    {
  85         ZSD_INBOUND,
  86         ZSM_UNACCEPTABLE,
  87         {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
  88         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
  89          FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
  90         },
  91    {
  92         ZSD_INBOUND,
  93         ZSM_UNACCEPTABLE,
  94         {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END},
  95         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
  96          FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
  97         },
  98    {
  99         ZSD_INBOUND,
 100         ZSM_UNACCEPTABLE,
 101         {FTDM_CHANNEL_STATE_COLLECT, FTDM_END},
 102         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 103          FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_RING, FTDM_END}
 104         },
 105    {
 106         ZSD_INBOUND,
 107         ZSM_UNACCEPTABLE,
 108         {FTDM_CHANNEL_STATE_RING, FTDM_END},
 109         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 110          FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
 111          FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}
 112         },
 113    {
 114         ZSD_INBOUND,
 115         ZSM_UNACCEPTABLE,
 116         {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
 117         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 118          FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
 119          FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}
 120         },
 121    {
 122         ZSD_INBOUND,
 123         ZSM_UNACCEPTABLE,
 124         {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
 125         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 126          FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
 127          FTDM_CHANNEL_STATE_UP, FTDM_END}
 128         },
 129    {
 130         ZSD_INBOUND,
 131         ZSM_UNACCEPTABLE,
 132         {FTDM_CHANNEL_STATE_UP, FTDM_END},
 133         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 134          FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
 135         },
 136    {
 137         ZSD_INBOUND,
 138         ZSM_UNACCEPTABLE,
 139         {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
 140         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 141          FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
 142         },
 143    {
 144         ZSD_INBOUND,
 145         ZSM_UNACCEPTABLE,
 146         {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
 147         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 148          FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
 149         },
 150    {
 151         ZSD_INBOUND,
 152         ZSM_UNACCEPTABLE,
 153         {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
 154         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 155          FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
 156         },
 157    {
 158         ZSD_INBOUND,
 159         ZSM_UNACCEPTABLE,
 160         {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
 161         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 162          FTDM_CHANNEL_STATE_DOWN, FTDM_END}
 163         },
 164         /**************************************************************************/
 165    {
 166         ZSD_OUTBOUND,
 167         ZSM_UNACCEPTABLE,
 168         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END},
 169         {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_DOWN,
 170          FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_DIALING,
 171          FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA,
 172          FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_CANCEL,
 173          FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
 174          FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
 175         },
 176    {
 177         ZSD_OUTBOUND,
 178         ZSM_UNACCEPTABLE,
 179         {FTDM_CHANNEL_STATE_RESTART, FTDM_END},
 180         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING,
 181          FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE,
 182          FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_IDLE, FTDM_END}
 183         },
 184         {
 185         ZSD_OUTBOUND,
 186         ZSM_UNACCEPTABLE,
 187         {FTDM_CHANNEL_STATE_IDLE, FTDM_END},
 188         {FTDM_CHANNEL_STATE_RESTART, FTDM_END}
 189         },
 190    {
 191         ZSD_OUTBOUND,
 192         ZSM_UNACCEPTABLE,
 193         {FTDM_CHANNEL_STATE_DOWN, FTDM_END},
 194         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 195          FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}
 196         },
 197    {
 198         ZSD_OUTBOUND,
 199         ZSM_UNACCEPTABLE,
 200         {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END},
 201         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 202          FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_DOWN, FTDM_END}
 203         },
 204    {
 205         ZSD_OUTBOUND,
 206         ZSM_UNACCEPTABLE,
 207         {FTDM_CHANNEL_STATE_DIALING, FTDM_END},
 208         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 209          FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING,
 210          FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS,
 211          FTDM_CHANNEL_STATE_UP, FTDM_END}
 212         },
 213    {
 214         ZSD_OUTBOUND,
 215         ZSM_UNACCEPTABLE,
 216         {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END},
 217         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 218          FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
 219          FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}
 220         },
 221    {
 222         ZSD_OUTBOUND,
 223         ZSM_UNACCEPTABLE,
 224         {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END},
 225         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 226          FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP,
 227          FTDM_CHANNEL_STATE_UP, FTDM_END}
 228         },
 229    {
 230         ZSD_OUTBOUND,
 231         ZSM_UNACCEPTABLE,
 232         {FTDM_CHANNEL_STATE_UP, FTDM_END},
 233         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 234          FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
 235         },
 236    {
 237         ZSD_OUTBOUND,
 238         ZSM_UNACCEPTABLE,
 239         {FTDM_CHANNEL_STATE_CANCEL, FTDM_END},
 240         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 241          FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
 242         },
 243    {
 244         ZSD_OUTBOUND,
 245         ZSM_UNACCEPTABLE,
 246         {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END},
 247         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 248          FTDM_CHANNEL_STATE_HANGUP, FTDM_END}
 249         },
 250    {
 251         ZSD_OUTBOUND,
 252         ZSM_UNACCEPTABLE,
 253         {FTDM_CHANNEL_STATE_HANGUP, FTDM_END},
 254         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 255          FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}
 256         },
 257    {
 258         ZSD_OUTBOUND,
 259         ZSM_UNACCEPTABLE,
 260         {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END},
 261         {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART,
 262          FTDM_CHANNEL_STATE_DOWN, FTDM_END}
 263         },
 264    }
 265 };
 266 
 267 /******************************************************************************/
 268 
 269 /* MONITIOR THREADS ***********************************************************/
 270 static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
 271 {
 272         ftdm_interrupt_t        *ftdm_sangoma_ss7_int[2];
 273         ftdm_span_t             *ftdmspan = (ftdm_span_t *) obj;
 274         ftdm_channel_t          *ftdmchan = NULL;
 275         sngss7_event_data_t     *sngss7_event = NULL;
 276         sngss7_span_data_t      *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data;
 277 
 278         ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id);
 279 
 280         /* set IN_THREAD flag so that we know this thread is running */
 281         ftdm_set_flag (ftdmspan, FTDM_SPAN_IN_THREAD);
 282 
 283         /* get an interrupt queue for this span for channel state changes */
 284         if (ftdm_queue_get_interrupt (ftdmspan->pendingchans, &ftdm_sangoma_ss7_int[0]) != FTDM_SUCCESS) {
 285                 SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for channel state changes!\n", ftdmspan->span_id);
 286                 goto ftdm_sangoma_ss7_run_exit;
 287         }
 288 
 289         /* get an interrupt queue for this span for Trillium events */
 290         if (ftdm_queue_get_interrupt (sngss7_span->event_queue, &ftdm_sangoma_ss7_int[1]) != FTDM_SUCCESS) {
 291                 SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for Trillium event queue!\n", ftdmspan->span_id);
 292                 goto ftdm_sangoma_ss7_run_exit;
 293         }
 294 
 295         while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) {
 296 
 297                 /* check the channel state queue for an event*/ 
 298                 switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, 2, 100))) {
 299                 /**********************************************************************/
 300                 case FTDM_SUCCESS:      /* process all pending state changes */
 301 
 302                         /* clean out all pending channel state changes */
 303                         while ((ftdmchan = ftdm_queue_dequeue (ftdmspan->pendingchans))) {
 304                                 
 305                                 /*first lock the channel */
 306                                 ftdm_mutex_lock(ftdmchan->mutex);
 307 
 308                                 /* process state changes for this channel until they are all done */
 309                                 while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 310                                         ftdm_sangoma_ss7_process_state_change (ftdmchan);
 311                                 }
 312  
 313                                 /* unlock the channel */
 314                                 ftdm_mutex_unlock (ftdmchan->mutex);                            
 315                         }/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans)))  */
 316 
 317                         /* clean out all pending stack events */
 318                         while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) {
 319                                 ftdm_sangoma_ss7_process_stack_event(sngss7_event);
 320                                 ftdm_safe_free(sngss7_event);
 321                         }/* while ((sngss7_event = ftdm_queue_dequeue(ftdmspan->signal_data->event_queue))) */
 322 
 323                         /* signal the core that sig events are queued for processing */
 324                         ftdm_span_trigger_signals(ftdmspan);
 325 
 326                         break;
 327                 /**********************************************************************/
 328                 case FTDM_TIMEOUT:
 329                         SS7_DEVEL_DEBUG ("ftdm_interrupt_wait timed-out on span = %d\n",ftdmspan->span_id);
 330 
 331                         break;
 332                 /**********************************************************************/
 333                 case FTDM_FAIL:
 334                         SS7_ERROR ("ftdm_interrupt_wait returned error!\non span = %d\n", ftdmspan->span_id);
 335 
 336                         break;
 337                 /**********************************************************************/
 338                 default:
 339                         SS7_ERROR("ftdm_interrupt_wait returned with unknown code on span = %d\n",ftdmspan->span_id);
 340 
 341                         break;
 342                 /**********************************************************************/
 343                 } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */
 344 
 345                 /* check if there is a GRA to proccess on the span */
 346                 if (sngss7_span->rx_gra.range > 0) {
 347                         check_if_rx_gra_started(ftdmspan);
 348                 } /* if (sngss7->span->rx_gra.range > 0) */
 349 
 350                 /* check if there is a GRS being processed on the span */
 351                 if (sngss7_span->rx_grs.range > 0) {
 352                         /* check if the rx_grs has started */
 353                         check_if_rx_grs_started(ftdmspan);
 354 
 355                         /* check if the rx_grs has cleared */
 356                         check_if_rx_grs_processed(ftdmspan);
 357                 } /* if (sngss7_span->rx_grs.range > 0) */
 358 
 359                 /* check each channel on the span to see if there is an un-procressed SUS/RES flag */
 360                 check_for_res_sus_flag(ftdmspan);
 361         } /* master while loop */
 362 
 363         /* clear the IN_THREAD flag so that we know the thread is done */
 364         ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD);
 365 
 366         ftdm_log (FTDM_LOG_INFO,"ftmod_sangoma_ss7 monitor thread for span=%u stopping.\n",ftdmspan->span_id);
 367 
 368         return NULL;
 369 
 370 ftdm_sangoma_ss7_run_exit:
 371 
 372         /* clear the IN_THREAD flag so that we know the thread is done */
 373         ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD);
 374 
 375         ftdm_log (FTDM_LOG_INFO,"ftmod_sangoma_ss7 monitor thread for span=%u stopping due to error.\n",ftdmspan->span_id);
 376 
 377         ftdm_sangoma_ss7_stop (ftdmspan);
 378 
 379         return NULL;
 380 }
 381 
 382 /******************************************************************************/
 383 static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event)
 384 {
 385         sngss7_chan_data_t  *sngss7_info ;
 386         ftdm_channel_t    *ftdmchan;
 387 
 388         /* get the ftdmchan and ss7_chan_data from the circuit */
 389         if (extract_chan_data(sngss7_event->circuit, &sngss7_info, &ftdmchan)) {
 390                 SS7_ERROR("Failed to extract channel data for circuit = %d!\n", sngss7_event->circuit);
 391                 return;
 392         }
 393 
 394         /* now that we have the right channel...put a lock on it so no-one else can use it */
 395         ftdm_mutex_lock(ftdmchan->mutex);
 396 
 397         /* while there's a state change present on this channel process it */
 398         while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 399                 ftdm_sangoma_ss7_process_state_change(ftdmchan);
 400         }
 401 
 402         /* figure out the type of event and send it to the right handler */
 403         switch (sngss7_event->event_id) {
 404         /**************************************************************************/
 405         case (SNGSS7_CON_IND_EVENT):
 406                 handle_con_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit,  &sngss7_event->event.siConEvnt);
 407                 break;
 408         /**************************************************************************/
 409         case (SNGSS7_CON_CFM_EVENT):
 410                 handle_con_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit,  &sngss7_event->event.siConEvnt);
 411                 break;
 412         /**************************************************************************/
 413         case (SNGSS7_CON_STA_EVENT):
 414                 handle_con_sta(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit,  &sngss7_event->event.siCnStEvnt, sngss7_event->evntType);
 415                 break;
 416         /**************************************************************************/
 417         case (SNGSS7_REL_IND_EVENT):
 418                 handle_rel_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit,  &sngss7_event->event.siRelEvnt);
 419                 break;
 420         /**************************************************************************/
 421         case (SNGSS7_REL_CFM_EVENT):
 422                 handle_rel_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit,  &sngss7_event->event.siRelEvnt);
 423                 break;
 424         /**************************************************************************/
 425         case (SNGSS7_DAT_IND_EVENT):
 426                 handle_dat_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit,  &sngss7_event->event.siInfoEvnt);
 427                 break;
 428         /**************************************************************************/
 429         case (SNGSS7_FAC_IND_EVENT):
 430                 handle_fac_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType,  &sngss7_event->event.siFacEvnt);
 431                 break;
 432         /**************************************************************************/
 433         case (SNGSS7_FAC_CFM_EVENT):
 434                 handle_fac_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType,  &sngss7_event->event.siFacEvnt);
 435                 break;
 436         /**************************************************************************/
 437         case (SNGSS7_UMSG_IND_EVENT):
 438                 handle_umsg_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit);
 439                 break;
 440         /**************************************************************************/
 441         case (SNGSS7_STA_IND_EVENT):
 442                 handle_sta_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->globalFlg, sngss7_event->evntType,  &sngss7_event->event.siStaEvnt);
 443                 break;
 444         /**************************************************************************/
 445         default:
 446                 SS7_ERROR("Unknown Event Id!\n");
 447                 break;
 448         /**************************************************************************/
 449         } /* switch (sngss7_event->event_id) */
 450 
 451         /* while there's a state change present on this channel process it */
 452         while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
 453                 ftdm_sangoma_ss7_process_state_change(ftdmchan);
 454         }
 455 
 456         /* unlock the channel */
 457         ftdm_mutex_unlock(ftdmchan->mutex);
 458 
 459         return;
 460 }
 461 
 462 /******************************************************************************/
 463 void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
 464 {
 465         sngss7_chan_data_t      *sngss7_info = ftdmchan->call_data;
 466         int                             i = 0;
 467         ftdm_sigmsg_t           sigev;
 468 
 469         memset (&sigev, 0, sizeof (sigev));
 470 
 471         sigev.chan_id = ftdmchan->chan_id;
 472         sigev.span_id = ftdmchan->span_id;
 473         sigev.channel = ftdmchan;
 474 
 475         SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state));
 476 
 477         /* clear the state change flag...since we might be setting a new state */
 478         ftdm_clear_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE);
 479         
 480         /*check what state we are supposed to be in */
 481         switch (ftdmchan->state) {
 482         /**************************************************************************/
 483         case FTDM_CHANNEL_STATE_COLLECT:        /* IAM received but wating on digits */
 484 
 485                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 486                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 487                         break;
 488                 }
 489 
 490                 while (ftdmchan->caller_data.dnis.digits[i] != '\0'){
 491                         i++;
 492                 }
 493 
 494                 /* check if the end of pulsing (ST) character has arrived or the right number of digits */
 495                 if (ftdmchan->caller_data.dnis.digits[i-1] == 'F') {
 496                         SS7_DEBUG_CHAN(ftdmchan, "Received the end of pulsing character %s\n", "");
 497 
 498                         /* remove the ST */
 499                         ftdmchan->caller_data.dnis.digits[i-1] = '\0';
 500                         
 501                         /*now go to the RING state */
 502                         ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
 503                         
 504                 } else if (i >= g_ftdm_sngss7_data.min_digits) {
 505                         SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits);
 506 
 507                         /*now go to the RING state */
 508                         ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING);
 509                         
 510                 } else {
 511                         SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n",
 512                                                 i,
 513                                                 g_ftdm_sngss7_data.min_digits,
 514                                                 ftdmchan->caller_data.dnis.digits);
 515 
 516                         /* start ISUP t35 */
 517                         if (ftdm_sched_timer (sngss7_info->t35.sched,
 518                                                                         "t35",
 519                                                                         sngss7_info->t35.beat,
 520                                                                         sngss7_info->t35.callback,
 521                                                                         &sngss7_info->t35,
 522                                                                         &sngss7_info->t35.hb_timer_id)) {
 523 
 524                                 SS7_ERROR ("Unable to schedule timer, hanging up call!\n");
 525 
 526                                 ftdmchan->caller_data.hangup_cause = 41;
 527 
 528                                 /* set the flag to indicate this hangup is started from the local side */
 529                                 sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL);
 530 
 531                                 /* end the call */
 532                                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
 533                         } /* if (ftdm_sched_timer(sngss7_info->t35.sched, */
 534                 } /* checking ST/#digits */
 535 
 536           break;
 537 
 538         /**************************************************************************/
 539         case FTDM_CHANNEL_STATE_RING:   /*incoming call request */
 540 
 541                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 542                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 543                         break;
 544                 }
 545 
 546                 /* kill t35 if active */
 547                 if (sngss7_info->t35.hb_timer_id) {
 548                         ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id);
 549                 }
 550 
 551                 SS7_DEBUG_CHAN(ftdmchan, "Sending incoming call from %s to %s to FTDM core\n",
 552                                         ftdmchan->caller_data.ani.digits,
 553                                         ftdmchan->caller_data.dnis.digits);
 554 
 555 
 556                 /* we have enough information to inform FTDM of the call */
 557                 sigev.event_id = FTDM_SIGEVENT_START;
 558                 ftdm_span_send_signal (ftdmchan->span, &sigev);
 559 
 560                 break;
 561         /**************************************************************************/
 562         case FTDM_CHANNEL_STATE_DIALING:        /*outgoing call request */
 563 
 564                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 565                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 566                         break;
 567                 }
 568 
 569                 SS7_DEBUG_CHAN(ftdmchan, "Sending outgoing call from \"%s\" to \"%s\" to LibSngSS7\n",
 570                                            ftdmchan->caller_data.ani.digits,
 571                                            ftdmchan->caller_data.dnis.digits);
 572 
 573                 /*call sangoma_ss7_dial to make outgoing call */
 574                 ft_to_sngss7_iam(ftdmchan);
 575 
 576                 break;
 577         /**************************************************************************/
 578         case FTDM_CHANNEL_STATE_PROGRESS:
 579 
 580                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 581                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 582                         break;
 583                 }
 584 
 585                 /*check if the channel is inbound or outbound */
 586                 if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND))   {
 587                         /*OUTBOUND...so we were told by the line of this so noifiy the user */
 588                         sigev.event_id = FTDM_SIGEVENT_PROGRESS;
 589                         ftdm_span_send_signal (ftdmchan->span, &sigev);
 590 
 591                         ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
 592                 } else {
 593                         /* inbound call so we need to send out ACM */
 594                         ft_to_sngss7_acm (ftdmchan);
 595                 }
 596 
 597                 break;
 598         /**************************************************************************/
 599         case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 600 
 601                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 602                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 603                         break;
 604                 }
 605 
 606                 /* nothing to do at this time */
 607                 break;
 608         /**************************************************************************/
 609         case FTDM_CHANNEL_STATE_UP:     /*call is accpeted...both incoming and outgoing */
 610 
 611                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 612                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 613                         break;
 614                 }
 615 
 616                 /*check if the channel is inbound or outbound */
 617                 if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
 618                         /*OUTBOUND...so we were told by the line that the other side answered */
 619                         sigev.event_id = FTDM_SIGEVENT_UP;
 620                         ftdm_span_send_signal(ftdmchan->span, &sigev);
 621                 } else {
 622                         /*INBOUND...so FS told us it was going to answer...tell the stack */
 623                         ft_to_sngss7_anm(ftdmchan);
 624                 }
 625 
 626                 break;
 627         /**************************************************************************/
 628         case FTDM_CHANNEL_STATE_CANCEL:
 629 
 630                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 631                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 632                         break;
 633                 }
 634 
 635                 SS7_ERROR_CHAN(ftdmchan,"Hanging up call before informing user%s\n", " ");
 636 
 637                 /*now go to the HANGUP complete state */
 638                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
 639 
 640                 break;
 641         /**************************************************************************/
 642         case FTDM_CHANNEL_STATE_TERMINATING:    /*call is hung up remotely */
 643 
 644                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 645                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 646                         break;
 647                 }
 648 
 649                 /* set the flag to indicate this hangup is started from the remote side */
 650                 sngss7_set_flag (sngss7_info, FLAG_REMOTE_REL);
 651 
 652                 /*this state is set when the line is hanging up */
 653                 sigev.event_id = FTDM_SIGEVENT_STOP;
 654                 ftdm_span_send_signal (ftdmchan->span, &sigev);
 655 
 656                 break;
 657         /**************************************************************************/
 658         case FTDM_CHANNEL_STATE_HANGUP: /*call is hung up locally */
 659 
 660                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 661                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 662                         break;
 663                 }
 664 
 665                 /* check for remote hangup flag */
 666                 if (sngss7_test_flag (sngss7_info, FLAG_REMOTE_REL)) {
 667                         /* remote release ...do nothing here */
 668                         SS7_DEBUG_CHAN(ftdmchan,"Hanging up remotely requested call!%s\n", "");
 669                 } else if (sngss7_test_flag (sngss7_info, FLAG_GLARE)) {
 670                         /* release due to glare */
 671                         SS7_DEBUG_CHAN(ftdmchan,"Hanging up requested call do to glare%s\n", "");
 672                 } else  {
 673                         /* set the flag to indicate this hangup is started from the local side */
 674                         sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL);
 675 
 676                         /*this state is set when FS is hanging up...so tell the stack */
 677                         ft_to_sngss7_rel (ftdmchan);
 678 
 679                         SS7_DEBUG_CHAN(ftdmchan,"Hanging up locally requested call!%s\n", "");
 680                 }
 681 
 682                 /*now go to the HANGUP complete state */
 683                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
 684 
 685                 break;
 686 
 687         /**************************************************************************/
 688         case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 689 
 690                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 691                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 692                         break;
 693                 }
 694 
 695                 if (sngss7_test_flag (sngss7_info, FLAG_REMOTE_REL)) {
 696                         /* check if this hangup is from a tx RSC */
 697                         if (sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) {
 698                                 /* go to RESTART State until RSCa is received */
 699                                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART);
 700                         } else {
 701                                 /* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */
 702                                 if (!(sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) &&
 703                                         !(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
 704                                         !(sngss7_test_flag(sngss7_info, FLAG_GLARE))) {
 705 
 706                                         /* send out the release complete */
 707                                         ft_to_sngss7_rlc (ftdmchan);
 708                                 }
 709 
 710                                 /*now go to the DOWN state */
 711                                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 712                         }
 713 
 714                         SS7_DEBUG_CHAN(ftdmchan,"Completing remotely requested hangup!%s\n", "");
 715                 } else if (sngss7_test_flag (sngss7_info, FLAG_LOCAL_REL)) {
 716 
 717                         /* if this hang up is do to a rx RESET we need to sit here till the RSP arrives */
 718                         if (sngss7_test_flag (sngss7_info, FLAG_RESET_TX_RSP)) {
 719                                 /* go to the down state as we have already received RSC-RLC */
 720                                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 721                         }
 722 
 723                         /* if it's a local release the user sends us to down */
 724                         SS7_DEBUG_CHAN(ftdmchan,"Completing locally requested hangup!%s\n", "");
 725                 } else if (sngss7_test_flag (sngss7_info, FLAG_GLARE)) {
 726                         SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup due to glare!%s\n", "");
 727 
 728                         ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 729                 } else {
 730                         SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup for unknown reason!%s\n", "");
 731                 }
 732 
 733                 break;
 734 
 735         /**************************************************************************/
 736         case FTDM_CHANNEL_STATE_DOWN:   /*the call is finished and removed */
 737 
 738                 if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
 739                         SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
 740                         break;
 741                 }
 742 
 743                 /* check if there is a reset response that needs to be sent */
 744                 if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) {
 745                         /* send a RSC-RLC */
 746                         ft_to_sngss7_rsca (ftdmchan);
 747 
 748                         /* clear the reset flag  */
 749                         clear_rx_rsc_flags(sngss7_info);
 750                 } /* if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) */
 751 
 752                 /* check if there was a GRS that needs a GRA */
 753                 if ((sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) &&
 754                         (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) &&
 755                         (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT))) {
 756 
 757                         /* check if this is the base circuit and send out the GRA
 758                          * we insure that this is the last circuit to have the state change queued
 759                          */
 760                         sngss7_span_data_t *span = ftdmchan->span->mod_data;
 761                         if (span->rx_grs.circuit == sngss7_info->circuit->id) {
 762                                 /* send out the GRA */
 763                                 ft_to_sngss7_gra(ftdmchan);
 764 
 765                                 /* clean out the spans GRS structure */
 766                                 sngss7_span_data_t *span = ftdmchan->span->mod_data;
 767                                 span->rx_grs.circuit = 0;
 768                                 span->rx_grs.range = 0;
 769                         }
 770 
 771                         /* clear the grp reset flag */
 772                         clear_rx_grs_flags(sngss7_info);
 773                 }/*  if ( sngss7_test_flag ( sngss7_info, FLAG_GRP_RESET_RX ) ) */
 774 
 775                 /* check if we got the reset response */
 776                 if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) {
 777                         /* clear the reset flag  */
 778                         clear_tx_rsc_flags(sngss7_info);
 779                 } /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) */
 780 
 781                 if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) {
 782                         /* clear the reset flag  */
 783                         clear_tx_grs_flags(sngss7_info);
 784                         
 785                         /* clean out the spans GRA structure */
 786                         sngss7_span_data_t *span = ftdmchan->span->mod_data;
 787                         span->rx_gra.circuit = 0;
 788                         span->rx_gra.range = 0;
 789                 } /* if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) */
 790 
 791                 /* check if we came from reset (aka we just processed a reset) */
 792                 if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) || 
 793                         (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED)) {
 794 
 795                         /* check if reset flags are up indicating there is more processing to do yet */
 796                         if (!(sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) &&
 797                                 !(sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) &&
 798                                 !(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
 799                                 !(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
 800 
 801                                 /* now check if there is an active block */
 802                                 if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) &&
 803                                         !(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) &&
 804                                         !(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) &&
 805                                         !(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) &&
 806                                         !(sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) &&
 807                                         !(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) &&
 808                                         !(sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
 809                                 
 810                                         /* check if the sig status is down, and bring it up if it isn't */
 811                                         if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
 812                                                 SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", "");
 813                                                 /* all flags are down so we can bring up the sig status */
 814                                                 sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
 815                                                 sigev.sigstatus = FTDM_SIG_STATE_UP;
 816                                                 ftdm_span_send_signal (ftdmchan->span, &sigev);
 817                                         } /* if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) */
 818                                 } /* if !blocked */
 819                         } else {
 820                                 SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->flags);
 821                         
 822                                 /* there is still another reset pending so go back to reset*/
 823                                 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
 824                         }
 825                 } /* if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) */
 826 
 827                 /* check if t35 is active */
 828                 if (sngss7_info->t35.hb_timer_id) {
 829                         ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id);
 830                 }
 831 
 832                 /* clear all of the call specific data store in the channel structure */
 833                 sngss7_info->suInstId = 0;
 834                 sngss7_info->spInstId = 0;
 835                 sngss7_info->globalFlg = 0;
 836                 sngss7_info->spId = 0;
 837 
 838                 /* clear any call related flags */
 839                 sngss7_clear_flag (sngss7_info, FLAG_REMOTE_REL);
 840                 sngss7_clear_flag (sngss7_info, FLAG_LOCAL_REL);
 841 
 842 
 843                 if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) {
 844                         ftdm_channel_t *close_chan = ftdmchan;
 845                         /* close the channel */
 846                         ftdm_channel_close (&close_chan);
 847                 } /* if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) */
 848 
 849                 /* check if there is a glared call that needs to be processed */
 850                 if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) {
 851                         
 852                         /* clear the glare flag */
 853                         sngss7_clear_flag (sngss7_info, FLAG_GLARE);
 854 
 855                         /* check if we have an IAM stored...if we don't have one just exit */
 856                         if (sngss7_info->glare.circuit != 0) {
 857                                 /* send the saved call back in to us */
 858                                 handle_con_ind (0, 
 859                                                                 sngss7_info->glare.spInstId, 
 860                                                                 sngss7_info->glare.circuit, 
 861                                                                 &sngss7_info->glare.iam);
 862 
 863                                 /* clear the glare info */
 864                                 memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t));
 865                         } /* if (sngss7_info->glare.circuit != 0) */
 866                 } /* if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) */
 867 
 868                 break;
 869         /**************************************************************************/
 870         case FTDM_CHANNEL_STATE_RESTART:        /* CICs needs a Reset */
 871 
 872                 if (sngss7_test_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK)) {
 873                         if ((sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) ||
 874                                 (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX))) {
 875 
 876                                 SS7_DEBUG_CHAN(ftdmchan,"Incoming Reset request on CIC in UCIC block, removing UCIC block%s\n", "");
 877 
 878                                 /* set the unblk flag */
 879                                 sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK);
 880                                 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
 881 
 882                                 /* break out of the processing for now */
 883                                 break;
 884                         }
 885                 }
 886 
 887                 /* if we're not coming from HANGUP_COMPLETE we need to check for resets
 888                  * we can also check if we are in a PAUSED state (no point in sending message
 889                  */
 890                 if ((ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) &&
 891                         (!sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED))) {
 892 
 893                         /* check if this is an outgoing RSC */
 894                         if ((sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) &&
 895                                 !(sngss7_test_flag(sngss7_info, FLAG_RESET_SENT))) {
 896 
 897                                 /* send a reset request */
 898                                 ft_to_sngss7_rsc (ftdmchan);
 899                                 sngss7_set_flag(sngss7_info, FLAG_RESET_SENT);
 900 
 901                         } /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) */
 902         
 903                         /* check if this is the first channel of a GRS (this flag is thrown when requesting reset) */
 904                         if ( (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) &&
 905                                 !(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_SENT)) &&
 906                                 (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_BASE))) {
 907 
 908                                         /* send out the grs */
 909                                         ft_to_sngss7_grs (ftdmchan);
 910                                         sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_SENT);
 911 
 912                         }/* if ( sngss7_test_flag ( sngss7_info, FLAG_GRP_RESET_TX ) ) */
 913                 } /* if ( last_state != HANGUP && !PAUSED */
 914         
 915                 /* if the sig_status is up...bring it down */
 916                 if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
 917                         sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
 918                         sigev.sigstatus = FTDM_SIG_STATE_DOWN;
 919                         ftdm_span_send_signal (ftdmchan->span, &sigev);
 920                 }
 921 
 922                 if (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX)) {
 923                         /* set the grp reset done flag so we know we have finished this reset */
 924                         sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_DN);
 925                 } /* if (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX)) */
 926 
 927 
 928                 if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_INUSE)) {
 929                         /* bring the call down first...then process the rest of the reset */
 930                         switch (ftdmchan->last_state){
 931                         /******************************************************************/
 932                         case (FTDM_CHANNEL_STATE_TERMINATING):
 933                                 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);     
 934                                 break;
 935                         /******************************************************************/
 936                         case (FTDM_CHANNEL_STATE_HANGUP):
 937                         case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE):
 938                                 /* go back to the last state after taking care of the rest of the restart state */
 939                                 ftdm_set_state_locked (ftdmchan, ftdmchan->last_state);
 940                         break;
 941                         /******************************************************************/
 942                         default:
 943                                 /* KONRAD: find out what the cause code should be */
 944                                 ftdmchan->caller_data.hangup_cause = 41;
 945 
 946                                 /* change the state to terminatting, it will throw us back here
 947                                  * once the call is done
 948                                  */
 949                                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 950                         break;
 951                         /******************************************************************/
 952                         } /* switch (ftdmchan->last_state) */
 953                 } else {
 954                         /* check if this an incoming RSC or we have a response already */
 955                         if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX) ||
 956                                 sngss7_test_flag (sngss7_info, FLAG_RESET_TX_RSP) ||
 957                                 sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX_RSP) ||
 958                                 sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX_CMPLT)) {
 959         
 960                                 SS7_DEBUG_CHAN(ftdmchan, "Reset processed moving to DOWN (0x%X)\n", sngss7_info->flags);
 961         
 962                                 /* go to a down state to clear the channel and send the response */
 963                                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 964                         } else {
 965                                 SS7_DEBUG_CHAN(ftdmchan, "Waiting on Reset Rsp/Grp Reset to move to DOWN (0x%X)\n", sngss7_info->flags);
 966                         }
 967                 }
 968 
 969                 break;
 970         /**************************************************************************/
 971         case FTDM_CHANNEL_STATE_SUSPENDED:      /* circuit has been blocked */
 972 
 973                   SS7_DEBUG_CHAN(ftdmchan,"Current flags: 0x%X\n", sngss7_info->flags);
 974 
 975                 /**********************************************************************/
 976                 if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) {
 977                         SS7_DEBUG_CHAN(ftdmchan, "Processing RESUME%s\n", "");
 978 
 979                         /* clear the RESUME flag */
 980                         sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME);
 981 
 982                         /* if there are any resets present */
 983                         if ((sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) ||
 984                                 (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) ||
 985                                 (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) ||
 986                                 (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) {
 987 
 988                                 /* go back to the reset state */
 989                                 goto suspend_goto_restart;
 990                         } else {
 991 
 992                                 /* bring the sig status back up */
 993                                 sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
 994                                 sigev.sigstatus = FTDM_SIG_STATE_UP;
 995                                 ftdm_span_send_signal(ftdmchan->span, &sigev);
 996                         }
 997 
 998                         /* go back to the last state */
 999                         goto suspend_goto_last;
1000                 } /* if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) */
1001 
1002                 if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) {
1003                         SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE%s\n", "");
1004 
1005                         /* bring the sig status down */
1006                         sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1007                         sigev.sigstatus = FTDM_SIG_STATE_DOWN;
1008                         ftdm_span_send_signal(ftdmchan->span, &sigev);
1009 
1010                         /* go back to the last state */
1011                         goto suspend_goto_last;
1012                 } /* if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { */
1013                 /**********************************************************************/
1014                 if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) {
1015                         SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", "");
1016 
1017                         /* bring the sig status down */
1018                         sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1019                         sigev.sigstatus = FTDM_SIG_STATE_DOWN;
1020                         ftdm_span_send_signal(ftdmchan->span, &sigev); 
1021 
1022                         /* send a BLA */
1023                         ft_to_sngss7_bla (ftdmchan);
1024 
1025                         /* check the last state and return to it to allow the call to finish */
1026                         goto suspend_goto_last;
1027                 }
1028 
1029                 if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX)){
1030                         SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_RX flag %s\n", "");
1031 
1032                         /* clear the unblock flag */
1033                         sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
1034 
1035                         /* bring the sig status up */
1036                         sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1037                         sigev.sigstatus = FTDM_SIG_STATE_UP;
1038                         ftdm_span_send_signal(ftdmchan->span, &sigev); 
1039 
1040                         /* send a uba */
1041                         ft_to_sngss7_uba (ftdmchan);
1042 
1043                         /* check the last state and return to it to allow the call to finish */
1044                         goto suspend_goto_last;
1045                 }
1046 
1047                 /**********************************************************************/
1048                 if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX)) {
1049                         SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_TX flag %s\n", "");
1050 
1051                         /* bring the sig status down */
1052                         sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1053                         sigev.sigstatus = FTDM_SIG_STATE_DOWN;
1054                         ftdm_span_send_signal(ftdmchan->span, &sigev); 
1055 
1056                         /* send a blo */
1057                         ft_to_sngss7_blo (ftdmchan);
1058 
1059                         /* check the last state and return to it to allow the call to finish */
1060                         goto suspend_goto_last;
1061                 }
1062 
1063                 if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX)){
1064                         SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_TX flag %s\n", "");
1065 
1066                         /* clear the unblock flag */
1067                         sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX);
1068 
1069                         /* bring the sig status up */
1070                         sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1071                         sigev.sigstatus = FTDM_SIG_STATE_UP;
1072                         ftdm_span_send_signal(ftdmchan->span, &sigev); 
1073 
1074                         /* send a ubl */
1075                         ft_to_sngss7_ubl (ftdmchan);
1076 
1077                         /* check the last state and return to it to allow the call to finish */
1078                         goto suspend_goto_last;
1079                 }
1080 
1081                 /**********************************************************************/
1082                 if (sngss7_test_flag (sngss7_info, FLAG_CKT_LC_BLOCK_RX)) {
1083                         SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_BLOCK_RX flag %s\n", "");
1084 
1085                         /* send a BLA */
1086                         /*ft_to_sngss7_bla(ftdmchan);*/
1087 
1088                         /* check the last state and return to it to allow the call to finish */
1089                         goto suspend_goto_last;
1090                 }
1091 
1092                 if (sngss7_test_flag (sngss7_info, FLAG_CKT_LC_UNBLK_RX)) {
1093                         SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_UNBLK_RX flag %s\n", "");
1094                         
1095                         /* clear the unblock flag */
1096                         sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX);
1097 
1098                         /* send a uba */
1099                         /*ft_to_sngss7_uba(ftdmchan);*/
1100 
1101                         /* check the last state and return to it to allow the call to finish */
1102                         goto suspend_goto_last;
1103                 }
1104                 /**********************************************************************/
1105                 if (sngss7_test_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK)) {
1106                         SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_BLOCK flag %s\n", "");
1107 
1108                         /* bring the channel signaling status to down */
1109                         sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
1110                         sigev.sigstatus = FTDM_SIG_STATE_DOWN;
1111                         ftdm_span_send_signal (ftdmchan->span, &sigev);
1112 
1113                         /* remove any reset flags */
1114                         clear_rx_grs_flags(sngss7_info);
1115                         clear_tx_grs_flags(sngss7_info);
1116                         clear_rx_rsc_flags(sngss7_info);
1117                         clear_tx_rsc_flags(sngss7_info);
1118                         
1119                         /* bring the channel down */
1120                         goto suspend_goto_last;
1121                 }
1122 
1123                 if (sngss7_test_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK)) {
1124                         SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_UNBLK flag %s\n", "");;
1125 
1126                         /* remove the UCIC block flag */
1127                         sngss7_clear_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK);
1128 
1129                         /* remove the UCIC unblock flag */
1130                         sngss7_clear_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK);
1131 
1132                         /* throw the channel into reset to sync states */
1133                         sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
1134 
1135                         /* bring the channel into restart again */
1136                         goto suspend_goto_restart;
1137                 }
1138 
1139 suspend_goto_last:
1140                 ftdm_set_state_locked (ftdmchan, ftdmchan->last_state);
1141                 break;
1142 
1143 suspend_goto_restart:
1144                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART);
1145                 break;
1146 
1147 /**************************************************************************/
1148         case FTDM_CHANNEL_STATE_IN_LOOP:        /* COT test */
1149 
1150                 /* send the lpa */
1151                 ft_to_sngss7_lpa (ftdmchan);
1152 
1153                 break;
1154         /**************************************************************************/
1155         case FTDM_CHANNEL_STATE_IDLE:
1156                         ftdm_set_state_locked(ftdmchan, ftdmchan->last_state);
1157                 break;
1158         /**************************************************************************/
1159         default:
1160                 /* we don't handle any of the other states */
1161                 SS7_ERROR_CHAN(ftdmchan, "ftmod_sangoma_ss7 does not support %s state\n",  ftdm_channel_state2str (ftdmchan->state));
1162                 
1163                 break;
1164         /**************************************************************************/
1165         }/*switch (ftdmchan->state) */
1166 
1167         return;
1168 }
1169 
1170 /******************************************************************************/
1171 static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
1172 {
1173         sngss7_chan_data_t  *sngss7_info = ftdmchan->call_data;
1174 
1175         /* lock the channel while we check whether it is availble */
1176         ftdm_mutex_lock (ftdmchan->mutex);
1177 
1178         /* check if there is a pending state change, give it a bit to clear */
1179         if (check_for_state_change(ftdmchan)) {
1180                 SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic);
1181                 /* check if we need to die */
1182                 SS7_ASSERT;
1183                 /* end the request */
1184                 goto outgoing_fail;
1185         };
1186 
1187         /* check if the channel sig state is UP */
1188         if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
1189                 SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, cancelling call!%s\n", " ");
1190                 goto outgoing_fail;
1191         }
1192 
1193         /* check if there is a remote block */
1194         if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) ||
1195                 (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) ||
1196                 (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) {
1197 
1198                 /* the channel is blocked...can't send any calls here */
1199                 SS7_ERROR_CHAN(ftdmchan, "Requested channel is remotely blocked, re-hunt channel!%s\n", " ");
1200                 goto outgoing_break;
1201         }
1202 
1203         /* check if there is a local block */
1204         if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) ||
1205                 (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) ||
1206                 (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) {
1207 
1208                 /* KONRAD FIX ME : we should check if this is a TEST call and allow it */
1209 
1210                 /* the channel is blocked...can't send any calls here */
1211                 SS7_ERROR_CHAN(ftdmchan, "Requested channel is locally blocked, re-hunt channel!%s\n", " ");
1212                 goto outgoing_break;
1213         }
1214 
1215         /* check the state of the channel */
1216         switch (ftdmchan->state){
1217         /**************************************************************************/
1218         case FTDM_CHANNEL_STATE_DOWN:
1219                 /* inform the monitor thread that we want to make a call */
1220                 ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DIALING);
1221 
1222                 /* unlock the channel */
1223                 ftdm_mutex_unlock (ftdmchan->mutex);
1224                 
1225                 goto outgoing_successful;
1226                 break;
1227         /**************************************************************************/
1228         default:
1229                 /* the channel is already used...this can't be, end the request */
1230                 SS7_ERROR("Outgoing call requested channel in already in use...indicating glare on span=%d,chan=%d\n",
1231                                         ftdmchan->physical_span_id,
1232                                         ftdmchan->physical_chan_id);
1233 
1234                 goto outgoing_break;
1235                 break;
1236         /**************************************************************************/
1237         } /* switch (ftdmchan->state) (original call) */
1238 
1239 outgoing_fail:
1240         SS7_DEBUG_CHAN(ftdmchan, "Call Request failed%s\n", " ");
1241         /* unlock the channel */
1242         ftdm_mutex_unlock (ftdmchan->mutex);
1243         return FTDM_FAIL;
1244 
1245 outgoing_break:
1246         SS7_DEBUG_CHAN(ftdmchan, "Call Request re-hunt%s\n", " ");
1247         /* unlock the channel */
1248         ftdm_mutex_unlock (ftdmchan->mutex);
1249         return FTDM_BREAK;
1250 
1251 outgoing_successful:
1252         SS7_DEBUG_CHAN(ftdmchan, "Call Request successful%s\n", " ");
1253         /* unlock the channel */
1254         ftdm_mutex_unlock (ftdmchan->mutex);
1255         return FTDM_SUCCESS;
1256 }
1257 
1258 /******************************************************************************/
1259 #if 0
1260           static FIO_CHANNEL_REQUEST_FUNCTION (ftdm_sangoma_ss7_request_chan)
1261           {
1262         SS7_INFO ("KONRAD-> I got called %s\n", __FUNCTION__);
1263         return FTDM_SUCCESS;
1264           }
1265 
1266 #endif
1267 
1268 /******************************************************************************/
1269 
1270 /* FT-CORE SIG STATUS FUNCTIONS ********************************************** */
1271 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_ss7_get_sig_status)
1272 {
1273         if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) {
1274                 *status = FTDM_SIG_STATE_UP;
1275         } else {
1276                 *status = FTDM_SIG_STATE_DOWN;
1277         }
1278 
1279         return FTDM_SUCCESS;
1280 }
1281 
1282 /******************************************************************************/
1283 static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_ss7_set_sig_status)
1284 {
1285         SS7_ERROR ("Cannot set channel status in this module\n");
1286         return FTDM_NOTIMPL;
1287 }
1288 
1289 /* FT-CORE SIG FUNCTIONS ******************************************************/
1290 static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span)
1291 {
1292         ftdm_channel_t          *ftdmchan = NULL;
1293         sngss7_chan_data_t      *sngss7_info = NULL;
1294         sngss7_span_data_t      *sngss7_span = NULL;
1295         sng_isup_inf_t          *sngss7_intf = NULL;
1296         int                             x;
1297 
1298 
1299         SS7_INFO ("Starting span %s:%u.\n", span->name, span->span_id);
1300 
1301         /* throw the channels in pause */
1302         for (x = 1; x < (span->chan_count + 1); x++) {
1303                 /* extract the channel structure and sngss7 channel data */
1304                 ftdmchan = span->channels[x];
1305                 if (ftdmchan->call_data == NULL) continue;
1306                 sngss7_info = ftdmchan->call_data;
1307                 sngss7_span = ftdmchan->span->mod_data;
1308                 sngss7_intf = &g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId];
1309 
1310 
1311                 /* lock the channel */
1312                 ftdm_mutex_lock(ftdmchan->mutex);
1313 
1314                 /* check if the interface is paused or resumed */
1315                 if (sngss7_test_flag(sngss7_intf, SNGSS7_PAUSED)) {
1316                         /* throw the pause flag */
1317                         sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME);
1318                         sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED);
1319                 } else {
1320                         /* throw the pause flag */
1321                         sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED);
1322                         sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME);
1323                 }
1324 #if 0
1325                 /* throw the grp reset flag */
1326                 sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX);
1327                 if (x == 1) {
1328                         sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE);
1329                         sngss7_span->tx_grs.circuit = sngss7_info->circuit->id;
1330                         sngss7_span->tx_grs.range = span->chan_count -1;
1331                 }
1332 #else
1333                 /* throw the channel into reset */
1334                 sngss7_set_flag(sngss7_info, FLAG_RESET_TX);
1335 #endif
1336                 /* throw the channel to suspend */
1337                 ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
1338 
1339                 /* unlock the channel */
1340                 ftdm_mutex_unlock(ftdmchan->mutex);
1341         }
1342 
1343         /* clear the monitor thread stop flag */
1344         ftdm_clear_flag (span, FTDM_SPAN_STOP_THREAD);
1345         ftdm_clear_flag (span, FTDM_SPAN_IN_THREAD);
1346 
1347         /* activate all the configured ss7 links */
1348         if (ft_to_sngss7_activate_all()) {
1349                 SS7_CRITICAL ("Failed to activate LibSngSS7!\n");
1350                 return FTDM_FAIL;
1351         }
1352 
1353         /*start the span monitor thread */
1354         if (ftdm_thread_create_detached (ftdm_sangoma_ss7_run, span) != FTDM_SUCCESS) {
1355                 SS7_CRITICAL ("Failed to start Span Monitor Thread!\n");
1356                 return FTDM_FAIL;
1357         }
1358 
1359         SS7_DEBUG ("Finished starting span %s:%u.\n", span->name, span->span_id);
1360 
1361         return FTDM_SUCCESS;
1362 }
1363 
1364 /******************************************************************************/
1365 static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t * span)
1366 {
1367         /*this function is called by the FT-Core to stop this span */
1368 
1369         ftdm_log (FTDM_LOG_INFO, "Stopping span %s:%u.\n", span->name,span->span_id);
1370 
1371         /* throw the STOP_THREAD flag to signal monitor thread stop */
1372         ftdm_set_flag (span, FTDM_SPAN_STOP_THREAD);
1373 
1374         /* wait for the thread to stop */
1375         while (ftdm_test_flag (span, FTDM_SPAN_IN_THREAD)) {
1376                 ftdm_log (FTDM_LOG_DEBUG,"Waiting for monitor thread to end for %s:%u.\n",
1377                                                                         span->name,
1378                                                                         span->span_id);
1379                 ftdm_sleep (1);
1380         }
1381 
1382         /* KONRAD FIX ME - deconfigure any circuits, links, attached to this span */
1383 
1384         ftdm_log (FTDM_LOG_DEBUG, "Finished stopping span %s:%u.\n", span->name, span->span_id);
1385 
1386         return FTDM_SUCCESS;
1387 }
1388 
1389 /* SIG_FUNCTIONS ***************************************************************/
1390 static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
1391 {
1392         sngss7_span_data_t      *ss7_span_info;
1393 
1394         ftdm_log (FTDM_LOG_INFO, "Configuring ftmod_sangoma_ss7 span = %s(%d)...\n",
1395                                                                 span->name,
1396                                                                 span->span_id);
1397 
1398         /* initalize the span's data structure */
1399         ss7_span_info = ftdm_calloc (1, sizeof (sngss7_span_data_t));
1400 
1401         /* create a timer schedule */
1402         if (ftdm_sched_create(&ss7_span_info->sched, "SngSS7_Schedule")) {
1403                 SS7_CRITICAL("Unable to create timer schedule!\n");
1404                 return FTDM_FAIL;
1405         }
1406 
1407         /* start the free run thread for the schedule */
1408         if (ftdm_sched_free_run(ss7_span_info->sched)) {
1409                 SS7_CRITICAL("Unable to schedule free run!\n");
1410                 return FTDM_FAIL;
1411         }
1412 
1413         /* create an event queue for this span */
1414         if ((ftdm_queue_create(&(ss7_span_info)->event_queue, SNGSS7_EVENT_QUEUE_SIZE)) != FTDM_SUCCESS) {
1415                 SS7_CRITICAL("Unable to create event queue!\n");
1416                 return FTDM_FAIL;
1417         }
1418 
1419         /*setup the span structure with the info so far */
1420         g_ftdm_sngss7_data.sig_cb               = sig_cb;
1421         span->start                                     = ftdm_sangoma_ss7_start;
1422         span->stop                                              = ftdm_sangoma_ss7_stop;
1423         span->signal_type                               = FTDM_SIGTYPE_SS7;
1424         span->signal_data                               = NULL;
1425         span->outgoing_call                     = ftdm_sangoma_ss7_outgoing_call;
1426         span->channel_request                   = NULL;
1427         span->signal_cb                                 = sig_cb;
1428         span->get_channel_sig_status    = ftdm_sangoma_ss7_get_sig_status;
1429         span->set_channel_sig_status    = ftdm_sangoma_ss7_set_sig_status;
1430         span->state_map                                 = &sangoma_ss7_state_map;
1431         span->mod_data                                  = ss7_span_info;
1432 
1433         /* set the flag to indicate that this span uses channel state change queues */
1434         ftdm_set_flag (span, FTDM_SPAN_USE_CHAN_QUEUE);
1435         /* set the flag to indicate that this span uses sig event queues */
1436         ftdm_set_flag (span, FTDM_SPAN_USE_SIGNALS_QUEUE);
1437 
1438         /* parse the configuration and apply to the global config structure */
1439         if (ftmod_ss7_parse_xml(ftdm_parameters, span)) {
1440                 ftdm_log (FTDM_LOG_CRIT, "Failed to parse configuration!\n");
1441                 return FTDM_FAIL;
1442         }
1443 
1444         /* configure libsngss7 */
1445         if (ft_to_sngss7_cfg_all()) {
1446                 ftdm_log (FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n");
1447                 return FTDM_FAIL;
1448         }
1449 
1450         ftdm_log (FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_ss7 span = %s(%d)...\n",
1451                                                                 span->name,
1452                                                                 span->span_id);
1453 
1454         return FTDM_SUCCESS;
1455 }
1456 
1457 /******************************************************************************/
1458 static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init)
1459 {
1460         /*this function is called by the FT-core to load the signaling module */
1461         uint32_t major = 0;
1462         uint32_t minor = 0;
1463         uint32_t build = 0;
1464 
1465         ftdm_log (FTDM_LOG_INFO, "Loading ftmod_sangoma_ss7...\n");
1466 
1467         /* default the global structure */
1468         memset (&g_ftdm_sngss7_data, 0x0, sizeof (ftdm_sngss7_data_t));
1469 
1470         sngss7_id = 0;
1471 
1472         cmbLinkSetId = 1;
1473 
1474         /* initalize the global gen_config flag */
1475         g_ftdm_sngss7_data.gen_config = 0;
1476 
1477         /* min. number of digitis to wait for */
1478         g_ftdm_sngss7_data.min_digits = 7;
1479 
1480         /* function trace initizalation */
1481         g_ftdm_sngss7_data.function_trace = 1;
1482         g_ftdm_sngss7_data.function_trace_level = 7;
1483 
1484         /* message (IAM, ACM, ANM, etc) trace initizalation */
1485         g_ftdm_sngss7_data.message_trace = 1;
1486         g_ftdm_sngss7_data.message_trace_level = 6;
1487 
1488         /* setup the call backs needed by Sangoma_SS7 library */
1489         sng_event.cc.sng_con_ind = sngss7_con_ind;
1490         sng_event.cc.sng_con_cfm = sngss7_con_cfm;
1491         sng_event.cc.sng_con_sta = sngss7_con_sta;
1492         sng_event.cc.sng_rel_ind = sngss7_rel_ind;
1493         sng_event.cc.sng_rel_cfm = sngss7_rel_cfm;
1494         sng_event.cc.sng_dat_ind = sngss7_dat_ind;
1495         sng_event.cc.sng_fac_ind = sngss7_fac_ind;
1496         sng_event.cc.sng_fac_cfm = sngss7_fac_cfm;
1497         sng_event.cc.sng_sta_ind = sngss7_sta_ind;
1498         sng_event.cc.sng_umsg_ind = sngss7_umsg_ind;
1499         sng_event.cc.sng_susp_ind = NULL;
1500         sng_event.cc.sng_resm_ind = NULL;
1501         sng_event.cc.sng_ssp_sta_cfm = NULL;
1502 
1503         sng_event.sm.sng_log = handle_sng_log;
1504         sng_event.sm.sng_mtp1_alarm = handle_sng_mtp1_alarm;
1505         sng_event.sm.sng_mtp2_alarm = handle_sng_mtp2_alarm;
1506         sng_event.sm.sng_mtp3_alarm = handle_sng_mtp3_alarm;
1507         sng_event.sm.sng_isup_alarm = handle_sng_isup_alarm;
1508         sng_event.sm.sng_cc_alarm = handle_sng_cc_alarm;
1509 
1510         /* initalize sng_ss7 library */
1511         sng_isup_init (&sng_event);
1512 
1513         /* print the version of the library being used */
1514         sng_isup_version(&major, &minor, &build);
1515         SS7_INFO("Loaded LibSng-SS7 %d.%d.%d\n", major, minor, build);
1516 
1517         /* crash on assert fail */
1518         ftdm_global_set_crash_policy (FTDM_CRASH_ON_ASSERT);
1519 
1520         return FTDM_SUCCESS;
1521 }
1522 
1523 /******************************************************************************/
1524 static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload)
1525 {
1526         /*this function is called by the FT-core to unload the signaling module */
1527 
1528         ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n");
1529 
1530         sng_isup_free();
1531 
1532         ftdm_log (FTDM_LOG_INFO, "Finished ftmod_sangoma_ss7 unload!\n");
1533         return FTDM_SUCCESS;
1534 }
1535 
1536 /******************************************************************************/
1537 static FIO_API_FUNCTION(ftdm_sangoma_ss7_api)
1538 {
1539         /* handle this in it's own file....so much to do */
1540         return (ftdm_sngss7_handle_cli_cmd (stream, data));
1541 }
1542 
1543 /******************************************************************************/
1544 static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_ss7_io_init)
1545 {
1546         assert (fio != NULL);
1547         memset (&g_ftdm_sngss7_interface, 0, sizeof (g_ftdm_sngss7_interface));
1548 
1549         g_ftdm_sngss7_interface.name = "ss7";
1550         g_ftdm_sngss7_interface.api = ftdm_sangoma_ss7_api;
1551 
1552         *fio = &g_ftdm_sngss7_interface;
1553 
1554         return FTDM_SUCCESS;
1555 }
1556 
1557 /******************************************************************************/
1558 
1559 
1560 /* START **********************************************************************/
1561 ftdm_module_t ftdm_module = {
1562         "sangoma_ss7",                                  /*char name[256];                                  */
1563         ftdm_sangoma_ss7_io_init,               /*fio_io_load_t                                  */
1564         NULL,                                                   /*fio_io_unload_t                                  */
1565         ftdm_sangoma_ss7_init,                  /*fio_sig_load_t                                        */
1566         NULL,                                                   /*fio_sig_configure_t                      */
1567         ftdm_sangoma_ss7_unload,                /*fio_sig_unload_t                                */
1568         ftdm_sangoma_ss7_span_config    /*fio_configure_span_signaling_t        */
1569 };
1570 /******************************************************************************/
1571 
1572 /******************************************************************************/
1573 /* For Emacs:
1574 * Local Variables:
1575 * mode:c
1576 * indent-tabs-mode:t
1577 * tab-width:4
1578 * c-basic-offset:4
1579 * End:
1580 * For VIM:
1581 * vim:set softtabstop=4 shiftwidth=4 tabstop=4:
1582 */
1583 /******************************************************************************/

/* [<][>][^][v][top][bottom][index][help] */