From 04d565281938ca24ffe5c82cda177624f221cd30 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Fri, 14 Jan 2011 18:43:42 -0500 Subject: [PATCH] freetdm: fix incorrect alarm reporting due to Wanpipe bug proper alarm handling for R2 calls --- libs/freetdm/mod_freetdm/mod_freetdm.c | 4 +- libs/freetdm/src/ftdm_io.c | 71 +++++++++++-------- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 31 ++++++-- .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 16 ++++- libs/freetdm/src/include/freetdm.h | 11 ++- 5 files changed, 89 insertions(+), 44 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 1beb6cd3b3..970cb5b993 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -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, diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 4210910116..8afe6e82f5 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -682,43 +682,54 @@ 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'; - - } - } else { - status = FTDM_NOTIMPL; - } + 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; } + *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); return status; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 68754d7123..2c9c42df12 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -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 */ diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index caabc9313c..c73f0c78e3 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -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; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 121aa18bf7..dc26a5dbfd 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -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