]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Fix for not handling a call state
authorDavid Yat Sin <dyatsin@sangoma.com>
Thu, 30 Sep 2010 15:41:47 +0000 (11:41 -0400)
committerDavid Yat Sin <dyatsin@sangoma.com>
Mon, 4 Oct 2010 21:50:54 +0000 (17:50 -0400)
Fix for MSN on BRI

libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c
libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c

index 08f340dc838f16360a0831770062d83094509e21..0ed5902153f442130be8a5bf316ce03954efa5fa 100644 (file)
@@ -726,7 +726,7 @@ static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
 }
 
 static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
-{
+{      
        ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
        if (sng_isdn_stack_start(span) != FTDM_SUCCESS) {
                ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
@@ -747,9 +747,11 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
 }
 
 static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
-{
+{      
        ftdm_iterator_t *chaniter = NULL;
        ftdm_iterator_t *curr = NULL;
+       unsigned i;
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
        ftdm_log(FTDM_LOG_INFO, "Stopping span %s\n", span->name);
        
        /* throw the STOP_THREAD flag to signal monitor thread stop */
@@ -772,8 +774,13 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
        }
        ftdm_iterator_free(chaniter);
 
-       ftdm_sched_destroy(&((sngisdn_span_data_t*)span->signal_data)->sched);
-       ftdm_queue_destroy(&((sngisdn_span_data_t*)span->signal_data)->event_queue);
+       ftdm_sched_destroy(&signal_data->sched);
+       ftdm_queue_destroy(&signal_data->event_queue);
+       for (i = 0 ; i < signal_data->num_local_numbers ; i++) {
+               if (signal_data->local_numbers[i] != NULL) {
+                       ftdm_safe_free(signal_data->local_numbers[i]);
+               }
+       }
        ftdm_safe_free(span->signal_data);
 
        ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name);
index ae6c0d92f7bc70511527267fa357a42c42928482..bc928354a7fcf28dc60af0eeeabdc06d0dc9c326 100644 (file)
@@ -55,6 +55,7 @@
 #define NUM_BRI_CHANNELS_PER_SPAN      2
 #define SNGISDN_EVENT_QUEUE_SIZE       100
 #define SNGISDN_EVENT_POLL_RATE                100
+#define SNGISDN_NUM_LOCAL_NUMBERS      8
 
 /* TODO: rename all *_cc_* to *_an_*  */
 
@@ -161,7 +162,7 @@ typedef struct sngisdn_chan_data {
 
 /* Span specific data */
 typedef struct sngisdn_span_data {
-       ftdm_span_t     *ftdm_span;
+       ftdm_span_t             *ftdm_span;
        uint8_t                 link_id;
        uint8_t                 switchtype;
        uint8_t                 signalling;                     /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
@@ -175,7 +176,9 @@ typedef struct sngisdn_span_data {
        uint8_t                 setup_arb;
        uint8_t                 facility;
        int8_t                  facility_timeout;
-       ftdm_sched_t    *sched;
+       uint8_t                 num_local_numbers;
+       char*                   local_numbers[SNGISDN_NUM_LOCAL_NUMBERS];
+       ftdm_sched_t    *sched;
        ftdm_queue_t    *event_queue;
 } sngisdn_span_data_t;
 
index 361b389f96283e093085c5f0a1335d2011942512..64d7a2403fc92f4b958a191ff297a0d78eb8b5e9 100644 (file)
 
 ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span);
 ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span);
+ftdm_status_t add_local_number(const char* val, ftdm_span_t *span);
 
 extern ftdm_sngisdn_data_t     g_sngisdn_data;
 
+ftdm_status_t add_local_number(const char* val, ftdm_span_t *span)
+{
+       sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
+
+       if (signal_data->num_local_numbers >= SNGISDN_NUM_LOCAL_NUMBERS) {
+               ftdm_log(FTDM_LOG_ERROR, "%s: Maximum number of local-numbers exceeded (max:%d)\n", span->name, SNGISDN_NUM_LOCAL_NUMBERS);
+               return FTDM_FAIL;
+       }
+       
+       signal_data->local_numbers[signal_data->num_local_numbers++] = ftdm_strdup(val);
+       return FTDM_SUCCESS;
+}
+
 ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
 {
        unsigned i;
@@ -253,6 +267,10 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
                        ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability);
                } else if (!strcasecmp(var, "outbound-bearer_layer1")) {
                        ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1);
+               } else if (!strcasecmp(var, "local-number")) {                  
+                       if (add_local_number(val, span) != FTDM_SUCCESS) {
+                               return FTDM_FAIL;
+                       }
                } else if (!strcasecmp(var, "facility-timeout")) {
                        signal_data->facility_timeout = atoi(val);
                        if (signal_data->facility_timeout < 0) {
index b7af8e98c58ab11a4fc059df25c75135d722f8db..827647f1f60915b1f38704f4f5c70911341d0700 100644 (file)
@@ -43,7 +43,7 @@ extern ftdm_status_t cpy_calling_name_from_stack(ftdm_caller_data_t *ftdm, Displ
 void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
 {
        ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
-       
+       unsigned i;
        int16_t suId = sngisdn_event->suId;
        uint32_t suInstId = sngisdn_event->suInstId;
        uint32_t spInstId = sngisdn_event->spInstId;
@@ -57,7 +57,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
        ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
        
        ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
-       
+               
        switch (ftdmchan->state) {
                case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
                        if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ||
@@ -80,11 +80,35 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
                        sngisdn_info->suInstId = get_unique_suInstId(suId);
                        sngisdn_info->spInstId = spInstId;
 
+                       if (conEvnt->cdPtyNmb.eh.pres && signal_data->num_local_numbers) {
+                               uint8_t local_number_matched = 0;
+                               for (i = 0 ; i < signal_data->num_local_numbers ; i++) {
+                                       if (!strcmp(signal_data->local_numbers[i], (char*)conEvnt->cdPtyNmb.nmbDigits.val)) {
+                                               local_number_matched++;
+                                               break;
+                                       }
+                               }
+                               if (!local_number_matched) {
+                                       ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SETUP, but local-number %s does not match - ignoring\n", conEvnt->cdPtyNmb.nmbDigits.val);
+                                       /* 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 */
+                                       ftdmchan->caller_data.hangup_cause = IN_CCNORTTODEST;
+                                       ftdm_sched_timer(signal_data->sched, "delayed_disconnect", 1, sngisdn_delayed_disconnect, (void*) sngisdn_info, NULL);
+                                       return;
+                               }
+                       }
+
                        /* If this is a glared call that was previously saved, we moved
                        all the info to the current call, so clear the glared saved data */
                        if (sngisdn_info->glare.spInstId == spInstId) {
                                clear_call_glare_data(sngisdn_info);
-                       }                       
+                       }
+
+                       
+                       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
+                               if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
+                                       sngisdn_info->ces = ces;
+                               }
+                       }
 
                        ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
                        g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
@@ -92,11 +116,6 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
 
                        ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
 
-                       if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
-                               signal_data->signalling == SNGISDN_SIGNALING_NET) {
-                               sngisdn_info->ces = ces;
-                       }
-
                        /* try to open the channel */
                        if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
                                ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
@@ -122,14 +141,13 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
                                ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val);
                                ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val);
                        }
