]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
Allow setting/getting signaling status from E&M channels
authorMoises Silva <moy@sangoma.com>
Sun, 6 Oct 2013 23:08:45 +0000 (19:08 -0400)
committerMoises Silva <moy@sangoma.com>
Sun, 6 Oct 2013 23:08:45 +0000 (19:08 -0400)
libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftmod/ftmod_analog_em/ftmod_analog_em.c

index 63d4cd96446f50c0fc2c25e7b7b5ff336f6f5bdb..865b52363fa86a5b334427ec91bf6ad9aeff3bd6 100755 (executable)
@@ -2294,7 +2294,6 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
                        }
                }
                break;
-       case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
        case FTDM_SIGEVENT_COLLECTED_DIGIT: /* Analog E&M */
                {
                        int span_id = ftdm_channel_get_span_id(sigmsg->channel);
@@ -2336,6 +2335,9 @@ static FIO_SIGNAL_CB_FUNCTION(on_fxo_signal)
                        }
                }
                break;
+       case FTDM_SIGEVENT_SIGSTATUS_CHANGED:
+               /* span signaling status changed ... nothing to do here .. */
+               break;
        default:
                {
                        switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Unhandled msg type %d for channel %d:%d\n",
index c387d5a52836f2254ae8c4e5e6f741f430a9f3ae..9d5dd60be79069e1957adca26bbbcd833a561c8c 100644 (file)
@@ -196,6 +196,23 @@ static ftdm_status_t ftdm_analog_em_start(ftdm_span_t *span)
        return ftdm_thread_create_detached(ftdm_analog_em_run, span);
 }
 
+static void ftdm_analog_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
+{
+       ftdm_sigmsg_t sig;
+       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Signalling link status changed to %s\n", ftdm_signaling_status2str(status));
+
+       memset(&sig, 0, sizeof(sig));
+       sig.chan_id = ftdmchan->chan_id;
+       sig.span_id = ftdmchan->span_id;
+       sig.channel = ftdmchan;
+       sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED;
+       sig.ev_data.sigstatus.status = status;
+       if (ftdm_span_send_signal(ftdmchan->span, &sig) != FTDM_SUCCESS) {
+               ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Failed to change channel status to %s\n", ftdm_signaling_status2str(status));
+       }
+       return;
+}
+
 /**
  * \brief Stops EM span thread (monitor)
  * \param span Span to monitor
@@ -215,10 +232,16 @@ static ftdm_status_t ftdm_analog_em_stop(ftdm_span_t *span)
  * \param status       Pointer to set signalling status
  * \return Success or failure
  */
-
 static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_em_get_channel_sig_status)
 {
-       ftdm_unused_arg(ftdmchan);
+       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
+               *status = FTDM_SIG_STATE_DOWN;
+               return FTDM_SUCCESS;
+       }
+       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
+               *status = FTDM_SIG_STATE_SUSPENDED;
+               return FTDM_SUCCESS;
+       }
        *status = FTDM_SIG_STATE_UP;
        return FTDM_SUCCESS;
 }
@@ -229,11 +252,82 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(analog_em_get_channel_sig_status)
  * \param status       Pointer to set signalling status
  * \return Success or failure
  */
