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 a0bf95b09c..a9735c9b62 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 @@ -99,7 +99,11 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ SS7_ASSERT; }; - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n"); + if (sngss7_info->glare.spInstId > 0) { + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM (glare detected on circuit)\n"); + } else { + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n"); + } /* check if the circuit has a remote block */ if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || @@ -208,11 +212,36 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ break; /**************************************************************************/ + case (FTDM_CHANNEL_STATE_DIALING): + case (FTDM_CHANNEL_STATE_TERMINATING): + case (FTDM_CHANNEL_STATE_HANGUP): + case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE): + + SS7_INFO_CHAN(ftdmchan, "Got IAM on channel in %s state...glare!\n", ftdm_channel_state2str (ftdmchan->state)); + + /* save the info so that we can use it later on */ + sngss7_info->glare.spInstId = spInstId; + sngss7_info->glare.circuit = circuit; + memcpy(&sngss7_info->glare.iam, siConEvnt, sizeof(*siConEvnt)); + + if (!(sngss7_test_flag(sngss7_info, FLAG_GLARE))) { + /* glare, throw the flag */ + sngss7_set_flag(sngss7_info, FLAG_GLARE); + + /* setup the hangup cause */ + ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */ + + /* this is a remote hangup request */ + sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + + /* move the state of the channel to Terminating to end the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + } + + break; + /**************************************************************************/ default: /* should not have gotten an IAM while in this state */ - SS7_ERROR("Got IAM in an invalid state (%s) on span=%d, chan=%d!\n", - ftdm_channel_state2str(ftdmchan->state), - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); + SS7_ERROR_CHAN(ftdmchan, "Got IAM on channel in invalid state(%s)...reset!\n", ftdm_channel_state2str (ftdmchan->state)); /* move the state of the channel to RESTART to force a reset */ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); @@ -1028,10 +1057,26 @@ ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t ci SS7_ASSERT; }; - /* glare, throw the flag, go to down state*/ - sngss7_set_flag(sngss7_info, FLAG_GLARE); + if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) { + /* the glare flag is already up so it was caught ... do nothing */ + SS7_DEBUG_CHAN(ftdmchan, "Glare flag is already up...nothing to do!%s\n", " "); + } else { + SS7_DEBUG_CHAN(ftdmchan, "Glare flag is not up yet...indicating glare from reattempt!%s\n", " "); + /* glare, throw the flag */ + sngss7_set_flag(sngss7_info, FLAG_GLARE); - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + /* clear any existing glare data from the channel */ + memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t)); + + /* setup the hangup cause */ + ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */ + + /* this is a remote hangup request */ + sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + + /* move the state of the channel to Terminating to end the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + } /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); 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 a9851bda3f..da90d34b48 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 @@ -303,24 +303,17 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) /* clean out all pending channel state changes */ while ((ftdmchan = ftdm_queue_dequeue (ftdmspan->pendingchans))) { - /* double check that this channel has a state change pending */ - if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - /*first lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); + + /*first lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + /* process state changes for this channel until they are all done */ + while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { ftdm_sangoma_ss7_process_state_change (ftdmchan); - - /* unlock the channel */ - ftdm_mutex_unlock (ftdmchan->mutex); - } else { - /* since we handle state changes again after handling the trillium queue - * this can occur since we'll clear the flag for the event but can't pop - * the channel out of pendingchans - */ -/* SS7_ERROR("ftdm_core reported state change, but state change flag not set on ft-span = %d, ft-chan = %d\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id);*/ } + + /* unlock the channel */ + ftdm_mutex_unlock (ftdmchan->mutex); }/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans))) */ /* clean out all pending stack events */ @@ -451,6 +444,11 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev /* now that we have the right channel...put a lock on it so no-one else can use it */ ftdm_mutex_lock(ftdmchan->mutex); + /* while there's a state change present on this channel process it */ + while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_ss7_process_state_change(ftdmchan); + } + /* figure out the type of event and send it to the right handler */ switch (sngss7_event->event_id) { /**************************************************************************/ @@ -748,7 +746,11 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) /* go to RESTART State until RSCa is received */ ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART); } else { - if (!(sngss7_test_flag (sngss7_info, FLAG_RESET_RX))) { + /* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */ + if (!(sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) && + !(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) && + !(sngss7_test_flag(sngss7_info, FLAG_GLARE))) { + /* send out the release complete */ ft_to_sngss7_rlc (ftdmchan); } @@ -879,7 +881,26 @@ static void 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_flag(sngss7_info, FLAG_GLARE)) { + + /* clear the glare flag */ + sngss7_clear_flag (sngss7_info, FLAG_GLARE); + + /* check if we have an IAM stored...if we don't have one just exit */ + if (sngss7_info->glare.circuit != 0) { + /* send the saved call back in to us */ + handle_con_ind (0, + sngss7_info->glare.spInstId, + sngss7_info->glare.circuit, + &sngss7_info->glare.iam); + + /* clear the glare info */ + memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t)); + } /* if (sngss7_info->glare.circuit != 0) */ + } /* if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) */ break; /**************************************************************************/ @@ -1167,11 +1188,13 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) SS7_ASSERT; }; + /* check if the channel sig state is UP */ if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, cancelling call!%s\n", " "); goto outgoing_fail; } + /* check if there is a remote block */ if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { @@ -1181,15 +1204,19 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) goto outgoing_break; } + /* check if there is a local block */ if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) || (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) { + /* KONRAD FIX ME : we should check if this is a TEST call and allow it */ + /* the channel is blocked...can't send any calls here */ SS7_ERROR_CHAN(ftdmchan, "Requested channel is locally blocked, re-hunt channel!%s\n", " "); goto outgoing_break; } + /* check the state of the channel */ switch (ftdmchan->state){ /**************************************************************************/ case FTDM_CHANNEL_STATE_DOWN: @@ -1208,7 +1235,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) ftdmchan->physical_span_id, ftdmchan->physical_chan_id); - goto outgoing_fail; + goto outgoing_break; break; /**************************************************************************/ } /* switch (ftdmchan->state) (original call) */ 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 3bf12ae307..45cf4957b6 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 @@ -321,8 +321,7 @@ typedef struct sngss7_timer_data { }sngss7_timer_data_t; typedef struct sngss7_glare_data { - uint32_t suInstId; - uint32_t spInstId; + uint32_t spInstId; uint32_t circuit; SiConEvnt iam; }sngss7_glare_data_t; @@ -612,31 +611,40 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha #define SS7_MSG_TRACE(fchan, sngss7info ,msg) if (g_ftdm_sngss7_data.message_trace) { \ switch (g_ftdm_sngss7_data.message_trace_level) { \ case 0: \ - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ case 1: \ - ftdm_log_chan(fchan, FTDM_LOG_ALERT, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_ALERT, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ case 2: \ - ftdm_log_chan(fchan, FTDM_LOG_CRIT, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_CRIT, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ case 3: \ - ftdm_log_chan(fchan, FTDM_LOG_ERROR, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_ERROR, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ case 4: \ - ftdm_log_chan(fchan, FTDM_LOG_WARNING, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_WARNING, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ case 5: \ - ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ case 6: \ - ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ case 7: \ - ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ default: \ - ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \ + ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ break; \ } /* switch (g_ftdm_sngss7_data.message_trace_level) */ \ } /* if(g_ftdm_sngss7_data.message_trace) */