-
+                       
                        if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
                                if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
                                        if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
                                                snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
                                        }
                                }
-
                                
                                if (signal_data->facility == SNGISDN_OPT_TRUE && conEvnt->facilityStr.eh.pres) {
                                        /* Verify whether the Caller Name will come in a subsequent FACILITY message */
@@ -260,6 +278,10 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
                        case FTDM_CHANNEL_STATE_DIALING:
                                ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
                                break;
+                       case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
+                       case FTDM_CHANNEL_STATE_HANGUP:
+                               /* Race condition, we just hung up the call - ignore this message */
+                               break;
                        default:
                                ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
 
@@ -274,7 +296,7 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
                                /* do nothing */
                                break;
                        case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
-                               /* We just hung up an incoming call right after we sent a CONNECT so ignore this message */
+                               /* Race condition, We just hung up an incoming call right after we sent a CONNECT - ignore this message */
                                break;
                        default:
                                ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
@@ -923,6 +945,16 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
                                                break;
                                }
                                break;
+                       case 12: /* We received a disconnect indication */
+                               switch (ftdmchan->state) {
+                                       case FTDM_CHANNEL_STATE_TERMINATING:
+                                               /* We are already waiting for user app to handle the disconnect, do nothing */
+                                               break;
+                                       default:
+                                               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));
+                                               break;
+                               }
+                               break;
                        case 22:
                                switch (ftdmchan->state) {
                                        case FTDM_CHANNEL_STATE_UP:
index 791c6b7d8cb601d54a51d54b39490a6c7dc2fad3..9bf60537fef5fb0ec26d0e07c5c909dfa6929bde 100644 (file)
@@ -706,7 +706,7 @@ void sngisdn_rcv_q931_ind(InMngmt *status)
                        ftdm_span_t *ftdmspan;
                        sngisdn_span_data_t     *signal_data = g_sngisdn_data.spans[status->t.usta.suId];
                        if (!signal_data) {
-                               ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId);
+                               ftdm_log(FTDM_LOG_INFO, "Received q931 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId);
                                return;
                        }
                        ftdmspan = signal_data->ftdm_span;
index db22fe5ce8c7c19b50357f1947ea222239f092ee..691e3104c0ac1a6cc4a2a55d94b1d5ecd1057f50 100644 (file)
@@ -424,11 +424,15 @@ void sngisdn_delayed_disconnect(void* p_sngisdn_info)
        sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;  
 
        ftdm_mutex_lock(ftdmchan->mutex);
-       if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
+       if (ftdmchan->caller_data.hangup_cause == IN_CCNORTTODEST || ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
                ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n",
                                                                        signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
 
                sngisdn_snd_disconnect(ftdmchan);
+               if (ftdmchan->caller_data.hangup_cause == IN_CCNORTTODEST) {
+                       ftdm_channel_t *close_chan = ftdmchan;
+                       ftdm_channel_close(&close_chan);
+               }
        }
 
        ftdm_mutex_unlock(ftdmchan->mutex);