]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
freetdm: fix incorrect alarm reporting due to Wanpipe bug
authorMoises Silva <moy@sangoma.com>
Fri, 14 Jan 2011 23:43:42 +0000 (18:43 -0500)
committerMoises Silva <moy@sangoma.com>
Fri, 14 Jan 2011 23:43:42 +0000 (18:43 -0500)
         proper alarm handling for R2 calls

libs/freetdm/mod_freetdm/mod_freetdm.c
libs/freetdm/src/ftdm_io.c
libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c
libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c
libs/freetdm/src/include/freetdm.h

index 1beb6cd3b3355c3cb0be84244abab0c032d8b319..970cb5b993a098cd991d6920c590bbdf09e32f3a 100755 (executable)
@@ -3763,9 +3763,7 @@ SWITCH_STANDARD_API(ft_function)
                                        flags = "call swap";
                                }
                                fchan = ftdm_span_get_channel(SPAN_CONFIG[j].span, 1);
-                               if (fchan) {
-                                       ftdm_channel_get_alarms(fchan, &alarmbits);
-                               }
+                               ftdm_channel_get_alarms(fchan, &alarmbits);
                                
                                if ((FTDM_SUCCESS == ftdm_span_get_sig_status(SPAN_CONFIG[j].span, &sigstatus))) {
                                        stream->write_function(stream,
index 42109101165118b5a0736dc4dd19aa19b1d2ccff..8afe6e82f5a05e8d23fc207f3702b212be908dc8 100644 (file)
@@ -682,42 +682,53 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_get_alarms(ftdm_channel_t *ftdmchan, ftdm
 {
        ftdm_status_t status = FTDM_FAIL;
 
-       ftdm_assert_return(alarmbits != NULL, FTDM_FAIL, "null argument\n");
+       ftdm_assert_return(alarmbits != NULL, FTDM_EINVAL, "null alarmbits argument\n");
+       ftdm_assert_return(ftdmchan != NULL, FTDM_EINVAL, "null channel argument\n");
+       ftdm_assert_return(ftdmchan->span != NULL, FTDM_EINVAL, "null span\n");
+       ftdm_assert_return(ftdmchan->span->fio != NULL, FTDM_EINVAL, "null io\n");
 
        *alarmbits = FTDM_ALARM_NONE;
 
+       if (!ftdmchan->span->fio->get_alarms) {
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "No get_alarms interface for this channel\n");
+               return FTDM_ENOSYS;
+       }
+
+       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CONFIGURED)) {
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Cannot get alarms from an unconfigured channel\n");
+               return FTDM_EINVAL;
+       }
+
        ftdm_channel_lock(ftdmchan);
 
-       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CONFIGURED)) {
-               if (ftdmchan->span->fio->get_alarms) {
-                       if ((status = ftdmchan->span->fio->get_alarms(ftdmchan)) == FTDM_SUCCESS) {
-                               *ftdmchan->last_error = '\0';
-                               *alarmbits = ftdmchan->alarm_flags;
-                               if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RED)) {
-                                       snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RED/");
-                               }
-                               if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_YELLOW)) {
-                                       snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "YELLOW/");
-                               }
-                               if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RAI)) {
-                                       snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RAI/");
-                               }
-                               if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_BLUE)) {
-                                       snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "BLUE/");
-                               }
-                               if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_AIS)) {
-                                       snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "AIS/");
-                               }
-                               if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_GENERAL)) {
-                                       snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "GENERAL");
-                               }
-                               *(ftdmchan->last_error + strlen(ftdmchan->last_error) - 1) = '\0';
+       if ((status = ftdmchan->span->fio->get_alarms(ftdmchan)) != FTDM_SUCCESS) {
+               ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "Failed to get alarms from channel\n");
+               goto done;
+       }
 
