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

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