From ea16afe34eacac3a2b51310c5db33fa97014b141 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 28 Jul 2011 08:04:07 -0400 Subject: [PATCH] svn-style merge from moy.ss7grs_perchan branch (spin off releases.3.2) addressed issue with multiple GRS at the same time in a single span revisions merged: afcc831d6fa1fccaf7ef091b8c48b905a76d834d 9c815c9ecd7102e7d30c3988cd41682b8cbade0b --- libs/freetdm/src/ftdm_io.c | 60 +- libs/freetdm/src/ftdm_threadmutex.c | 78 ++- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c | 58 +- .../ftmod_sangoma_ss7_handle.c | 80 ++- .../ftmod_sangoma_ss7_main.c | 75 +- .../ftmod_sangoma_ss7_main.h | 28 +- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c | 99 ++- .../ftmod_sangoma_ss7_support.c | 663 ++++++++++-------- libs/freetdm/src/include/ftdm_threadmutex.h | 12 +- libs/freetdm/src/include/private/ftdm_core.h | 11 +- 10 files changed, 684 insertions(+), 480 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 5b99865044..8b0de8508b 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -5433,12 +5433,14 @@ static void execute_safety_hangup(void *data) FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) { + ftdm_channel_t *fchan = NULL; if (sigmsg->channel) { - ftdm_mutex_lock(sigmsg->channel->mutex); - sigmsg->chan_id = sigmsg->channel->chan_id; - sigmsg->span_id = sigmsg->channel->span_id; - sigmsg->call_id = sigmsg->channel->caller_data.call_id; - sigmsg->call_priv = sigmsg->channel->caller_data.priv; + fchan = sigmsg->channel; + ftdm_channel_lock(fchan); + sigmsg->chan_id = fchan->chan_id; + sigmsg->span_id = fchan->span_id; + sigmsg->call_id = fchan->caller_data.call_id; + sigmsg->call_priv = fchan->caller_data.priv; } /* some core things to do on special events */ @@ -5447,14 +5449,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t case FTDM_SIGEVENT_SIGSTATUS_CHANGED: { 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); + ftdm_set_flag(fchan, FTDM_CHANNEL_SIG_UP); + ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED); } else { - ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + ftdm_clear_flag(fchan, FTDM_CHANNEL_SIG_UP); if (sigmsg->ev_data.sigstatus.status == FTDM_SIG_STATE_SUSPENDED) { - ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED); + ftdm_set_flag(fchan, FTDM_CHANNEL_SUSPENDED); } else { - ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SUSPENDED); + ftdm_clear_flag(fchan, FTDM_CHANNEL_SUSPENDED); } } } @@ -5462,14 +5464,14 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t case FTDM_SIGEVENT_START: { - ftdm_assert(!ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED), "Started call twice!"); + ftdm_assert(!ftdm_test_flag(fchan, FTDM_CHANNEL_CALL_STARTED), "Started call twice!"); - if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_OUTBOUND)) { - ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_WARNING, "Inbound call taking over outbound channel\n"); - ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_OUTBOUND); + if (ftdm_test_flag(fchan, FTDM_CHANNEL_OUTBOUND)) { + ftdm_log_chan_msg(fchan, FTDM_LOG_WARNING, "Inbound call taking over outbound channel\n"); + ftdm_clear_flag(fchan, FTDM_CHANNEL_OUTBOUND); } - ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED); - ftdm_call_set_call_id(sigmsg->channel, &sigmsg->channel->caller_data); + ftdm_set_flag(fchan, FTDM_CHANNEL_CALL_STARTED); + ftdm_call_set_call_id(fchan, &fchan->caller_data); /* when cleaning up the public API I added this because mod_freetdm.c on_fxs_signal was * doing it during SIGEVENT_START, but now that flags are private they can't, wonder if * is needed at all? */ @@ -5483,8 +5485,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t case FTDM_SIGEVENT_PROGRESS_MEDIA: { /* test signaling module compliance */ - if (sigmsg->channel->state != FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { - ftdm_log_chan(sigmsg->channel, FTDM_LOG_WARNING, "FTDM_SIGEVENT_PROGRESS_MEDIA sent in state %s\n", ftdm_channel_state2str(sigmsg->channel->state)); + if (fchan->state != FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { + ftdm_log_chan(fchan, FTDM_LOG_WARNING, "FTDM_SIGEVENT_PROGRESS_MEDIA sent in state %s\n", ftdm_channel_state2str(fchan->state)); } } break; @@ -5492,8 +5494,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t case FTDM_SIGEVENT_UP: { /* test signaling module compliance */ - if (sigmsg->channel->state != FTDM_CHANNEL_STATE_UP) { - ftdm_log_chan(sigmsg->channel, FTDM_LOG_WARNING, "FTDM_SIGEVENT_UP sent in state %s\n", ftdm_channel_state2str(sigmsg->channel->state)); + if (fchan->state != FTDM_CHANNEL_STATE_UP) { + ftdm_log_chan(fchan, FTDM_LOG_WARNING, "FTDM_SIGEVENT_UP sent in state %s\n", ftdm_channel_state2str(fchan->state)); } } break; @@ -5505,20 +5507,20 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t /* if the call was never started, do not send SIGEVENT_STOP this happens for FXS devices in ftmod_analog which blindly send SIGEVENT_STOP, we should fix it there ... */ - if (!ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_CALL_STARTED)) { - ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user never knew about a call in this channel\n"); + if (!ftdm_test_flag(fchan, FTDM_CHANNEL_CALL_STARTED)) { + ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user never knew about a call in this channel\n"); goto done; } - if (ftdm_test_flag(sigmsg->channel, FTDM_CHANNEL_USER_HANGUP)) { - ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n"); + if (ftdm_test_flag(fchan, FTDM_CHANNEL_USER_HANGUP)) { + ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Ignoring SIGEVENT_STOP since user already requested hangup\n"); goto done; } - if (sigmsg->channel->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan_msg(sigmsg->channel, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n"); + if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) { + ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Scheduling safety hangup timer\n"); /* if the user does not move us to hangup in 2 seconds, we will do it ourselves */ - ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, sigmsg->channel, &sigmsg->channel->hangup_timer); + ftdm_sched_timer(globals.timingsched, "safety-hangup", FORCE_HANGUP_TIMER, execute_safety_hangup, fchan, &fchan->hangup_timer); } } break; @@ -5537,8 +5539,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t done: - if (sigmsg->channel) { - ftdm_mutex_unlock(sigmsg->channel->mutex); + if (fchan) { + ftdm_channel_unlock(fchan); } return FTDM_SUCCESS; diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c index 57a8fb4830..f2524727ca 100644 --- a/libs/freetdm/src/ftdm_threadmutex.c +++ b/libs/freetdm/src/ftdm_threadmutex.c @@ -27,6 +27,7 @@ # endif # include #endif +/*#define FTDM_DEBUG_MUTEX 0*/ #include "private/ftdm_core.h" #include "ftdm_threadmutex.h" @@ -46,8 +47,26 @@ struct ftdm_mutex { #define FTDM_THREAD_CALLING_CONVENTION +#ifdef FTDM_DEBUG_MUTEX +#define FTDM_MUTEX_MAX_REENTRANCY 30 +typedef struct ftdm_lock_entry { + const char *file; + const char *func; + uint32_t line; +} ftdm_lock_entry_t; + +typedef struct ftdm_lock_history { + ftdm_lock_entry_t locked; + ftdm_lock_entry_t unlocked; +} ftdm_lock_history_t; +#endif + struct ftdm_mutex { pthread_mutex_t mutex; +#ifdef FTDM_DEBUG_MUTEX + ftdm_lock_history_t lock_history[FTDM_MUTEX_MAX_REENTRANCY]; + uint8_t reentrancy; +#endif }; #endif @@ -112,7 +131,7 @@ FT_DECLARE(ftdm_status_t) ftdm_thread_create_detached_ex(ftdm_thread_function_t ftdm_thread_t *thread = NULL; ftdm_status_t status = FTDM_FAIL; - if (!func || !(thread = (ftdm_thread_t *)ftdm_malloc(sizeof(ftdm_thread_t)))) { + if (!func || !(thread = (ftdm_thread_t *)ftdm_calloc(1, sizeof(ftdm_thread_t)))) { goto done; } @@ -162,7 +181,7 @@ FT_DECLARE(ftdm_status_t) ftdm_mutex_create(ftdm_mutex_t **mutex) #endif ftdm_mutex_t *check = NULL; - check = (ftdm_mutex_t *)ftdm_malloc(sizeof(**mutex)); + check = (ftdm_mutex_t *)ftdm_calloc(1, sizeof(**mutex)); if (!check) goto done; #ifdef WIN32 @@ -209,21 +228,40 @@ FT_DECLARE(ftdm_status_t) ftdm_mutex_destroy(ftdm_mutex_t **mutex) return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(ftdm_mutex_t *mutex) +#define ADD_LOCK_HISTORY(mutex, file, line, func) \ + { \ + if ((mutex)->reentrancy < FTDM_MUTEX_MAX_REENTRANCY) { \ + (mutex)->lock_history[mutex->reentrancy].locked.file = (file); \ + (mutex)->lock_history[mutex->reentrancy].locked.func = (func); \ + (mutex)->lock_history[mutex->reentrancy].locked.line = (line); \ + (mutex)->lock_history[mutex->reentrancy].unlocked.file = NULL; \ + (mutex)->lock_history[mutex->reentrancy].unlocked.func = NULL; \ + (mutex)->lock_history[mutex->reentrancy].unlocked.line = 0; \ + (mutex)->reentrancy++; \ + if ((mutex)->reentrancy == FTDM_MUTEX_MAX_REENTRANCY) { \ + ftdm_log((file), (func), (line), FTDM_LOG_LEVEL_ERROR, "Max reentrancy reached for mutex %p\n", (mutex)); \ + } \ + } \ + } + +FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(const char *file, int line, const char *func, ftdm_mutex_t *mutex) { #ifdef WIN32 EnterCriticalSection(&mutex->mutex); #else int err; if ((err = pthread_mutex_lock(&mutex->mutex))) { - ftdm_log(FTDM_LOG_ERROR, "Failed to lock mutex %d:%s\n", err, strerror(err)); + ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Failed to lock mutex %d:%s\n", err, strerror(err)); return FTDM_FAIL; } +#endif +#ifdef FTDM_DEBUG_MUTEX + ADD_LOCK_HISTORY(mutex, file, line, func); #endif return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(ftdm_mutex_t *mutex) +FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(const char *file, int line, const char *func, ftdm_mutex_t *mutex) { #ifdef WIN32 if (!TryEnterCriticalSection(&mutex->mutex)) @@ -231,17 +269,43 @@ FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(ftdm_mutex_t *mutex) #else if (pthread_mutex_trylock(&mutex->mutex)) return FTDM_FAIL; +#endif +#ifdef FTDM_DEBUG_MUTEX + ADD_LOCK_HISTORY(mutex, file, line, func); #endif return FTDM_SUCCESS; } -FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(ftdm_mutex_t *mutex) +FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const char *func, ftdm_mutex_t *mutex) { +#ifdef FTDM_DEBUG_MUTEX + int i = 0; + if (mutex->reentrancy == 0) { + ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Cannot unlock something that is not locked!\n"); + return FTDM_FAIL; + } + i = mutex->reentrancy - 1; + /* I think this is a fair assumption when debugging */ + if (func != mutex->lock_history[i].locked.func) { + ftdm_log(file, func, line, FTDM_LOG_LEVEL_WARNING, "Mutex %p was suspiciously locked at %s->%s:%d but unlocked at %s->%s:%d!\n", + mutex, mutex->lock_history[i].locked.func, mutex->lock_history[i].locked.file, mutex->lock_history[i].locked.line, + func, file, line); + } + mutex->lock_history[i].unlocked.file = file; + mutex->lock_history[i].unlocked.line = line; + mutex->lock_history[i].unlocked.func = func; + mutex->reentrancy--; +#endif #ifdef WIN32 LeaveCriticalSection(&mutex->mutex); #else - if (pthread_mutex_unlock(&mutex->mutex)) + if (pthread_mutex_unlock(&mutex->mutex)) { + ftdm_log(file, func, line, FTDM_LOG_LEVEL_ERROR, "Failed to unlock mutex: %s\n", strerror(errno)); +#ifdef FTDM_DEBUG_MUTEX + mutex->reentrancy++; +#endif return FTDM_FAIL; + } #endif return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c index 710b0c37a6..f1da5f195a 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c @@ -1618,10 +1618,11 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c /******************************************************************************/ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose) { - int x; - sngss7_chan_data_t *sngss7_info; - ftdm_channel_t *ftdmchan; - sngss7_span_data_t *sngss7_span; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_span_data_t *sngss7_span = NULL; + int x = 0; + int basefound = 0; if (range > 31) { stream->write_function(stream, "Invalid range value %d", range); @@ -1638,42 +1639,45 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c if ((ftdmchan->physical_span_id == span) && ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { + /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + ftdm_channel_lock(ftdmchan); + + /* if another reset is still in progress, skip this channel */ + if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX)) { + ftdm_channel_unlock(ftdmchan); + continue; + } /* check if there is a pending state change|give it a bit to clear */ if (check_for_state_change(ftdmchan)) { SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - /* check if we need to die */ - SS7_ASSERT; - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - /* move to the next channel */ + ftdm_channel_unlock(ftdmchan); continue; - } else { - /* throw the grp reset flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX); - if (ftdmchan->physical_chan_id == chan) { - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE); - sngss7_span->tx_grs.circuit = sngss7_info->circuit->id; - sngss7_span->tx_grs.range = range-1; - } - - /* set the channel to suspended state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* throw the grp reset flag */ + sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX); + if (!basefound) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Setting channel as GRS base\n"); + sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_BASE); + sngss7_info->tx_grs.circuit = sngss7_info->circuit->id; + sngss7_info->tx_grs.range = range - 1; + basefound = 1; + } - } /* if ( span and chan) */ + /* set the channel to restart state */ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } /* if ( cic != 0) */ + ftdm_channel_unlock(ftdmchan); + + } + + } /* go the next circuit */ x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + } x = (g_ftdm_sngss7_data.cfg.procId * 1000) + 1; while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c index 48a842c37c..20e9a1261c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -1910,11 +1910,10 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_span_data_t *sngss7_span = NULL; - int range; - + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_span_data_t *sngss7_span = NULL; + int range = 0; /* confirm that the circuit is voice channel */ if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { @@ -1948,9 +1947,15 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* fill in the span structure for this circuit */ sngss7_span = ftdmchan->span->signal_data; - sngss7_span->rx_grs.circuit = circuit; - sngss7_span->rx_grs.range = range; + if (sngss7_info->rx_grs.range) { + SS7_CRITICAL("Cannot handle another GRS on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + sngss7_info->rx_grs.circuit = circuit; + sngss7_info->rx_grs.range = range; + ftdm_set_flag(sngss7_span, SNGSS7_RX_GRS_PENDING); /* the reset will be started in the main thread by "check_if_rx_grs_started" */ SS7_FUNC_TRACE_EXIT(__FUNCTION__); @@ -1962,10 +1967,10 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_span_data_t *sngss7_span = NULL; - int range; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_span_data_t *sngss7_span = NULL; + int range = 0; /* confirm that the circuit is voice channel */ if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].type != SNG_CKT_VOICE) { @@ -1999,17 +2004,24 @@ ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* fill in the span structure for this circuit */ sngss7_span = ftdmchan->span->signal_data; - sngss7_span->rx_gra.circuit = circuit; - sngss7_span->rx_gra.range = range; + if (sngss7_info->rx_gra.range) { + SS7_ERROR("Cannot handle another GRA on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + sngss7_info->rx_gra.circuit = circuit; + sngss7_info->rx_gra.range = range; /* check if there is a cause value in the GRA */ if ((siStaEvnt != NULL) && (siStaEvnt->causeDgn.eh.pres == PRSNT_NODEF) && (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { - sngss7_span->rx_gra.cause = siStaEvnt->causeDgn.causeVal.val; + sngss7_info->rx_gra.cause = siStaEvnt->causeDgn.causeVal.val; } + ftdm_set_flag(sngss7_span, SNGSS7_RX_GRA_PENDING); + /* the reset will be started in the main thread by "check_if_rx_gra_started" */ SS7_FUNC_TRACE_EXIT(__FUNCTION__); @@ -2121,9 +2133,12 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = NULL; - ftdm_channel_t *ftdmchan = NULL; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_chan_data_t *cinfo = NULL; + sngss7_span_data_t *sngss7_span = NULL; + ftdm_channel_t *ftdmchan = NULL; /* confirm that the circuit is voice channel */ @@ -2147,13 +2162,28 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit DECODE_LCC_EVENT(evntType)); } - /* check if we just sent a GRS request...*/ + /* find out if the cic belongs to one of our GRS requests, if so, + * all circuits in the request must be blocked */ sngss7_span = ftdmchan->span->signal_data; - if (sngss7_span->tx_grs.circuit > 0) { - /* we need to put all circuits on this UCIC */ - sngss7_span->ucic.circuit = sngss7_span->tx_grs.circuit; - sngss7_span->ucic.range = sngss7_span->tx_grs.range; - goto done; + iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL); + curr = iter; + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_t *fchan = ftdm_iterator_current(curr); + + ftdm_channel_lock(fchan); + + cinfo = fchan->call_data; + if (circuit == cinfo->tx_grs.circuit) { + cinfo->ucic.circuit = cinfo->tx_grs.circuit; + cinfo->ucic.range = cinfo->tx_grs.range; + ftdm_set_flag(sngss7_span, SNGSS7_UCIC_PENDING); + + ftdm_channel_unlock(fchan); + + goto done; + } + + ftdm_channel_unlock(fchan); } /* lock the channel */ @@ -2168,6 +2198,10 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); done: + if (iter) { + ftdm_iterator_free(iter); + } + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 08f4688cc7..f5b162e104 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -328,13 +328,13 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) /* unlock the channel */ ftdm_mutex_unlock (ftdmchan->mutex); - }/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans))) */ + } /* clean out all pending stack events */ while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) { ftdm_sangoma_ss7_process_stack_event(sngss7_event); ftdm_safe_free(sngss7_event); - }/* while ((sngss7_event = ftdm_queue_dequeue(ftdmspan->signal_data->event_queue))) */ + } /* signal the core that sig events are queued for processing */ ftdm_span_trigger_signals(ftdmspan); @@ -356,27 +356,27 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) break; /**********************************************************************/ - } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */ + } /* check if there is a GRA to proccess on the span */ - if (sngss7_span->rx_gra.range > 0) { + if (ftdm_test_flag(sngss7_span, SNGSS7_RX_GRA_PENDING)) { check_if_rx_gra_started(ftdmspan); - } /* if (sngss7->span->rx_gra.range > 0) */ + } /* check if there is a GRS being processed on the span */ - if (sngss7_span->rx_grs.range > 0) { + if (ftdm_test_flag(sngss7_span, SNGSS7_RX_GRS_PENDING)) { /* check if the rx_grs has started */ check_if_rx_grs_started(ftdmspan); /* check if the rx_grs has cleared */ check_if_rx_grs_processed(ftdmspan); - } /* if (sngss7_span->rx_grs.range > 0) */ + } /* check if there is a UCIC to be processed on the span */ - if (sngss7_span->ucic.range > 0) { + if (ftdm_test_flag(sngss7_span, SNGSS7_UCIC_PENDING)) { /* process the span wide UCIC */ process_span_ucic(ftdmspan); - } /* if (sngss7_span->ucic.range > 0) */ + } /* check each channel on the span to see if there is an un-procressed SUS/RES flag */ check_for_res_sus_flag(ftdmspan); @@ -398,8 +398,8 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) default: SS7_ERROR("%s:Failed to poll span event\n", ftdmspan->name); /**********************************************************************/ - } /* switch (ftdm_span_poll_event(span, 0)) */ - } /* master while loop */ + } + } /* clear the IN_THREAD flag so that we know the thread is done */ ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD); @@ -423,8 +423,8 @@ ftdm_sangoma_ss7_run_exit: /******************************************************************************/ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event) { - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(sngss7_event->circuit, &sngss7_info, &ftdmchan)) { @@ -432,8 +432,8 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + /* now that we have the right channel ... put a lock on it so no-one else can use it */ + ftdm_channel_lock(ftdmchan); /* while there's a state change present on this channel process it */ ftdm_channel_advance_states(ftdmchan); @@ -496,24 +496,23 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev SS7_ERROR("Unknown Event Id!\n"); break; /**************************************************************************/ - } /* switch (sngss7_event->event_id) */ + } /* while there's a state change present on this channel process it */ ftdm_channel_advance_states(ftdmchan); /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + ftdm_channel_unlock(ftdmchan); - return; } /******************************************************************************/ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) { - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - sng_isup_inf_t *isup_intf = NULL; - int state_flag = 1; - int i = 0; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + sng_isup_inf_t *isup_intf = NULL; + int state_flag = 1; + int i = 0; SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state)); @@ -807,7 +806,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* clear the reset flag */ clear_rx_rsc_flags(sngss7_info); - } /* if (sngss7_test_ckt_flag (sngss7_info, FLAG_RESET_RX)) */ + } /* check if there was a GRS that needs a GRA */ if ((sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) && @@ -815,10 +814,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT))) { /* check if this is the base circuit and send out the GRA - * we insure that this is the last circuit to have the state change queued - */ - sngss7_span_data_t *span = ftdmchan->span->signal_data; - if (span->rx_grs.circuit == sngss7_info->circuit->id) { + * we insure that this is the last circuit to have the state change queued */ + if (sngss7_info->rx_grs.range) { /* send out the GRA */ ft_to_sngss7_gra(ftdmchan); @@ -828,21 +825,22 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* clear the grp reset flag */ clear_rx_grs_flags(sngss7_info); - }/* if ( sngss7_test_ckt_flag ( sngss7_info, FLAG_GRP_RESET_RX ) ) */ + } /* check if we got the reset response */ if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) { /* clear the reset flag */ clear_tx_rsc_flags(sngss7_info); - } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_RESET_TX_RSP)) */ + } if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) { /* clear the reset flag */ clear_tx_grs_flags(sngss7_info); - - /* clean out the spans GRA structure */ - clear_rx_gra_data(sngss7_info); - } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) */ + if (sngss7_info->rx_gra.range) { + /* clean out the spans GRA structure */ + clear_rx_gra_data(sngss7_info); + } + } /* check if we came from reset (aka we just processed a reset) */ if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) || @@ -900,7 +898,7 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) ftdm_channel_t *close_chan = ftdmchan; /* close the channel */ ftdm_channel_close (&close_chan); - } /* if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) */ + } /* check if there is a glared call that needs to be processed */ if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) { @@ -918,8 +916,8 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* clear the glare info */ memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t)); - } /* if (sngss7_info->glare.circuit != 0) */ - } /* if (sngss7_test_ckt_flag(sngss7_info, FLAG_GLARE)) */ + } + } break; /**************************************************************************/ @@ -1265,13 +1263,12 @@ suspend_goto_restart: break; /**************************************************************************/ - }/*switch (ftdmchan->state) */ -#if 1 + } + if (state_flag) { /* clear the state change flag...since we might be setting a new state */ ftdm_channel_complete_state(ftdmchan); } -#endif return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index 4acf443be9..b433bfb20d 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -423,7 +423,7 @@ typedef struct sng_ss7_cfg { sng_isup_ckt_t isupCkt[10000]; /* KONRAD - only need 2000 ( and 0-1000 aren't used) since other servers are registerd else where */ sng_nsap_t nsap[MAX_NSAPS+1]; sng_isap_t isap[MAX_ISAPS+1]; -}sng_ss7_cfg_t; +} sng_ss7_cfg_t; typedef struct ftdm_sngss7_data { sng_ss7_cfg_t cfg; @@ -433,7 +433,7 @@ typedef struct ftdm_sngss7_data { int message_trace; int message_trace_level; fio_signal_cb_t sig_cb; -}ftdm_sngss7_data_t; +} ftdm_sngss7_data_t; typedef struct sngss7_timer_data { ftdm_timer_id_t hb_timer_id; @@ -442,13 +442,13 @@ typedef struct sngss7_timer_data { ftdm_sched_callback_t callback; ftdm_sched_t *sched; void *sngss7_info; -}sngss7_timer_data_t; +} sngss7_timer_data_t; typedef struct sngss7_glare_data { uint32_t spInstId; uint32_t circuit; SiConEvnt iam; -}sngss7_glare_data_t; +} sngss7_glare_data_t; typedef struct sngss7_group_data { uint32_t circuit; @@ -456,7 +456,7 @@ typedef struct sngss7_group_data { uint8_t status[255]; uint8_t type; uint8_t cause; -}sngss7_group_data_t; +} sngss7_group_data_t; typedef struct sngss7_chan_data { ftdm_channel_t *ftdmchan; @@ -473,20 +473,24 @@ typedef struct sngss7_chan_data { void *raw_data; /* send on next sigevent */ sngss7_glare_data_t glare; sngss7_timer_data_t t35; -}sngss7_chan_data_t; - -typedef struct sngss7_span_data { - ftdm_sched_t *sched; sngss7_group_data_t rx_grs; sngss7_group_data_t rx_gra; sngss7_group_data_t tx_grs; + sngss7_group_data_t ucic; +} sngss7_chan_data_t; + +#define SNGSS7_RX_GRS_PENDING (1 << 0) +#define SNGSS7_UCIC_PENDING (1 << 1) +#define SNGSS7_RX_GRA_PENDING (1 << 2) +typedef struct sngss7_span_data { + ftdm_sched_t *sched; + uint32_t flags; sngss7_group_data_t rx_cgb; sngss7_group_data_t tx_cgb; sngss7_group_data_t rx_cgu; sngss7_group_data_t tx_cgu; - sngss7_group_data_t ucic; ftdm_queue_t *event_queue; -}sngss7_span_data_t; +} sngss7_span_data_t; typedef struct sngss7_event_data { @@ -836,7 +840,6 @@ ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); ftdm_status_t copy_tknStr_to_sngss7(char* str, TknStr *tknStr, TknU8 *oddEven); int check_for_state_change(ftdm_channel_t *ftdmchan); -int check_cics_in_range(sngss7_chan_data_t *sngss7_info); int check_for_reset(sngss7_chan_data_t *sngss7_info); ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan); unsigned long get_unique_id(void); @@ -875,6 +878,7 @@ ftdm_status_t sngss7_add_raw_data(sngss7_chan_data_t *sngss7_info, uint8_t* data /* in ftmod_sangoma_ss7_timers.c */ void handle_isup_t35(void *userdata); + /******************************************************************************/ /* MACROS *********************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index 47249c2f5a..b65e0146e6 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -39,32 +39,6 @@ /* GLOBALS ********************************************************************/ -/* PROTOTYPES *****************************************************************/ -void ft_to_sngss7_iam(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_acm(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_anm(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_rel(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_rlc(ftdm_channel_t * ftdmchan); - -void ft_to_sngss7_rsc(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_rsca(ftdm_channel_t * ftdmchan); - -void ft_to_sngss7_blo(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_bla(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_ubl(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_uba(ftdm_channel_t * ftdmchan); - -void ft_to_sngss7_lpa(ftdm_channel_t * ftdmchan); - -void ft_to_sngss7_gra(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_grs(ftdm_channel_t * ftdmchan); - -void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan); - -void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan); - /* FUNCTIONS ******************************************************************/ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) { @@ -447,7 +421,6 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) { SS7_FUNC_TRACE_ENTER (__FUNCTION__); - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; SiStaEvnt gra; @@ -458,11 +431,11 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) /* fill in the range */ gra.rangStat.range.pres = PRSNT_NODEF; - gra.rangStat.range.val = sngss7_span->rx_grs.range; + gra.rangStat.range.val = sngss7_info->rx_grs.range; /* fill in the status */ gra.rangStat.status.pres = PRSNT_NODEF; - gra.rangStat.status.len = ((sngss7_span->rx_grs.range + 1) >> 3) + (((sngss7_span->rx_grs.range + 1) & 0x07) ? 1 : 0); + gra.rangStat.status.len = ((sngss7_info->rx_grs.range + 1) >> 3) + (((sngss7_info->rx_grs.range + 1) & 0x07) ? 1 : 0); /* the status field should be 1 if blocked for maintenace reasons * and 0 is not blocked....since we memset the struct nothing to do @@ -472,15 +445,15 @@ void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan) sng_cc_sta_request (1, 0, 0, - sngss7_span->rx_grs.circuit, + sngss7_info->rx_grs.circuit, 0, SIT_STA_GRSRSP, &gra); - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRA (%d:%d)\n", + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Tx GRA (%d:%d)\n", sngss7_info->circuit->cic, sngss7_info->circuit->cic, - (sngss7_info->circuit->cic + sngss7_span->rx_grs.range)); + (sngss7_info->circuit->cic + sngss7_info->rx_grs.range)); SS7_FUNC_TRACE_EXIT (__FUNCTION__); @@ -492,33 +465,55 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan) { SS7_FUNC_TRACE_ENTER (__FUNCTION__); - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + sngss7_chan_data_t *cinfo = NULL; sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; SiStaEvnt grs; - memset (&grs, 0x0, sizeof(grs)); - - grs.rangStat.eh.pres = PRSNT_NODEF; - grs.rangStat.range.pres = PRSNT_NODEF; - grs.rangStat.range.val = sngss7_span->tx_grs.range; - - sng_cc_sta_request (1, - 0, - 0, - sngss7_span->tx_grs.circuit, - 0, - SIT_STA_GRSREQ, - &grs); - - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRS (%d:%d)\n", - sngss7_info->circuit->cic, - sngss7_info->circuit->cic, - (sngss7_info->circuit->cic + sngss7_span->tx_grs.range)); + iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL); + curr = iter; + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_t *fchan = ftdm_iterator_current(curr); + ftdm_channel_lock(fchan); + + cinfo = fchan->call_data; + + if (!cinfo->tx_grs.range) { + + ftdm_channel_unlock(fchan); + + continue; + } + + memset (&grs, 0x0, sizeof(grs)); + grs.rangStat.eh.pres = PRSNT_NODEF; + grs.rangStat.range.pres = PRSNT_NODEF; + grs.rangStat.range.val = cinfo->tx_grs.range; + + sng_cc_sta_request (1, + 0, + 0, + cinfo->tx_grs.circuit, + 0, + SIT_STA_GRSREQ, + &grs); + + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx GRS (%d:%d)\n", + sngss7_info->circuit->cic, + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + cinfo->tx_grs.range)); + + memset(&cinfo->tx_grs, 0, sizeof(cinfo->tx_grs)); + + ftdm_channel_unlock(fchan); + } + + ftdm_iterator_free(iter); SS7_FUNC_TRACE_EXIT (__FUNCTION__); -return; } /******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 3c07f82933..34ebd6f18e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -47,7 +47,6 @@ uint32_t sngss7_id; /* PROTOTYPES *****************************************************************/ int check_for_state_change(ftdm_channel_t *ftdmchan); -int check_cics_in_range(sngss7_chan_data_t *sngss7_info); int check_for_reset(sngss7_chan_data_t *sngss7_info); unsigned long get_unique_id(void); @@ -61,14 +60,6 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan); ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan); -ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_rx_rsc_flags(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_tx_rsc_flags(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info); -ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info); - ftdm_status_t encode_subAddrIE_nsap(const char *subAddr, char *subAddrIE, int type); ftdm_status_t encode_subAddrIE_nat(const char *subAddr, char *subAddrIE, int type); @@ -862,45 +853,6 @@ int check_for_state_change(ftdm_channel_t *ftdmchan) return 0; } -/******************************************************************************/ -int check_cics_in_range(sngss7_chan_data_t *sngss7_info) -{ - - -#if 0 - ftdm_channel_t *tmp_ftdmchan; - sngss7_chan_data_t *tmp_sngss7_info; - int i = 0; - - /* check all the circuits in the range to see if we are the last ckt to reset */ - for ( i = sngss7_info->grs.circuit; i < ( sngss7_info->grs.range + 1 ); i++ ) { - if ( g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0 ) { - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCircuit[i].id, &tmp_sngss7_info, &tmp_ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCircuit[i].id); - return 0; - } - - /* check if the channel still has the reset flag done is up */ - if (!sngss7_test_ckt_flag(tmp_sngss7_info, FLAG_GRP_RESET_RX_DN)) { - SS7_DEBUG_CHAN(tmp_ftdmchan, "[CIC:%d] Still processing reset...\n", tmp_sngss7_info->circuit->cic); - return 0; - } - } /* if not siglink */ - } /* for */ - - SS7_DEBUG("All circuits out of reset: circuit=%d, range=%d\n", - sngss7_info->grs.circuit, - sngss7_info->grs.range); - return 1; - -#endif - - return 0; - -} - /******************************************************************************/ ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan) { @@ -961,67 +913,86 @@ unsigned long get_unique_id(void) /******************************************************************************/ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan) { - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; - int i; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_chan_data_t *cinfo = NULL; + int i = 0; + iter = ftdm_span_get_chan_iterator(ftdmspan, NULL); + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_t *fchan = ftdm_iterator_current(curr); - SS7_INFO("Rx GRS (%d:%d)\n", - g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic, - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_grs.circuit].cic + sngss7_span->rx_grs.range)); + ftdm_channel_lock(fchan); + + cinfo = fchan->call_data; - for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { - - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { - continue; - } - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + if (!cinfo->rx_grs.range) { + ftdm_channel_unlock(fchan); continue; } - /* check if the GRP_RESET_RX flag is already up */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) { - /* we have already processed this channel...move along */ - continue; + SS7_INFO("Rx GRS (%d:%d)\n", + g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_grs.circuit].cic, + (g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_grs.circuit].cic + cinfo->rx_grs.range)); + + for (i = cinfo->rx_grs.circuit; i < (cinfo->rx_grs.circuit + cinfo->rx_grs.range + 1); i++) { + + /* confirm this is a voice channel, otherwise we do nothing */ + if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { + continue; + } + + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + continue; + } + + /* check if the GRP_RESET_RX flag is already up */ + if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX)) { + /* we have already processed this channel...move along */ + continue; + } + + /* lock the channel */ + ftdm_channel_lock(ftdmchan); + + /* clear up any pending state changes */ + while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_ss7_process_state_change (ftdmchan); + } + + /* flag the channel as having received a reset */ + sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX); + + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* go to idle so that we can redo the restart state*/ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + + break; + /**************************************************************************/ + default: + + /* set the state of the channel to restart...the rest is done by the chan monitor */ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_channel_unlock(ftdmchan); + } - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); + ftdm_channel_unlock(fchan); + } - /* clear up any pending state changes */ - while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change (ftdmchan); - } - - /* flag the channel as having received a reset */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX); - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* go to idle so that we can redo the restart state*/ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**************************************************************************/ - default: - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) */ - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* for (chans in GRS */ + ftdm_iterator_free(iter); return FTDM_SUCCESS; } @@ -1029,191 +1000,244 @@ ftdm_status_t check_if_rx_grs_started(ftdm_span_t *ftdmspan) /******************************************************************************/ ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan) { - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; - int i; - int byte = 0; - int bit = 0; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_chan_data_t *cinfo = NULL; + int i = 0, bn = 0; + int byte = 0, bit = 0; + int cic_start = 0, cic_end = 0, num_cics = 0; + ftdm_bitmap_t *lockmap = 0; + ftdm_size_t mapsize = 0; - /* check all the circuits in the range to see if they are done resetting */ - for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + iter = ftdm_span_get_chan_iterator(ftdmspan, NULL); + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_t *fchan = ftdm_iterator_current(curr); + + ftdm_channel_lock(fchan); + + cinfo = fchan->call_data; + + if (!cinfo->rx_grs.range) { + + ftdm_channel_unlock(fchan); - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { continue; } - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - continue; + cic_start = cinfo->rx_grs.circuit; + cic_end = cinfo->rx_grs.circuit + cinfo->rx_grs.range; + num_cics = cinfo->rx_grs.range + 1; + mapsize = (num_cics / FTDM_BITMAP_NBITS) + 1; + + lockmap = ftdm_calloc(mapsize, sizeof(*lockmap)); + if (!lockmap) { + ftdm_channel_unlock(fchan); + return FTDM_ENOMEM; } - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); + /* check all the circuits in the range to see if they are done resetting */ + for (i = cic_start, bn = 0; i <= cic_end; i++, bn++) { - /* check if there is a state change pending on the channel */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - /* check the state to the GRP_RESET_RX_DN flag */ - if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) { - /* this channel is still resetting...do nothing */ + /* confirm this is a voice channel, otherwise we do nothing */ + if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { + continue; + } + + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n"); + continue; + } + + /* lock the channel */ + ftdm_channel_lock(ftdmchan); + ftdm_map_set_bit(lockmap, bn); + + /* check if there is a state change pending on the channel */ + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + /* check the state to the GRP_RESET_RX_DN flag */ + if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) { + /* this channel is still resetting...do nothing */ goto GRS_UNLOCK_ALL; - } /* if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */ - } else { - /* state change pending */ - goto GRS_UNLOCK_ALL; - } - } /* for ( i = circuit; i < (circuit + range + 1); i++) */ + } /* if (!sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */ + } else { + /* state change pending */ + goto GRS_UNLOCK_ALL; + } - SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", - sngss7_span->rx_grs.circuit, - sngss7_span->rx_grs.range); - - /* check all the circuits in the range to see if they are done resetting */ - for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { - - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { - continue; } - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i); - /* check if we need to die */ - SS7_ASSERT; - /* move along */ - continue; + SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", cinfo->rx_grs.circuit, cinfo->rx_grs.range); + for (i = cic_start; i <= cic_end; i++) { + + /* confirm this is a voice channel, otherwise we do nothing */ + if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { + continue; + } + + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i); + ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n"); + continue; + } + + /* throw the GRP reset flag complete flag */ + sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); + + /* move the channel to the down state */ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + /* update the status map if the ckt is in blocked state */ + if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) || + (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { + + cinfo->rx_grs.status[byte] = (cinfo->rx_grs.status[byte] | (1 << bit)); + } + + /* update the bit and byte counter*/ + bit ++; + if (bit == 8) { + byte++; + bit = 0; + } + } - - /* throw the GRP reset flag complete flag */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); - - /* move the channel to the down state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - /* update the status map if the ckt is in blocked state */ - if ((sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) || - (sngss7_test_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { - - sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit)); - } /* if blocked */ - - /* update the bit and byte counter*/ - bit ++; - if (bit == 8) { - byte++; - bit = 0; - } - } /* for ( i = circuit; i < (circuit + range + 1); i++) */ - GRS_UNLOCK_ALL: - for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + for (i = cic_start, bn = 0; i <= cic_end; i++, bn++) { + /* confirm this is a voice channel, otherwise we do nothing */ + if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { + continue; + } - /* confirm this is a voice channel, otherwise we do nothing */ - if (g_ftdm_sngss7_data.cfg.isupCkt[i].type != SNG_CKT_VOICE) { - continue; + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + ftdm_assert(FTDM_FALSE, "Failed to extract channel data during GRS\n"); + continue; + } + if (ftdm_map_test_bit(lockmap, bn)) { + /* unlock the channel */ + ftdm_channel_unlock(ftdmchan); + ftdm_map_clear_bit(lockmap, bn); + } } - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - continue; - } + ftdm_safe_free(lockmap); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + ftdm_channel_unlock(fchan); } + ftdm_iterator_free(iter); + return FTDM_SUCCESS; } /******************************************************************************/ ftdm_status_t check_if_rx_gra_started(ftdm_span_t *ftdmspan) { - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; - int i; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_chan_data_t *cinfo = NULL; + int i = 0; - SS7_INFO("Rx GRA (%d:%d)\n", - g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic, - (g_ftdm_sngss7_data.cfg.isupCkt[sngss7_span->rx_gra.circuit].cic + sngss7_span->rx_gra.range)); + iter = ftdm_span_get_chan_iterator(ftdmspan, NULL); - for (i = sngss7_span->rx_gra.circuit; i < (sngss7_span->rx_gra.circuit + sngss7_span->rx_gra.range + 1); i++) { + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_t *fchan = ftdm_iterator_current(curr); + ftdm_channel_lock(fchan); + + cinfo = fchan->call_data; + + if (!cinfo->rx_gra.range) { + + ftdm_channel_unlock(fchan); - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); continue; } - /* check if the channel is already procoessing the GRA */ - if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) { - /* move along */ - continue; - } + SS7_INFO("Rx GRA (%d:%d)\n", + g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_gra.circuit].cic, + (g_ftdm_sngss7_data.cfg.isupCkt[cinfo->rx_gra.circuit].cic + cinfo->rx_gra.range)); - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); + for (i = cinfo->rx_gra.circuit; i < (cinfo->rx_gra.circuit + cinfo->rx_gra.range + 1); i++) { - /* clear up any pending state changes */ - while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change (ftdmchan); - } - - - - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); - - /* go to DOWN */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - - /* do nothing, just drop the message */ - SS7_DEBUG("Receveived GRA in down state, dropping\n"); - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_TERMINATING: - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); - - break; - /**********************************************************************/ - default: - /* ITU Q764-2.9.5.1.c -> release the circuit */ - if (sngss7_span->rx_gra.cause != 0) { - ftdmchan->caller_data.hangup_cause = sngss7_span->rx_gra.cause; - } else { - ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + continue; } - /* go to terminating to hang up the call */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /**********************************************************************/ + /* check if the channel is already processing the GRA */ + if (sngss7_test_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) { + /* move along */ + continue; + } + + /* lock the channel */ + ftdm_channel_lock(ftdmchan); + + /* clear up any pending state changes */ + while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_ss7_process_state_change (ftdmchan); + } + + switch (ftdmchan->state) { + /**********************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); + + /* go to DOWN */ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: + + /* do nothing, just drop the message */ + SS7_DEBUG("Receveived GRA in down state, dropping\n"); + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_TERMINATING: + case FTDM_CHANNEL_STATE_HANGUP: + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_ckt_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); + + break; + /**********************************************************************/ + default: + /* ITU Q764-2.9.5.1.c -> release the circuit */ + if (cinfo->rx_gra.cause != 0) { + ftdmchan->caller_data.hangup_cause = cinfo->rx_gra.cause; + } else { + ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ + } + + /* go to terminating to hang up the call */ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + break; + /**********************************************************************/ + } + + ftdm_channel_unlock(ftdmchan); } - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* for ( circuits in request */ + ftdm_channel_unlock(fchan); + } + ftdm_iterator_free(iter); return FTDM_SUCCESS; } @@ -1286,41 +1310,66 @@ ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan) /******************************************************************************/ ftdm_status_t process_span_ucic(ftdm_span_t *ftdmspan) { - ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; - int i; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_chan_data_t *cinfo = NULL; + sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data; + int i = 0; - for (i = sngss7_span->ucic.circuit; i < (sngss7_span->ucic.circuit + sngss7_span->ucic.range + 1); i++) { + iter = ftdm_span_get_chan_iterator(ftdmspan, NULL); + curr = iter; + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_t *fchan = ftdm_iterator_current(curr); + + ftdm_channel_lock(fchan); + + cinfo = fchan->call_data; + + if (!cinfo->ucic.range) { + + ftdm_channel_unlock(fchan); - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); continue; } - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); + for (i = cinfo->ucic.circuit; i < (cinfo->ucic.circuit + cinfo->ucic.range + 1); i++) { - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx UCIC\n", sngss7_info->circuit->cic); + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + continue; + } - /* clear up any pending state changes */ - while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change (ftdmchan); + /* lock the channel */ + ftdm_channel_lock(ftdmchan); + + SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Rx UCIC\n", sngss7_info->circuit->cic); + + /* clear up any pending state changes */ + while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_ss7_process_state_change (ftdmchan); + } + + /* throw the ckt block flag */ + sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); + + /* set the channel to suspended state */ + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_channel_unlock(ftdmchan); } + /* clear out the ucic data since we're done with it */ + memset(&cinfo->ucic, 0, sizeof(cinfo->ucic)); - /* throw the ckt block flag */ - sngss7_set_ckt_blk_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); - - /* set the channel to suspended state */ - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); + ftdm_channel_unlock(fchan); } - /* clear out the ucic data since we're done with it */ - memset(&sngss7_span->ucic, 0x0, sizeof(sngss7_group_data_t)); + ftdm_clear_flag(sngss7_span, SNGSS7_UCIC_PENDING); + + ftdm_iterator_free(iter); return FTDM_SUCCESS; } @@ -1339,11 +1388,36 @@ ftdm_status_t clear_rx_grs_flags(sngss7_chan_data_t *sngss7_info) /******************************************************************************/ ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info) { - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + sngss7_chan_data_t *cinfo = NULL; + ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; + sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmchan->span->signal_data; - /* clear the rx_grs data fields */ - memset(&sngss7_span->rx_grs, 0x0, sizeof(sngss7_group_data_t)); + memset(&sngss7_info->rx_grs, 0, sizeof(sngss7_info->rx_grs)); + + iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL); + curr = iter; + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_t *fchan = ftdm_iterator_current(curr); + + ftdm_channel_lock(fchan); + + cinfo = fchan->call_data; + if (cinfo->rx_grs.range) { + /* there is still another grs pending, do not clear the SNGSS7_RX_GRS_PENDING flag yet */ + ftdm_channel_unlock(fchan); + goto done; + } + + ftdm_channel_unlock(fchan); + } + + /* if we're here is because there is no other grs going on now in this span */ + ftdm_clear_flag(sngss7_span, SNGSS7_RX_GRS_PENDING); + +done: + ftdm_iterator_free(iter); return FTDM_SUCCESS; } @@ -1351,11 +1425,38 @@ ftdm_status_t clear_rx_grs_data(sngss7_chan_data_t *sngss7_info) /******************************************************************************/ ftdm_status_t clear_rx_gra_data(sngss7_chan_data_t *sngss7_info) { - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; + ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; + sngss7_chan_data_t *cinfo = NULL; + ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; + sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; /* clear the rx_grs data fields */ - memset(&sngss7_span->rx_gra, 0x0, sizeof(sngss7_group_data_t)); + memset(&sngss7_info->rx_gra, 0, sizeof(sngss7_info->rx_gra)); + + iter = ftdm_span_get_chan_iterator(ftdmchan->span, NULL); + curr = iter; + for (curr = iter; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_t *fchan = ftdm_iterator_current(curr); + + ftdm_channel_lock(fchan); + + cinfo = fchan->call_data; + if (cinfo->rx_gra.range) { + /* there is still another gra pending, do not clear the SNGSS7_RX_GRA_PENDING flag yet */ + ftdm_channel_unlock(fchan); + goto done; + } + + ftdm_channel_unlock(fchan); + } + + /* if we're here is because there is no other gra pending in this span */ + ftdm_clear_flag(sngss7_span, SNGSS7_RX_GRA_PENDING); + +done: + + ftdm_iterator_free(iter); return FTDM_SUCCESS; } @@ -1374,12 +1475,8 @@ ftdm_status_t clear_tx_grs_flags(sngss7_chan_data_t *sngss7_info) /******************************************************************************/ ftdm_status_t clear_tx_grs_data(sngss7_chan_data_t *sngss7_info) { - ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan; - sngss7_span_data_t *sngss7_span = ftdmchan->span->signal_data; - - /* clear the rx_grs data fields */ - memset(&sngss7_span->tx_grs, 0x0, sizeof(sngss7_group_data_t)); - + /* clear everything up */ + memset(&sngss7_info->tx_grs, 0, sizeof(sngss7_info->tx_grs)); return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/include/ftdm_threadmutex.h b/libs/freetdm/src/include/ftdm_threadmutex.h index c5afb46eb5..2e802fe913 100644 --- a/libs/freetdm/src/include/ftdm_threadmutex.h +++ b/libs/freetdm/src/include/ftdm_threadmutex.h @@ -43,14 +43,14 @@ FT_DECLARE(void) ftdm_thread_override_default_stacksize(ftdm_size_t size); FT_DECLARE(ftdm_status_t) ftdm_mutex_create(ftdm_mutex_t **mutex); FT_DECLARE(ftdm_status_t) ftdm_mutex_destroy(ftdm_mutex_t **mutex); -#define ftdm_mutex_lock(_x) _ftdm_mutex_lock(_x) -FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(ftdm_mutex_t *mutex); +#define ftdm_mutex_lock(_x) _ftdm_mutex_lock(__FILE__, __LINE__, __FUNCTION__, _x) +FT_DECLARE(ftdm_status_t) _ftdm_mutex_lock(const char *file, int line, const char *func, ftdm_mutex_t *mutex); -#define ftdm_mutex_trylock(_x) _ftdm_mutex_trylock(_x) -FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(ftdm_mutex_t *mutex); +#define ftdm_mutex_trylock(_x) _ftdm_mutex_trylock(__FILE__, __LINE__, __FUNCTION__, _x) +FT_DECLARE(ftdm_status_t) _ftdm_mutex_trylock(const char *file, int line, const char *func, ftdm_mutex_t *mutex); -#define ftdm_mutex_unlock(_x) _ftdm_mutex_unlock(_x) -FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(ftdm_mutex_t *mutex); +#define ftdm_mutex_unlock(_x) _ftdm_mutex_unlock(__FILE__, __LINE__, __FUNCTION__, _x) +FT_DECLARE(ftdm_status_t) _ftdm_mutex_unlock(const char *file, int line, const char *func, ftdm_mutex_t *mutex); FT_DECLARE(ftdm_status_t) ftdm_interrupt_create(ftdm_interrupt_t **cond, ftdm_socket_t device); FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **cond); diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 67015c6fdf..e4be27ce40 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -719,8 +719,8 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void * */ #define ftdm_socket_close(it) if (it > -1) { close(it); it = -1;} -#define ftdm_channel_lock(chan) ftdm_mutex_lock(chan->mutex) -#define ftdm_channel_unlock(chan) ftdm_mutex_unlock(chan->mutex) +#define ftdm_channel_lock(chan) ftdm_mutex_lock((chan)->mutex) +#define ftdm_channel_unlock(chan) ftdm_mutex_unlock((chan)->mutex) #define ftdm_log_throttle(level, ...) \ time_current_throttle_log = ftdm_current_time_in_ms(); \ @@ -777,6 +777,13 @@ static __inline__ int16_t ftdm_saturated_add(int16_t sample1, int16_t sample2) return (int16_t)addres; } +/* Bitmap helper functions */ +typedef long ftdm_bitmap_t; +#define FTDM_BITMAP_NBITS (sizeof(ftdm_bitmap_t) * 8) +#define ftdm_map_set_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] |= ((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS))) +#define ftdm_map_clear_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] &= ~((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS))) +#define ftdm_map_test_bit(map, bit) (map[(bit/FTDM_BITMAP_NBITS)] & ((ftdm_bitmap_t)1 << (bit % FTDM_BITMAP_NBITS))) + #ifdef __cplusplus } #endif