-                       }
-               } else {
-                       status = FTDM_NOTIMPL;
-               }
+       *ftdmchan->last_error = '\0';
+       *alarmbits = ftdmchan->alarm_flags;
+       if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RED)) {
+               snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RED/");
+       }
+       if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_YELLOW)) {
+               snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "YELLOW/");
        }
+       if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_RAI)) {
+               snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "RAI/");
+       }
+       if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_BLUE)) {
+               snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "BLUE/");
+       }
+       if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_AIS)) {
+               snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "AIS/");
+       }
+       if (ftdm_test_alarm_flag(ftdmchan, FTDM_ALARM_GENERAL)) {
+               snprintf(ftdmchan->last_error + strlen(ftdmchan->last_error), sizeof(ftdmchan->last_error) - strlen(ftdmchan->last_error), "GENERAL");
+       }
+       *(ftdmchan->last_error + strlen(ftdmchan->last_error) - 1) = '\0';
+
+done:
 
        ftdm_channel_unlock(ftdmchan);  
 
index 68754d7123f0ccf6dc690b578ee9cedf2795135a..2c9c42df128b3fc7d365b7f8067be0cbd30fa161 100644 (file)
@@ -820,8 +820,14 @@ static void ftdm_r2_on_call_read(openr2_chan_t *r2chan, const unsigned char *buf
 
 static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm)
 {
-       ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
-       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Alarm notification: %d\n", alarm);
+       ftdm_channel_t *fchan = openr2_chan_get_client_data(r2chan);
+
+       ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Alarm notification %d when in state %s (sigstatus = %d)\n", 
+                       alarm, ftdm_channel_state2str(fchan->state), ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP) ? 1 : 0);
+
+       if (alarm && ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) {
+               ftdm_r2_set_chan_sig_status(fchan, FTDM_SIG_STATE_DOWN);
+       }
 }
 
 static void ftdm_r2_on_os_error(openr2_chan_t *r2chan, int errorcode)
@@ -875,14 +881,18 @@ static void ftdm_r2_on_line_blocked(openr2_chan_t *r2chan)
 {
        ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
        ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end blocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
-       ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
+       if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+               ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED);
+       }
 }
 
 static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan)
 {
        ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan);
        ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state));
-       ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
+       if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
+               ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP);
+       }
 }
 
 static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message)