-
 static FIO_SPAN_GET_SIG_STATUS_FUNCTION(analog_em_get_span_sig_status)
 {
-       ftdm_unused_arg(span);
-       *status = FTDM_SIG_STATE_UP;
+       ftdm_iterator_t *citer = NULL;
+       ftdm_iterator_t *chaniter = ftdm_span_get_chan_iterator(span, NULL);
+       if (!chaniter) {
+               ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
+               return FTDM_FAIL;
+       }
+       /* if ALL channels are in alarm, report DOWN, UP otherwise. */
+       *status = FTDM_SIG_STATE_DOWN;
+       for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
+               ftdm_channel_t *fchan = ftdm_iterator_current(citer);
+               ftdm_channel_lock(fchan);
+               if (!ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) {
+                       if (!ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) {
+                               *status = FTDM_SIG_STATE_UP;
+                               ftdm_channel_unlock(fchan);
+                               break;
+                       } else {
+                               *status = FTDM_SIG_STATE_SUSPENDED;
+                       }
+               }
+               ftdm_channel_unlock(fchan);
+       }
+       ftdm_iterator_free(chaniter);
+       return FTDM_SUCCESS;
+}
+
+static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(analog_em_set_channel_sig_status)
+{
+       switch (status) {
+       case FTDM_SIG_STATE_DOWN:
+               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot bring channel down, perhaps you want to try '%s'\n", ftdm_signaling_status2str(FTDM_SIG_STATE_SUSPENDED));
+               return FTDM_FAIL;
+       case FTDM_SIG_STATE_SUSPENDED:
+               if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
+                       ftdm_set_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
+                       ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
+               }
+               break;
+       case FTDM_SIG_STATE_UP:
+               if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) {
+                       ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED);
+                       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IN_ALARM)) {
+                               ftdm_analog_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
+                       }
+               }
+               break;
+       default:
+               ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Cannot set signaling status to unknown value '%d'\n", status);
+               return FTDM_FAIL;
+       }
+       return FTDM_SUCCESS;
+}
+
+static FIO_SPAN_SET_SIG_STATUS_FUNCTION(analog_em_set_span_sig_status)
+{
+       ftdm_iterator_t *chaniter = NULL;
+       ftdm_iterator_t *citer = NULL;
+
+       chaniter = ftdm_span_get_chan_iterator(span, NULL);
+       if (!chaniter) {
+               ftdm_log(FTDM_LOG_CRIT, "Failed to allocate channel iterator for span %s!\n", span->name);
+               return FTDM_FAIL;
+       }
+       /* iterate over all channels, setting them to the requested state */
+       for (citer = chaniter; citer; citer = ftdm_iterator_next(citer)) {
+               ftdm_channel_t *fchan = ftdm_iterator_current(citer);
+               /* we set channel's state through analog_em_set_channel_sig_status(), since it already takes care of notifying the user when appropriate */
+               ftdm_channel_lock(fchan);
+               if ((analog_em_set_channel_sig_status(fchan, status)) != FTDM_SUCCESS) {
+                       ftdm_log_chan(fchan, FTDM_LOG_ERROR, "Failed to set signaling status to %s\n", ftdm_signaling_status2str(status));
+               }
+               ftdm_channel_unlock(fchan);
+       }
+       ftdm_iterator_free(chaniter);
        return FTDM_SUCCESS;
 }
 
@@ -334,6 +428,8 @@ static FIO_SIG_CONFIGURE_FUNCTION(ftdm_analog_em_configure_span)
        span->outgoing_call = analog_em_outgoing_call;
        span->get_channel_sig_status = analog_em_get_channel_sig_status;
        span->get_span_sig_status = analog_em_get_span_sig_status;
+       span->set_channel_sig_status = analog_em_set_channel_sig_status;
+       span->set_span_sig_status = analog_em_set_span_sig_status;
        ftdm_span_load_tones(span, tonemap);
        if (immediate_ringback || !ftdm_strlen_zero(ringback_file)) {
                analog_data->immediate_ringback = FTDM_TRUE;
@@ -859,6 +955,12 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
        ftdm_mutex_lock(event->channel->mutex);
        locked++;
 
+       if (ftdm_test_flag(event->channel, FTDM_CHANNEL_SUSPENDED)) {
+               ftdm_log(FTDM_LOG_WARNING, "Ignoring event %s on channel %d:%d in state %s, channel is suspended\n",
+                               ftdm_oob_event2str(event->enum_id), event->channel->span_id, event->channel->chan_id, ftdm_channel_state2str(event->channel->state));
+               goto done;
+       }
+
        switch(event->enum_id) {
        case FTDM_OOB_ONHOOK:
                {
@@ -893,6 +995,9 @@ static __inline__ ftdm_status_t process_event(ftdm_span_t *span, ftdm_event_t *e
                }
                break;
        }
+
+done:
+
        if (locked) {
                ftdm_mutex_unlock(event->channel->mutex);
        }