root/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c

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

DEFINITIONS

This source file includes following definitions.
  1. sngisdn_process_con_ind
  2. sngisdn_process_con_cfm
  3. sngisdn_process_cnst_ind
  4. sngisdn_process_disc_ind
  5. sngisdn_process_rel_ind
  6. sngisdn_process_dat_ind
  7. sngisdn_process_sshl_ind
  8. sngisdn_process_sshl_cfm
  9. sngisdn_process_rmrt_ind
  10. sngisdn_process_rmrt_cfm
  11. sngisdn_process_flc_ind
  12. sngisdn_process_fac_ind
  13. sngisdn_process_sta_cfm
  14. sngisdn_process_srv_ind
  15. sngisdn_process_srv_cfm
  16. sngisdn_process_rst_cfm
  17. sngisdn_process_rst_ind

   1 /*
   2  * Copyright (c) 2010, Sangoma Technologies
   3  * David Yat Sin <dyatsin@sangoma.com>
   4  * All rights reserved.
   5  *
   6  * Redistribution and use in source and binary forms, with or without
   7  * modification, are permitted provided that the following conditions
   8  * are met:
   9  *
  10  * * Redistributions of source code must retain the above copyright
  11  * notice, this list of conditions and the following disclaimer.
  12  *
  13  * * Redistributions in binary form must reproduce the above copyright
  14  * notice, this list of conditions and the following disclaimer in the
  15  * documentation and/or other materials provided with the distribution.
  16  *
  17  * * Neither the name of the original author; nor the names of any contributors
  18  * may be used to endorse or promote products derived from this software
  19  * without specific prior written permission.
  20  *
  21  *
  22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  25  * A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER
  26  * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  27  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  28  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  29  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  30  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
  31  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33  */
  34 
  35 #include "ftmod_sangoma_isdn.h"
  36 
  37 extern ftdm_status_t cpy_calling_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
  38 extern ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
  39 extern ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
  40 extern ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Display *display);
  41 
  42 /* Remote side transmit a SETUP */
  43 void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
  44 {
  45         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
  46         
  47         int16_t suId = sngisdn_event->suId;
  48         uint32_t suInstId = sngisdn_event->suInstId;
  49         uint32_t spInstId = sngisdn_event->spInstId;
  50         int16_t dChan = sngisdn_event->dChan;
  51         uint8_t ces = sngisdn_event->ces;
  52         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;        
  53         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
  54         sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
  55         ConEvnt *conEvnt = &sngisdn_event->event.conEvnt;
  56 
  57         ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
  58         
  59         ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
  60         
  61         switch (ftdmchan->state) {
  62                 case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
  63                         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ||
  64                                 ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
  65 
  66                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP but channel is in USE, saving call for later processing\n");
  67                                 /* the flag the channel as having a collision */
  68                                 sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
  69 
  70                                 /* save the SETUP for processing once the channel has gone to DOWN */
  71                                 memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
  72                                 sngisdn_info->glare.suId = suId;
  73                                 sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
  74                                 sngisdn_info->glare.spInstId = spInstId;
  75                                 sngisdn_info->glare.dChan = dChan;
  76                                 sngisdn_info->glare.ces = ces;
  77                                 break;
  78                         }
  79                         
  80                         sngisdn_info->suInstId = get_unique_suInstId(suId);
  81                         sngisdn_info->spInstId = spInstId;
  82 
  83                         /* If this is a glared call that was previously saved, we moved
  84                         all the info to the current call, so clear the glared saved data */
  85                         if (sngisdn_info->glare.spInstId == spInstId) {
  86                                 clear_call_glare_data(sngisdn_info);
  87                         }                       
  88 
  89                         ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
  90                         g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
  91                         ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
  92 
  93                         ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
  94 
  95                         if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
  96                                 signal_data->signalling == SNGISDN_SIGNALING_NET) {
  97                                 sngisdn_info->ces = ces;
  98                         }
  99 
 100                         /* try to open the channel */
 101                         if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
 102                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
 103                                 sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
 104                                 ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
 105                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
 106                                 break;
 107                         }
 108 
 109 #if 0
 110                         /* Export ftdmchan variables here if we need to */
 111                         ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1");
 112                         ftdm_channel_add_var(ftdmchan, "isdn_crap", "morecrap");
 113                         ftdm_channel_add_var(ftdmchan, "isdn_stuff", "s");
 114                         ftdm_channel_add_var(ftdmchan, "isdn_d", "asdsadasdasdsad");
 115 #endif
 116                         /* Fill in call information */
 117                         cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
 118                         cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
 119                         cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display);
 120 
 121                         if (conEvnt->bearCap[0].eh.pres) {
 122                                 ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val);
 123                                 ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val);
 124                         }
 125 
 126                         if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
 127                                 if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
 128                                         if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
 129                                                 snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
 130                                         }
 131                                 }
 132 
 133                                 
 134                                 if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
 135                                         /* Verify whether the Caller Name will come in a subsequent FACILITY message */
 136                                         uint16_t ret_val;
 137                                         char retrieved_str[255];
 138                                         
 139                                         ret_val = sng_isdn_retrieve_facility_caller_name(conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len, retrieved_str);
 140                                         /*
 141                                                 return values for "sng_isdn_retrieve_facility_information_following":
 142                                                 If there will be no information following, or fails to decode IE, returns -1
 143                                                 If there will be no information following, but current FACILITY IE contains a caller name, returns 0
 144                                                 If there will be information following, returns 1
 145                                         */
 146 
 147                                         if (ret_val == 1) {
 148                                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
 149                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
 150                                                 /* Launch timer in case we never get a FACILITY msg */
 151                                                 if (signal_data->facility_timeout) {
 152                                                         ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, 
 153                                                                         sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
 154                                                 }
 155                                                 break;
 156                                         } else if (ret_val == 0) {
 157                                                 strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
 158                                         }
 159                                 }
 160                         }
 161 
 162                         if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) {
 163                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
 164                         } else {
 165                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
 166                         }
 167                         break;
 168                 case FTDM_CHANNEL_STATE_TERMINATING:
 169                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in TERMINATING state, saving SETUP info for later processing\n");
 170                         ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare\n");
 171                         
 172                         sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
 173 
 174                         /* save the SETUP for processing once the channel has gone to DOWN */
 175                         memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
 176                         sngisdn_info->glare.suId = suId;
 177                         sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
 178                         sngisdn_info->glare.spInstId = spInstId;
 179                         sngisdn_info->glare.dChan = dChan;
 180                         sngisdn_info->glare.ces = ces;
 181                         
 182                         break;
 183                 case FTDM_CHANNEL_STATE_DIALING:        /* glare */
 184                         if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
 185                                 /* Save inbound call info so we can send a RELEASE when this channel goes to a different state */
 186                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP in DIALING state, rejecting inbound call\n");
 187                                 sngisdn_set_flag(sngisdn_info, FLAG_DELAYED_REL);
 188 
 189                                 sngisdn_info->glare.suId = suId;
 190                                 sngisdn_info->glare.suInstId = get_unique_suInstId(suId);
 191                                 sngisdn_info->glare.spInstId = spInstId;
 192 
 193                                 sngisdn_info->glare.dChan = dChan;
 194                                 sngisdn_info->glare.ces = ces;
 195                                 ftdmchan->caller_data.hangup_cause = 0x2C; /* Channel requested not available */
 196                                 ftdm_sched_timer(signal_data->sched, "delayed_release", 1, sngisdn_delayed_release, (void*) sngisdn_info, NULL);
 197                         } else {
 198                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in DIALING state, saving SETUP info for later processing\n");
 199                                 
 200                                 /* the flag the channel as having a collision */
 201                                 ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare");
 202                                 sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
 203 
 204                                 /* save the SETUP for processing once the channel has gone to DOWN */
 205                                 memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
 206                                 sngisdn_info->glare.suId = suId;
 207                                 sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
 208                                 sngisdn_info->glare.spInstId = spInstId;
 209                                 sngisdn_info->glare.dChan = dChan;
 210                                 sngisdn_info->glare.ces = ces;
 211 
 212                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 213                         }
 214                         break;
 215                 default:
 216                         ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
 217                         break;
 218         }
 219         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 220         return;
 221 }
 222 
 223 /* Remote side transmit a CONNECT or CONNECT ACK */
 224 void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
 225 {
 226         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 227 
 228         int16_t suId = sngisdn_event->suId;
 229         uint32_t suInstId = sngisdn_event->suInstId;
 230         uint32_t spInstId = sngisdn_event->spInstId;
 231         uint8_t ces = sngisdn_event->ces;
 232         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 233         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 234         
 235         /* Function does not require any info from conStEvnt struct for now */
 236         /* CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; */      
 237                                 
 238         ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
 239         
 240         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces);
 241 
 242         if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
 243                 ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
 244 
 245                 if(sngisdn_info->ces == CES_MNGMNT) {
 246                         /* We assign the call to the first TE */
 247                         sngisdn_info->ces = ces;
 248                 } else {
 249                         /* We already assigned this call, do nothing */
 250                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n");
 251                         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 252                         return;
 253                 }
 254         }
 255 
 256         if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
 257                 switch(ftdmchan->state) {
 258                         case FTDM_CHANNEL_STATE_PROGRESS:
 259                         case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 260                         case FTDM_CHANNEL_STATE_DIALING:
 261                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
 262                                 break;
 263                         default:
 264                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
 265 
 266                                 /* Start the disconnect procedure */
 267                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 268                                 break;
 269                 }
 270         } else {
 271                 switch(ftdmchan->state) {
 272                         case FTDM_CHANNEL_STATE_UP:
 273                                 /* This is the only valid state we should get a CONNECT ACK on */
 274                                 /* do nothing */
 275                                 break;
 276                         case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 277                                 /* We just hung up an incoming call right after we sent a CONNECT so ignore this message */
 278                                 break;
 279                         default:
 280                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
 281                                 
 282                                 /* Start the disconnect procedure */
 283                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 284                                 break;
 285                 }
 286         }
 287 
 288         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 289         return;
 290 }
 291 
 292 void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
 293 {
 294         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 295 
 296         int16_t suId = sngisdn_event->suId;
 297         uint32_t suInstId = sngisdn_event->suInstId;
 298         uint32_t spInstId = sngisdn_event->spInstId;
 299         uint8_t ces = sngisdn_event->ces;
 300         uint8_t evntType = sngisdn_event->evntType;
 301         
 302         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 303         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 304         
 305         sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 306         
 307         CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt;
 308 
 309         ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
 310 
 311         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n",
 312                                                                                                         (evntType == MI_ALERTING)?"ALERT":
 313                                                                                                         (evntType == MI_CALLPROC)?"PROCEED":
 314                                                                                                         (evntType == MI_PROGRESS)?"PROGRESS":
 315                                                                                                         (evntType == MI_SETUPACK)?"SETUP ACK":
 316                                                                                                                         (evntType == MI_INFO)?"INFO":"UNKNOWN",
 317                                                                                                                         suId, suInstId, spInstId, ces);
 318         
 319         switch(evntType) {
 320                 case MI_PROGRESS:
 321                         if (signal_data->switchtype == SNGISDN_SWITCH_NI2 &&
 322                                                  cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) {
 323 
 324                                 switch(cnStEvnt->causeDgn[0].causeVal.val) {
 325                                         case 17:        /* User Busy */
 326                                         case 18:        /* No User responding */
 327                                         case 19:        /* User alerting, no answer */
 328                                         case 21:        /* Call rejected, the called party does not with to accept this call */
 329                                         case 27:        /* Destination out of order */
 330                                         case 31:        /* Normal, unspecified */
 331                                         case 34:        /* Circuit/Channel congestion */
 332                                         case 41:        /* Temporary failure */
 333                                         case 42:        /* Switching equipment is experiencing a period of high traffic */
 334                                         case 47:        /* Resource unavailable */
 335                                         case 58:        /* Bearer Capability not available */
 336                                         case 63:        /* Service or option not available */
 337                                         case 65:        /* Bearer Cap not implemented, not supported */
 338                                         case 79:        /* Service or option not implemented, unspecified */
 339                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Cause requires disconnect (cause:%d)\n", cnStEvnt->causeDgn[0].causeVal.val);
 340                                                 ftdmchan->caller_data.hangup_cause = cnStEvnt->causeDgn[0].causeVal.val;
 341                                                 
 342                                                 sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC);
 343                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 344                                                 goto sngisdn_process_cnst_ind_end;
 345                                 }
 346                         }
 347                         /* fall-through */
 348                 case MI_ALERTING:
 349                 case MI_CALLPROC:
 350                 
 351                         switch(ftdmchan->state) {
 352                                 case FTDM_CHANNEL_STATE_DIALING:                                        
 353                                         if (evntType == MI_PROGRESS ||
 354                                                 (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
 355                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
 356                                         } else {
 357                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
 358                                         }
 359                                         break;
 360                                 case FTDM_CHANNEL_STATE_PROGRESS:
 361                                         if (evntType == MI_PROGRESS ||
 362                                                 (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) {
 363                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
 364                                         }
 365                                         break;
 366                                 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 367                                         /* We are already in progress media, we can't go to any higher state except up */
 368                                         /* Do nothing */
 369                                         break;
 370                                 default:
 371                                         ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
 372 
 373                                         /* Start the disconnect procedure */
 374                                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 375                                         break;
 376                         }
 377                         break;
 378                 case MI_SETUPACK:
 379                         ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP_ACK, but overlap sending not implemented (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 380                         break;
 381                 case MI_INFO:
 382                         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing INFO (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 383 
 384                         if (cnStEvnt->cdPtyNmb.eh.pres) {
 385                                 switch(ftdmchan->state) {
 386                                         case FTDM_CHANNEL_STATE_COLLECT:
 387                                         {
 388                                                 ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits;
 389                                                 ftdm_size_t num_digits;
 390 
 391                                                 cpy_called_num_from_stack(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb);
 392                                                 num_digits = strlen(ftdmchan->caller_data.dnis.digits);
 393 
 394                                                 if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) {
 395                                                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
 396                                                 } else {
 397                                                         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "received %d of %d digits\n", num_digits, min_digits);
 398                                                 }
 399                                         }
 400                                         break;
 401                                         case FTDM_CHANNEL_STATE_RING:
 402                                         case FTDM_CHANNEL_STATE_PROGRESS:
 403                                         case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 404                                         case FTDM_CHANNEL_STATE_UP:
 405                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val);
 406                                                 break;
 407                                         default:
 408                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
 409                                                 break;
 410                                 }
 411                         }
 412 
 413                         break;
 414                 default:
 415                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unhandled STATUS event\n");
 416                         break;
 417         }
 418 
 419 sngisdn_process_cnst_ind_end:
 420         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 421         return;
 422 }
 423 
 424 void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
 425 {
 426         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 427 
 428         int16_t suId = sngisdn_event->suId;
 429         uint32_t suInstId = sngisdn_event->suInstId;
 430         uint32_t spInstId = sngisdn_event->spInstId;
 431         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 432         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 433         
 434         DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt;
 435 
 436         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 437 
 438         ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
 439         switch (ftdmchan->state) {
 440                 case FTDM_CHANNEL_STATE_RING:
 441                 case FTDM_CHANNEL_STATE_DIALING:
 442                 case FTDM_CHANNEL_STATE_PROGRESS:
 443                 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 444                 case FTDM_CHANNEL_STATE_UP:
 445                         if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
 446                                 ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
 447                         } else {
 448                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n");
 449                                 ftdmchan->caller_data.hangup_cause = 0;
 450                         }
 451                         sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL);
 452                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 453                         break;
 454                 case FTDM_CHANNEL_STATE_COLLECT:
 455                 case FTDM_CHANNEL_STATE_GET_CALLERID:
 456                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
 457                         break;
 458                 case FTDM_CHANNEL_STATE_DOWN:
 459                         /* somehow we are in down, nothing we can do locally */
 460                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT but we are in DOWN state\n");
 461                         break;
 462                 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 463                         /* This is a race condition. We just sent a DISCONNECT, on this channel */
 464                         /* Do nothing */
 465                         break;
 466                 default:
 467                         ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
 468                                                   ftdm_channel_state2str(ftdmchan->state));
 469                         /* start reset procedure */
 470 
 471                         /* Start the release procedure */
 472                         ftdm_set_flag(sngisdn_info, FLAG_REMOTE_REL);
 473                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 474                         break;
 475         }
 476 
 477         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 478         return;
 479 }
 480 
 481 void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
 482 {
 483         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 484         int16_t suId = sngisdn_event->suId;
 485         uint32_t suInstId = sngisdn_event->suInstId;
 486         uint32_t spInstId = sngisdn_event->spInstId;
 487         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;        
 488         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 489         
 490         RelEvnt *relEvnt = &sngisdn_event->event.relEvnt;
 491 
 492         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 493         
 494         ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
 495         
 496         if ((suInstId && (sngisdn_info->glare.suInstId == suInstId)) ||
 497                 (spInstId && (sngisdn_info->glare.spInstId == spInstId))) {
 498 
 499                 /* This hangup is for a glared saved call */
 500                 ftdm_clear_flag(sngisdn_info, FLAG_DELAYED_REL);
 501                 clear_call_glare_data(sngisdn_info);
 502 
 503                 ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 504                 return;
 505         }
 506 
 507         /* check whether the ftdm channel is in a state to accept a call */
 508         switch (ftdmchan->state) {
 509                 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 510                         /* go to DOWN */
 511                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 512                         break;
 513                 case FTDM_CHANNEL_STATE_DOWN:
 514                         /* do nothing, just drop the message */
 515                         break;
 516                 case FTDM_CHANNEL_STATE_DIALING:
 517                         /* Remote side rejected our SETUP message on outbound call */
 518                         if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
 519                                 sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
 520                         }
 521                         /* fall-through */
 522                 case FTDM_CHANNEL_STATE_PROGRESS:
 523                 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 524                 case FTDM_CHANNEL_STATE_UP:
 525                 case FTDM_CHANNEL_STATE_RING:
 526                         /* If we previously had a glare on this channel,
 527                         this RELEASE could be for the previous call.  Confirm whether call_data has
 528                         not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
 529                         if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId ||
 530                                                                         ((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) {
 531                                 if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) {
 532                                         ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val;
 533                                         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause);
 534                                 } else {
 535                                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "RELEASE COMPLETE did not have a cause code\n");
 536                                         ftdmchan->caller_data.hangup_cause = 0;
 537                                 }
 538 
 539                                 sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
 540                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 541 
 542                         } else {
 543                                 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "RELEASE was for previous call (suInstId:%u spInstId:%u)\n", suInstId, spInstId);
 544                         }
 545                         break;
 546                 case FTDM_CHANNEL_STATE_COLLECT:
 547                 case FTDM_CHANNEL_STATE_GET_CALLERID:
 548                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
 549                         break;
 550                 case FTDM_CHANNEL_STATE_TERMINATING:
 551                         if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE) &&
 552                                                                 sngisdn_info->glare.suInstId != suInstId) {
 553                                 /* This release if for the outbound call that we already started clearing */
 554 
 555                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Received RELEASE for local glared call\n");
 556                                 sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
 557                         } else {
 558                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received release before we could clear local call\n");
 559                                 /* FS core took too long to respond to the SIG STOP event */
 560                                 sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
 561                                 /* set abort flag so that we do not transmit another release complete on this channel once FS core is done */
 562                         }
 563                         break;
 564                 default:
 565                         ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
 566                                                         ftdm_channel_state2str(ftdmchan->state));
 567 
 568                         break;
 569         }
 570 
 571 
 572         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 573         return;
 574 }
 575 
 576 void sngisdn_process_dat_ind (sngisdn_event_data_t *sngisdn_event)
 577 {
 578         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);    
 579         int16_t suId = sngisdn_event->suId;
 580         uint32_t suInstId = sngisdn_event->suInstId;
 581         uint32_t spInstId = sngisdn_event->spInstId;
 582 
 583         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 584         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 585 
 586         /* Function does not require any info from infoEvnt struct for now */
 587         /* InfoEvnt *infoEvnt = &sngisdn_event->event.infoEvnt; */
 588         
 589         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DATA IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 590         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 591         return;
 592 }
 593 
 594 void sngisdn_process_sshl_ind (sngisdn_event_data_t *sngisdn_event)
 595 {
 596         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 597         int16_t suId = sngisdn_event->suId;
 598         uint32_t suInstId = sngisdn_event->suInstId;
 599         uint32_t spInstId = sngisdn_event->spInstId;
 600 
 601         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 602         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 603 
 604         /* Function does not require any info from ssHlEvnt struct for now */
 605         /* SsHlEvnt *ssHlEvnt = &sngisdn_event->event.ssHlEvnt; */
 606         
 607         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 608         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 609         return;
 610 }
 611 
 612 void sngisdn_process_sshl_cfm (sngisdn_event_data_t *sngisdn_event)
 613 {
 614         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 615         int16_t suId = sngisdn_event->suId;
 616         uint32_t suInstId = sngisdn_event->suInstId;
 617         uint32_t spInstId = sngisdn_event->spInstId;
 618         
 619         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 620         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 621 
 622         /* Function does not require any info from ssHlEvnt struct for now */
 623         /* SsHlEvnt *ssHlEvnt = &sngisdn_event->event.ssHlEvnt; */
 624 
 625         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 626         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 627         return;
 628 }
 629 
 630 void sngisdn_process_rmrt_ind (sngisdn_event_data_t *sngisdn_event)
 631 {
 632         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 633         int16_t suId = sngisdn_event->suId;
 634         uint32_t suInstId = sngisdn_event->suInstId;
 635         uint32_t spInstId = sngisdn_event->spInstId;
 636 
 637         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 638         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 639 
 640         /* Function does not require any info from ssHlEvnt struct for now */
 641         /* RmRtEvnt *rmRtEvnt = &sngisdn_event->event.rmRtEvnt; */
 642 
 643         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RESUME/RETRIEVE IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 644         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 645         return;
 646 }
 647 
 648 void sngisdn_process_rmrt_cfm (sngisdn_event_data_t *sngisdn_event)
 649 {
 650         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 651         int16_t suId = sngisdn_event->suId;
 652         uint32_t suInstId = sngisdn_event->suInstId;
 653         uint32_t spInstId = sngisdn_event->spInstId;
 654 
 655         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 656         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 657         
 658         /* Function does not require any info from ssHlEvnt struct for now */
 659         /* RmRtEvnt *rmRtEvnt = &sngisdn_event->event.rmRtEvnt; */
 660         
 661         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 662         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 663         return;
 664 }
 665 
 666 void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event)
 667 {
 668         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 669         int16_t suId = sngisdn_event->suId;
 670         uint32_t suInstId = sngisdn_event->suInstId;
 671         uint32_t spInstId = sngisdn_event->spInstId;
 672 
 673         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 674         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 675 
 676         /* Function does not require any info from ssHlEvnt struct for now */
 677         /* StaEvnt *staEvnt = &sngisdn_event->event.staEvnt; */
 678 
 679         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 680         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 681         return;
 682 }
 683 
 684 void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
 685 {
 686         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 687 
 688         int16_t suId = sngisdn_event->suId;
 689         uint32_t suInstId = sngisdn_event->suInstId;
 690         uint32_t spInstId = sngisdn_event->spInstId;
 691 
 692         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 693         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 694         sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
 695 
 696         FacEvnt *facEvnt = &sngisdn_event->event.facEvnt;
 697 
 698         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 699 
 700         switch (ftdmchan->state) {
 701                 case FTDM_CHANNEL_STATE_GET_CALLERID:
 702                         /* Update the caller ID Name */
 703                         if (facEvnt->facElmt.facStr.pres) {
 704                                 char retrieved_str[255];
 705                                 
 706                                 /* return values for "sng_isdn_retrieve_facility_information_following":
 707                                 If there will be no information following, or fails to decode IE, returns -1
 708                                 If there will be no information following, but current FACILITY IE contains a caller name, returns 0
 709                                 If there will be information following, returns 1
 710                                 */
 711                                 
 712                                 if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) {
 713                                         strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
 714                                 } else {
 715                                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n");
 716                                 }
 717                                 if (signal_data->facility_timeout) {
 718                                         /* Cancel facility timeout */
 719                                         ftdm_sched_cancel_timer(signal_data->sched, sngisdn_info->timers[SNGISDN_TIMER_FACILITY]);
 720                                 }
 721                         }
 722 
 723                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
 724                         break;
 725                 case FTDM_CHANNEL_STATE_RING:
 726                         /* We received the caller ID Name in FACILITY, but its too late, facility-timeout already occurred */
 727                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "FACILITY received, but we already proceeded with call\n");
 728                         break;
 729                 default:
 730                         /* We do not support other FACILITY types for now, so do nothing */
 731                         break;
 732         }
 733         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 734         return;
 735 }
 736 
 737 void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
 738 {
 739         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 740         
 741         int16_t suId = sngisdn_event->suId;
 742         uint32_t suInstId = sngisdn_event->suInstId;
 743         uint32_t spInstId = sngisdn_event->spInstId;
 744         sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
 745         ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
 746         
 747         StaEvnt *staEvnt = &sngisdn_event->event.staEvnt;
 748         
 749         uint8_t call_state = 0;
 750 
 751         if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
 752                 call_state = staEvnt->callSte.callGlblSte.val;
 753         }
 754 
 755         ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
 756 
 757         ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
 758 
 759         if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) {
 760                 if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
 761                         call_state = staEvnt->callSte.callGlblSte.val;
 762                 } else {
 763                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received STATUS without call state\n");
 764                         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 765                         return;
 766                 }
 767                 switch (staEvnt->causeDgn[0].causeVal.val) {
 768                         case FTDM_CAUSE_RESPONSE_TO_STATUS_ENQUIRY:
 769                                 ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Status Check OK:%d", call_state);
 770                                 ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 771                                 return;
 772                         case FTDM_CAUSE_WRONG_CALL_STATE:
 773                                 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Message incompatible with call state (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
 774                                 break;
 775                         case FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
 776                                 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Recovery on timer expire (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
 777                                 break;
 778                         default:
 779                                 ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "STATUS CONFIRM (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
 780                                 break;
 781                 }
 782 
 783                 /* Section 4.3.30 from INT Interface - Service Definition */
 784                 ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
 785                 
 786                 switch(call_state) {
 787                         /* Sere ITU-T Q931 for definition of call states */
 788                         case 0: /* Remote switch thinks there are no calls on this channel */
 789                                 switch (ftdmchan->state) {
 790                                         case FTDM_CHANNEL_STATE_COLLECT:
 791                                         case FTDM_CHANNEL_STATE_DIALING:
 792                                         case FTDM_CHANNEL_STATE_UP:
 793                                                 sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
 794                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 795                                                 break;
 796                                         case FTDM_CHANNEL_STATE_TERMINATING:
 797                                                 /* We are in the process of clearing local states,
 798                                                 just make sure we will not send any messages to remote switch */
 799                                                 sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
 800                                                 break;
 801                                         case FTDM_CHANNEL_STATE_HANGUP:
 802                                                 /* This cannot happen, state_advance always sets
 803                                                 ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
 804                                                 and we called check_for_state_change earlier so something is very wrong here!!! */
 805                                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
 806                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 807                                                 break;
 808                                         case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 809                                                 /* We were waiting for remote switch to send RELEASE COMPLETE
 810                                                 but this will not happen, so just clear local state */
 811                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
 812                                                 break;
 813                                         case FTDM_CHANNEL_STATE_DOWN:
 814                                                 /* If our local state is down as well, then there is nothing to do */
 815                                                 break;
 816                                         default:
 817                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 818                                                 break;
 819                                 }
 820                                 break;
 821                         case 1:
 822                                 switch (ftdmchan->state) {
 823                                         case FTDM_CHANNEL_STATE_UP:
 824                                                 /* Remote side is still waiting for our CONNECT message */
 825                                                 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
 826                                                         ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
 827                                                         break;
 828                                                 }
 829                                                 /* Fall-through */
 830                                         default:
 831                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 832                                                 break;
 833                                 }
 834                                 break;
 835                                 case 2: /* overlap sending/receiving */
 836                                         switch (ftdmchan->state) {
 837                                                 case FTDM_CHANNEL_STATE_COLLECT:
 838                                                         /* T302 Timeout reached */
 839                                                         /* Send the call to user, and see if they accept it */
 840                                                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n");
 841                                                         ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
 842                                                         break;
 843                                                 case FTDM_CHANNEL_STATE_PROGRESS:
 844                                                 case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 845                                                         ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
 846                                                         sngisdn_snd_disconnect(ftdmchan);
 847                                                         break;
 848                                                 case FTDM_CHANNEL_STATE_DOWN:
 849                                                 case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 850                                                         /* We hung up locally, but remote switch doesn't know send disconnect again*/
 851                                                         sngisdn_snd_disconnect(ftdmchan);
 852                                                         break;
 853                                                 default:
 854                                                         ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 855                                                         break;
 856                                         }
 857                                         break;
 858                         case 3:
 859                                 switch (ftdmchan->state) {
 860                                         case FTDM_CHANNEL_STATE_PROGRESS:
 861                                                 /* T310 timer has expired */
 862                                                 ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
 863                                                 ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T310 Timer expired, hanging up call\n");
 864                                                 sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC);
 865                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 866 
 867                                                 break;
 868                                         case FTDM_CHANNEL_STATE_UP:
 869                                                 /* Remote side is still waiting for our CONNECT message */
 870                                                 if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
 871                                                         ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
 872                                                         break;
 873                                                 }
 874                                                 /* Fall-through */
 875                                         default:
 876                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 877                                                 break;
 878                                 }
 879                                 break;
 880                         case 8: /* Remote switch is in "Connect Request state" */
 881                                 switch (ftdmchan->state) {
 882                                         case FTDM_CHANNEL_STATE_UP:
 883                                                 /* This is ok. We sent a Connect, and we are waiting for a connect ack */
 884                                                 /* Do nothing */
 885                                                 break;
 886                                         case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 887                                                 /* We hung up locally, but remote switch doesn't know send disconnect again*/
 888                                                 sngisdn_snd_disconnect(ftdmchan);
 889                                                 break;
 890                                         default:
 891                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 892                                                 break;
 893                                 }
 894                                 break;
 895                         case 9: /* Remote switch is in "Incoming call proceeding" state */
 896                                 switch (ftdmchan->state) {
 897                                         case FTDM_CHANNEL_STATE_PROGRESS:
 898                                         case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
 899                                         case FTDM_CHANNEL_STATE_GET_CALLERID:
 900                                                 /* Do nothing */
 901                                                 break;
 902                                         case FTDM_CHANNEL_STATE_UP:
 903                                                 /* Remote switch missed our CONNECT message, re-send */
 904                                                 ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
 905                                                 break;
 906                                         default:
 907                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 908                                                 break;
 909                                 }
 910                                 break;
 911                         case 10: /* Remote switch is in active state */
 912                                 switch (ftdmchan->state) {
 913                                         case FTDM_CHANNEL_STATE_UP:
 914                                                 /* This is ok, they are in active state and we are in active state */
 915                                                 /* Do nothing */
 916                                                 break;
 917                                         case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 918                                                 /* We sent a disconnect message, but remote side missed it ? */
 919                                                 ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_disconnect", 1, sngisdn_delayed_disconnect, (void*) sngisdn_info, NULL);
 920                                                 break;
 921                                         default:
 922                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 923                                                 break;
 924                                 }
 925                                 break;
 926                         case 22:
 927                                 switch (ftdmchan->state) {
 928                                         case FTDM_CHANNEL_STATE_UP:
 929                                                 /* Stack is in the process of clearing the call*/
 930                                                 ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
 931                                                 break;
 932                                         case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
 933                                                 /* Do nothing as we will get a RELEASE COMPLETE */
 934                                                 break;
 935                                         default:
 936                                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 937                                                 //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
 938                                                 break;
 939                                 }
 940                         default:
 941                                 ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
 942                                                 //ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
 943                                 break;
 944                 }
 945         }
 946 
 947         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 948         return;
 949 }
 950 
 951 
 952 void sngisdn_process_srv_ind (sngisdn_event_data_t *sngisdn_event)
 953 {
 954         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 955         int16_t suId = sngisdn_event->suId;
 956         int16_t dChan = sngisdn_event->dChan;
 957         uint8_t ces = sngisdn_event->ces;
 958 
 959         /* Function does not require any info from ssHlEvnt struct for now */
 960         /*Srv *srvEvnt = &sngisdn_event->event.srvEvnt;*/
 961         
 962         ftdm_log(FTDM_LOG_DEBUG, "Processing SERVICE IND (suId:%u dChan:%d ces:%d)\n", suId, dChan, ces);
 963         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 964         return;
 965 }
 966 
 967 void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
 968 {
 969         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 970         int16_t suId = sngisdn_event->suId;
 971         int16_t dChan = sngisdn_event->dChan;
 972         uint8_t ces = sngisdn_event->ces;
 973 
 974         /* Function does not require any info from ssHlEvnt struct for now */
 975         /*Srv *srvEvnt = &sngisdn_event->event.srvEvnt;*/
 976         
 977         ftdm_log(FTDM_LOG_DEBUG, "Processing SERVICE CFM (suId:%u dChan:%d ces:%d)\n", suId, dChan, ces);
 978         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 979         return;
 980 }
 981 
 982 void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
 983 {
 984         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
 985         int16_t suId = sngisdn_event->suId;
 986         int16_t dChan = sngisdn_event->dChan;
 987         uint8_t ces = sngisdn_event->ces;
 988         uint8_t evntType = sngisdn_event->evntType;
 989 
 990         /* Function does not require any info from ssHlEvnt struct for now */
 991         /*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
 992         
 993         ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
 994         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
 995         return;
 996 }
 997 
 998 
 999 void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
1000 {
1001         ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
1002         int16_t suId = sngisdn_event->suId;
1003         int16_t dChan = sngisdn_event->dChan;
1004         uint8_t ces = sngisdn_event->ces;
1005         uint8_t evntType = sngisdn_event->evntType;
1006 
1007         /* Function does not require any info from ssHlEvnt struct for now */
1008         /*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
1009                 
1010         ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d %s)\n", suId, dChan, ces,
1011                                                                                                         (evntType == IN_LNK_DWN)?"LNK_DOWN":
1012                                                                                                         (evntType == IN_LNK_UP)?"LNK_UP":
1013                                                                                                         (evntType == IN_INDCHAN)?"b-channel":
1014                                                                                                         (evntType == IN_LNK_DWN_DM_RLS)?"Nfas service procedures":
1015                                                                                                         (evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown");
1016         ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
1017         return;
1018 }

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