@@ -914,7 +924,7 @@ static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const
 static void ftdm_r2_on_context_log(openr2_context_t *r2context, const char *file, const char *function, unsigned int line, 
        openr2_log_level_t level, const char *fmt, va_list ap)
 {
-#define CONTEXT_TAG "Context -"
+#define CONTEXT_TAG "Context - "
        char logmsg[256];
        char completemsg[sizeof(logmsg) + sizeof(CONTEXT_TAG) - 1];
        vsnprintf(logmsg, sizeof(logmsg), fmt, ap);
@@ -1191,6 +1201,14 @@ static int ftdm_r2_io_get_oob_event(openr2_chan_t *r2chan, openr2_oob_event_t *e
        return 0;
 }
 
+static int ftdm_r2_io_get_alarm_state(openr2_chan_t *r2chan, int *alarm)
+{
+       ftdm_channel_t *fchan = openr2_chan_get_fd(r2chan);
+       ftdm_assert_return(alarm, -1, "Alarm pointer is null\n");
+       *alarm = ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM) ? 1 : 0;
+       return 0;
+}
+
 static openr2_io_interface_t ftdm_r2_io_iface = {
        /* .open */ ftdm_r2_io_open, /* never called */
        /* .close */ ftdm_r2_io_close, /* never called */
@@ -1201,7 +1219,8 @@ static openr2_io_interface_t ftdm_r2_io_iface = {
        /* .read */ ftdm_r2_io_read,
        /* .setup */ ftdm_r2_io_setup, /* never called */
        /* .wait */ ftdm_r2_io_wait,
-       /* .get_oob_event */ ftdm_r2_io_get_oob_event /* never called */
+       /* .get_oob_event */ ftdm_r2_io_get_oob_event,
+       /* .get_alarm_state */ ftdm_r2_io_get_alarm_state 
 };
 
 /* resolve a loglevel string, such as "debug,notice,warning",  to an openr2 log level integer */
index caabc9313cdcb2883c09b565cec5b220104a4b6f..c73f0c78e3bc6a8fb25f75ab1a5fb78afb1bb98d 100644 (file)
@@ -1179,7 +1179,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
        unsigned int alarms = 0;
        int err;
 
-       memset(&tdm_api,0,sizeof(tdm_api));
+       memset(&tdm_api, 0, sizeof(tdm_api));
 
 #ifdef LIBSANGOMA_VERSION
        if ((err = sangoma_tdm_get_fe_alarms(ftdmchan->sockfd, &tdm_api, &alarms))) {
@@ -1225,9 +1225,19 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
                alarms &= ~WAN_TE_BIT_ALARM_RAI;
        }
 
+       if (!ftdmchan->alarm_flags) {
+               if (FTDM_IS_DIGITAL_CHANNEL(ftdmchan)) {
+                       ftdm_channel_hw_link_status_t sangoma_status = 0;
+                       /* there is a bug in wanpipe where alarms were not properly set when they should be
+                        * on at application startup, until that is fixed we check the link status here too */
+                       ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_LINK_STATUS, &sangoma_status);
+                       ftdmchan->alarm_flags = sangoma_status == FTDM_HW_LINK_DISCONNECTED ? 1 : 0;
+                       ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Link status is %d\n", sangoma_status);
+               }
+       }
+
        if (alarms) {
-               /* FIXME: investigate what else does the driver report */
-               ftdm_log(FTDM_LOG_DEBUG, "Unmapped wanpipe alarms: %d\n", alarms);
+               ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Unmapped wanpipe alarms: %d\n", alarms);
        }
 
        return FTDM_SUCCESS;
index 121aa18bf73bdf8742ddbcd31e5be835577ad6bd..dc26a5dbfd85e8485891fbe0ac2822e09a0291bf 100644 (file)
@@ -168,10 +168,17 @@ typedef enum {
 FTDM_STR2ENUM_P(ftdm_str2ftdm_chan_type, ftdm_chan_type2str, ftdm_chan_type_t)
 
 /*! \brief Test if a channel is a voice channel */
-#define FTDM_IS_VOICE_CHANNEL(ftdm_chan) ((ftdm_chan)->type != FTDM_CHAN_TYPE_DQ921 && (ftdm_chan)->type != FTDM_CHAN_TYPE_DQ931)
+#define FTDM_IS_VOICE_CHANNEL(fchan) ((fchan)->type != FTDM_CHAN_TYPE_DQ921 && (fchan)->type != FTDM_CHAN_TYPE_DQ931)
 
 /*! \brief Test if a channel is a D-channel */
-#define FTDM_IS_DCHAN(ftdm_chan) ((ftdm_chan)->type == FTDM_CHAN_TYPE_DQ921 || (ftdm_chan)->type == FTDM_CHAN_TYPE_DQ931)
+#define FTDM_IS_DCHAN(ftdm_chan) ((fchan)->type == FTDM_CHAN_TYPE_DQ921 || (fchan)->type == FTDM_CHAN_TYPE_DQ931)
+
+/*! \brief Test if a channel is digital channel */
+#define FTDM_IS_DIGITAL_CHANNEL(fchan) ((fchan)->span->trunk_type == FTDM_TRUNK_E1 || \
+                                       (fchan)->span->trunk_type == FTDM_TRUNK_T1 || \
+                                       (fchan)->span->trunk_type == FTDM_TRUNK_J1 || \
+                                       (fchan)->span->trunk_type == FTDM_TRUNK_BRI || \
+                                       (fchan)->span->trunk_type == FTDM_TRUNK_BRI_PTMP)
 
 /*! \brief Logging function prototype to be used for all FreeTDM logs 
  *  you should use ftdm_global_set_logger to set your own logger