From a020724030c651aed8e427511b8dc79c4ae7a661 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 17 Jan 2011 12:44:52 -0500 Subject: [PATCH 1/2] freetdm: add deprecate warning to get last error stuff that nobody sets anyways --- libs/freetdm/TODO | 6 +++++- libs/freetdm/src/include/freetdm.h | 6 ++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/libs/freetdm/TODO b/libs/freetdm/TODO index 45b134bad3..6b8ef8f826 100644 --- a/libs/freetdm/TODO +++ b/libs/freetdm/TODO @@ -5,5 +5,9 @@ then ftdm_event_t would be renamed to ftdm_oob_event_t and the enum_id renamed to type, then ftdm_span_next_event() will only return OOB events -- query span hw status (connected/disconnected) on startup +- Deprecate last_error members. + It requires a lot of discipline to set the last_error string for every failure. + It does not add much value to the user either, most of the errors are criptic and + cannot be shown to end users, we already provide extensive logging for problem + troubleshooting. diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 0b9c619a70..2666a26df2 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -1064,6 +1064,9 @@ FT_DECLARE(ftdm_codec_t) ftdm_channel_get_codec(const ftdm_channel_t *ftdmchan); /*! * \brief Get the last error string for the channel * + * \deprecated This API will disappear in the future and not every + * FreeTDM API set the last error value + * * \param ftdmchan The channel to get the error from * * \retval The error string (not thread-safe, the string is per channel, not per thread) @@ -1136,6 +1139,9 @@ FT_DECLARE(ftdm_status_t) ftdm_span_find(uint32_t id, ftdm_span_t **span); /*! * \brief Get the last error string for the given span * + * \deprecated This API will disappear in the future and not every + * FreeTDM API set the last error value + * * \param span The span to get the last error from * * \retval character string for the last error From 6734fe711bbc69dc999f237a1865a3013a1d762b Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Mon, 17 Jan 2011 15:42:36 -0500 Subject: [PATCH 2/2] freetdm: General fixes for alarm handling and added MFCR2 suspend support - Clean up ftdm_channel_set_sig_status locking and sanity checks - Set FTDM_CHANNEL_SUSPENDED when delivering FTDM_SIGEVENT_SIGSTATUS changed to SUSPENDED - Clear FTDM_CHANNEL_SUSPENDED when delivering FTDM_SIGEVENT_SIGSTATUS changed to UP - Update ftmod_r2 to honor local suspend requests when returning from alarm state --- libs/freetdm/src/ftdm_io.c | 44 ++++++++++----- libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c | 56 +++++++++++++------ .../src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c | 15 ++++- 3 files changed, 81 insertions(+), 34 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 6cd2a226c8..6bfa37576c 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -2529,26 +2529,34 @@ done: return status; } -FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t sigstatus) +FT_DECLARE(ftdm_status_t) ftdm_channel_set_sig_status(ftdm_channel_t *fchan, ftdm_signaling_status_t sigstatus) { - ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel\n"); - ftdm_assert_return(ftdmchan->span != NULL, FTDM_FAIL, "Null span\n"); + ftdm_status_t res; + + ftdm_assert_return(fchan != NULL, FTDM_FAIL, "Null channel\n"); + ftdm_assert_return(fchan->span != NULL, FTDM_FAIL, "Null span\n"); + ftdm_assert_return(fchan->span->set_channel_sig_status != NULL, FTDM_ENOSYS, "Not implemented\n"); + + ftdm_channel_lock(fchan); + + if (ftdm_test_flag(fchan, FTDM_CHANNEL_IN_ALARM)) { + ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "You can not set the signaling status of an alarmed channel\n"); + res = FTDM_EINVAL; + goto done; + } if (sigstatus == FTDM_SIG_STATE_DOWN) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "The user is not allowed to set the signaling status to DOWN, valid states are UP or SUSPENDED\n"); - return FTDM_FAIL; + ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "You can not set the signaling status to DOWN, valid states are UP or SUSPENDED\n"); + res = FTDM_EINVAL; + goto done; } - if (ftdmchan->span->set_channel_sig_status) { - ftdm_status_t res; - ftdm_channel_lock(ftdmchan); - res = ftdmchan->span->set_channel_sig_status(ftdmchan, sigstatus); - ftdm_channel_unlock(ftdmchan); - return res; - } else { - ftdm_log(FTDM_LOG_ERROR, "set_channel_sig_status method not implemented!\n"); - return FTDM_FAIL; - } + res = fchan->span->set_channel_sig_status(fchan, sigstatus); +done: + + ftdm_channel_unlock(fchan); + + return res; } FT_DECLARE(ftdm_status_t) ftdm_channel_get_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t *sigstatus) @@ -5505,8 +5513,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t { if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_UP) { ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED); } else { ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_SUSPENDED) { + ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED); + } else { + ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED); + } } } break; diff --git a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c index 2c9c42df12..434417726b 100644 --- a/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c +++ b/libs/freetdm/src/ftmod/ftmod_r2/ftmod_r2.c @@ -70,6 +70,7 @@ typedef struct ftdm_r2_call_t { int answer_pending:1; int disconnect_rcvd:1; int protocol_error:1; + int localsuspend_on_alarm:1; ftdm_size_t dnis_index; ftdm_size_t ani_index; char logname[255]; @@ -499,8 +500,16 @@ static ftdm_status_t ftdm_r2_stop(ftdm_span_t *span) static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_channel_sig_status) { + openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan; + openr2_cas_signal_t rxcas, txcas; + + /* get the current rx and tx cas bits */ + openr2_chan_get_cas(r2chan, &rxcas, &txcas); + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { *status = FTDM_SIG_STATE_UP; + } else if (rxcas == OR2_CAS_BLOCK || txcas == OR2_CAS_BLOCK) { + *status = FTDM_SIG_STATE_SUSPENDED; } else { *status = FTDM_SIG_STATE_DOWN; } @@ -561,6 +570,11 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_r2_get_span_sig_status) 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)) { + *status = FTDM_SIG_STATE_DOWN; + ftdm_channel_unlock(fchan); + break; + } if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP)) { *status = FTDM_SIG_STATE_UP; ftdm_channel_unlock(fchan); @@ -825,8 +839,11 @@ static void ftdm_r2_on_hardware_alarm(openr2_chan_t *r2chan, int alarm) 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); + if (alarm) { + R2CALL(fchan)->localsuspend_on_alarm = ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED) ? 1 : 0; + if (ftdm_test_flag(fchan, FTDM_CHANNEL_SIG_UP) || ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) { + ftdm_r2_set_chan_sig_status(fchan, FTDM_SIG_STATE_DOWN); + } } } @@ -881,18 +898,31 @@ 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)); - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP) + || !ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SUSPENDED)) { ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED); } } static void ftdm_r2_on_line_idle(openr2_chan_t *r2chan) { + openr2_cas_signal_t rxcas, txcas; ftdm_channel_t *ftdmchan = openr2_chan_get_client_data(r2chan); + + /* get the current rx and tx cas bits */ + openr2_chan_get_cas(r2chan, &rxcas, &txcas); ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Far end unblocked in state %s\n", ftdm_channel_state2str(ftdmchan->state)); - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP) + && txcas == OR2_CAS_IDLE) { + /* if txcas is not idle, it means we're still blocked as far as the user is concerned, do not send SIGEVENT UP, + * it will be done when the user set the line to IDLE (if the remote is still also IDLE) */ ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_UP); + } else if (txcas == OR2_CAS_BLOCK && R2CALL(ftdmchan)->localsuspend_on_alarm) { + /* the user requested to block, we do not notify about state up until the user set the bits to IDLE, however + * if we're just getting back from alarmed condition, we notify about suspended again */ + ftdm_r2_set_chan_sig_status(ftdmchan, FTDM_SIG_STATE_SUSPENDED); } + R2CALL(ftdmchan)->localsuspend_on_alarm = 0; } static void ftdm_r2_write_log(openr2_log_level_t level, const char *file, const char *function, int line, const char *message) @@ -2018,9 +2048,6 @@ static void __inline__ block_channel(ftdm_channel_t *fchan, ftdm_stream_handle_t if (fchan->state != FTDM_CHANNEL_STATE_DOWN) { stream->write_function(stream, "cannot block channel %d:%d because has a call in progress\n", fchan->span_id, fchan->chan_id); - } else if (ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) { - stream->write_function(stream, "cannot block channel %d:%d because is already blocked\n", - fchan->span_id, fchan->chan_id); } else { if (!openr2_chan_set_blocked(r2chan)) { ftdm_set_flag(fchan, FTDM_CHANNEL_SUSPENDED); @@ -2038,17 +2065,12 @@ static void __inline__ unblock_channel(ftdm_channel_t *fchan, ftdm_stream_handle { openr2_chan_t *r2chan = R2CALL(fchan)->r2chan; ftdm_mutex_lock(fchan->mutex); - if (ftdm_test_flag(fchan, FTDM_CHANNEL_SUSPENDED)) { - if (!openr2_chan_set_idle(r2chan)) { - ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED); - stream->write_function(stream, "unblocked channel %d:%d\n", - fchan->span_id, fchan->chan_id); - } else { - stream->write_function(stream, "failed to unblock channel %d:%d\n", - fchan->span_id, fchan->chan_id); - } + if (!openr2_chan_set_idle(r2chan)) { + ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED); + stream->write_function(stream, "unblocked channel %d:%d\n", + fchan->span_id, fchan->chan_id); } else { - stream->write_function(stream, "cannot unblock channel %d:%d because is not blocked\n", + stream->write_function(stream, "failed to unblock channel %d:%d\n", fchan->span_id, fchan->chan_id); } ftdm_mutex_unlock(fchan->mutex); diff --git a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c index c73f0c78e3..1f2ad84d72 100644 --- a/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c +++ b/libs/freetdm/src/ftmod/ftmod_wanpipe/ftmod_wanpipe.c @@ -1257,6 +1257,7 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_type) { case WP_API_EVENT_LINK_STATUS: { +#if 0 switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_link_status) { case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED: *event_id = FTDM_OOB_ALARM_CLEAR; @@ -1265,6 +1266,11 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc *event_id = FTDM_OOB_ALARM_TRAP; break; }; +#else + /* The WP_API_EVENT_ALARM event should be used to clear alarms */ + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Ignoring wanpipe link status event\n", ftdm_oob_event2str(*event_id)); + *event_id = FTDM_OOB_NOOP; +#endif } break; @@ -1353,8 +1359,13 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc break; case WP_API_EVENT_ALARM: { - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Got wanpipe alarms %d\n", tdm_api->wp_tdm_cmd.event.wp_api_event_alarm); - *event_id = FTDM_OOB_ALARM_TRAP; + if (tdm_api->wp_tdm_cmd.event.wp_api_event_alarm) { + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "Got Wanpipe alarms %d\n", tdm_api->wp_tdm_cmd.event.wp_api_event_alarm); + *event_id = FTDM_OOB_ALARM_TRAP; + } else { + ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Wanpipe alarms cleared\n"); + *event_id = FTDM_OOB_ALARM_CLEAR; + } } break; case WP_API_EVENT_POLARITY_REVERSE: