Merge branch 'releases.3.4' into releases.3.5

Conflicts:
	libs/freetdm/mod_freetdm/mod_freetdm.c
	libs/freetdm/src/ftdm_state.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c
	libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c
This commit is contained in:
David Yat Sin 2012-04-26 16:13:26 -04:00
commit 5226489c39
13 changed files with 469 additions and 154 deletions

View File

@ -0,0 +1,43 @@
SS7 Native Bridge
Native bridge is enabled on 2 conditions:
* The SIP header FreeTDM-TransUUID is set in the originating leg and matches a freetdm channel
* The variable freetdm_native_sigbridge is true and the originating leg is also a freetdm channel
Some coding rules apply to this feature:
- Each channel is responsible for clearning its own peer_data and event queue
at the end of the call (when moving to DOWN state)
- Each channel dequeues messages only from its own queue and enqueues messages
in the peer's queue, with the only exception being messages received before
the bridge is stablished (IAM for sure and possible SAM messages) because
if the bridge is not yet stablished the messages must be queued by the channel
in its own queue temporarily until the bridge is ready
- When the bridge is ready it is the responsibility of the incoming channel to
move the messages that stored temporarily in its own queue to the bridged peer queue
- During hangup, each channel is responsible for moving itself to DOWN. The procedure
however differs slightly depending on the hangup conditions
If the user requests hangup (ie, FreeSWITCH) the request will be noted by setting the
FTDM_CHANNEL_USER_HANGUP flag but will not be processed yet because call control is
driven only by the link messages (so no hangup from ESL or command line allowed)
When REL message comes, the channel receiving it must move to TERMINATING state and:
- If the user has not hangup yet (FTDM_CHANNEL_USER_HANGUP flag not set) then
notify the user via SIGEVENT_STOP and wait for the user to move to HANGUP
state by calling ftdm_channel_call_hangup() before sending RLC
- If the user did hangup already (FTDM_CHANNEL_USER_HANGUP flag is set) then
skip user notification and move to HANGUP state directly where the RLC message
will be sent
- On HANGUP state the RLC is sent and the channel is moved to DOWN, final state
The peer channel will forward the REL message and wait for RLC from the network, when
RLC is received the channel can move straight to DOWN itself because the peer channel
is completing its own shutdown procedure when it received the REL message

View File

@ -1409,7 +1409,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
chan_id = 0;
}
if (session && globals.sip_headers) {
if (session && globals.sip_headers && !switch_core_session_check_interface (session,freetdm_endpoint_interface) ) {
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *sipvar;
@ -1474,7 +1474,7 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-LOC-NADI");
if (sipvar) {
ftdm_usrmsg_add_var(&usrmsg, "ss7_loc_nadi", sipvar);
}
}
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-DNIS-TON");
if (sipvar) {
@ -1726,7 +1726,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
ftdm_channel_get_span_id(peer_private->ftdmchan), ftdm_channel_get_id(peer_private->ftdmchan));
switch_core_session_rwunlock(network_peer);
}
/* Figure out if there is a native bridge requested through dial plan variable and the originating channel is also freetdm (not going through SIP) */
} else if (session
&& (var = channel_get_variable(session, var_event, FREETDM_VAR_PREFIX "native_sigbridge"))
@ -2043,6 +2042,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
if (!ftdm_strlen_zero(var_value)) {
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OCN", "%s", var_value);
}
var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_ocn_nadi");
if (!ftdm_strlen_zero(var_value)) {
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OCN-NADI", "%s", var_value);

View File

@ -2203,9 +2203,12 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *
{
ftdm_status_t status = FTDM_SUCCESS;
if (ftdm_test_flag(chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
/* In native sigbridge mode we ignore hangup requests from the user and hangup only when the signaling module decides it */
if (ftdm_test_flag(chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE) && chan->state != FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan_ex(chan, file, func, line, FTDM_LOG_LEVEL_DEBUG,
"Ignoring hangup in channel in state %s (native bridge enabled)\n", ftdm_channel_state2str(chan->state));
ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP);
goto done;
}

View File

@ -48,7 +48,6 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c
ftdm_time_t diff = 0;
ftdm_channel_state_t state = fchan->state;
#if 0
/* I could not perform this sanity check without more disruptive changes. Ideally we should check here if the signaling module completing the state
executed a state processor (called ftdm_channel_advance_states() which call fchan->span->state_processor(fchan)) for the state. That is just a
@ -59,6 +58,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_complete_state(const char *file, const c
ftdm_channel_advance_states() would set the state_status to PROCESSING and then the check below for STATUS_NEW would be valid. Currently is not
valid because the signaling module may be completing the state at the end of the state_processor callback and therefore the state will still be
in STATUS_NEW, and is perfectly valid ... */
if (fchan->state_status == FTDM_STATE_STATUS_NEW) {
ftdm_log_chan_ex(fchan, file, func, line, FTDM_LOG_LEVEL_CRIT,
"Asking to complete state change from %s to %s in %llums, but the state is still unprocessed (this might be a bug!)\n",

View File

@ -35,7 +35,7 @@
*
*/
#if 0
#if 0
#define SMG_RELAY_DBG
#endif
@ -1332,7 +1332,7 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span,
}
#ifdef SMG_RELAY_DBG
stream->write_function(stream," blk_flag=%x | ckt_flag=%x | chan_flag=%x", ss7_info->blk_flags, ss7_info->ckt_flags, ftdmchan->flags);
stream->write_function(stream," | blk_flag=%x | ckt_flag=%x", ss7_info->blk_flags, ss7_info->ckt_flags);
#endif
stream->write_function(stream, "\n");
} /* if ( hole, sig, voice) */
@ -1374,36 +1374,26 @@ static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int c
}
if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
/* 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", ss7_info->circuit->cic);
/* check if we need to die */
ftdm_assert(0, "State change not completed\n");
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
/* move to the next channel */
continue;
} else {
/* throw the ckt block flag */
sngss7_set_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
/* 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);
}
} /* if ( span and chan) */
}
} /* if ( cic != 0) */
/* go the next circuit */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
}
handle_show_blocks(stream, span, chan, verbose);
@ -1440,33 +1430,22 @@ static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int c
}
if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) {
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
/* 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", ss7_info->circuit->cic);
/* check if we need to die */
ftdm_assert(0, "State change not completed\n");
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
/* move to the next channel */
continue;
} else {
/* throw the ckt block flag */
sngss7_set_ckt_blk_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX);
/* clear the block flag */
sngss7_clear_ckt_blk_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX);
/* check group blocking */
sngss7_clear_ckt_blk_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX);
/* 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);
}
@ -1812,6 +1791,8 @@ static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int c
/* throw the grp maint. block flag */
sngss7_set_ckt_blk_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
/* bring the sig status down */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
@ -1945,6 +1926,7 @@ static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int c
/* bring the sig status up */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
/* if this is the first channel in the range */
if (!main_chan) {

View File

@ -131,6 +131,16 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* KONRAD FIX ME : check in case there is a ckt and grp block */
}
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX_DN);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_SENT);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX_DN);
sngss7_clear_ckt_flag(sngss7_info, FLAG_FULL_NUMBER);
/* check whether the ftdm channel is in a state to accept a call */
switch (ftdmchan->state) {
@ -175,6 +185,12 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* fill in ANI */
ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits);
}
else {
if (g_ftdm_sngss7_data.cfg.force_inr) {
sngss7_set_ckt_flag(sngss7_info, FLAG_INR_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT);
}
}
if (siConEvnt->cgPtyNum.scrnInd.pres) {
/* fill in the screening indication value */
@ -186,6 +202,11 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val;
}
} else {
if (g_ftdm_sngss7_data.cfg.force_inr) {
sngss7_set_ckt_flag(sngss7_info, FLAG_INR_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT);
}
SS7_INFO_CHAN(ftdmchan,"No Calling party (ANI) information in IAM!%s\n", " ");
}
@ -436,10 +457,26 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/**************************************************************************/
case (INFORMATION):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx INF\n", sngss7_info->circuit->cic);
SS7_DEBUG_CHAN (ftdmchan, "Cancelling T.39 timer %s\n", " ");
/* check if t39 is active */
if (sngss7_info->t39.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t39.sched, sngss7_info->t39.hb_timer_id);
SS7_DEBUG_CHAN (ftdmchan, "T.39 timer has been cancelled upon receiving INF message %s\n", " ");
}
sngss7_set_ckt_flag(sngss7_info, FLAG_INF_RX_DN);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
break;
/**************************************************************************/
case (INFORMATREQ):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx INR\n", sngss7_info->circuit->cic);
ft_to_sngss7_inf(ftdmchan, siCnStEvnt);
sngss7_set_ckt_flag(sngss7_info, FLAG_INR_RX);
break;
/**************************************************************************/
case (SUBSADDR):
@ -1143,11 +1180,12 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
break;
/**************************************************************************/
case SIT_STA_CGBRSP: /* mntc. oriented CGB response */
/*handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/
SS7_INFO(" Rx CGBA \n");
break;
/**************************************************************************/
case SIT_STA_CGURSP: /* mntc. oriented CGU response */
/*SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));*/
SS7_INFO(" Rx CGUA \n");
break;
/**************************************************************************/
case SIT_STA_GRSREQ: /* circuit group reset request */
@ -2472,6 +2510,8 @@ ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* bring the sig status down */
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_DOWN);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
/* unlock the channel again before we exit */
ftdm_mutex_unlock(ftdmchan->mutex);
@ -2589,8 +2629,7 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
while( x < loop_range ) {
if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != SNG_CKT_VOICE) {
loop_range++;
}
else {
} else {
if (extract_chan_data(x, &sngss7_info, &ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x);
}
@ -2627,7 +2666,8 @@ ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ
if (sngss7_channel_status_clear(sngss7_info)) {
sngss7_set_sig_status(sngss7_info, FTDM_SIG_STATE_UP);
}
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED);
ftdm_mutex_unlock(ftdmchan->mutex);
/* update the bit and byte counter*/

View File

@ -81,6 +81,7 @@ void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCo
/* initalize the sngss7_event */
sngss7_event = ftdm_malloc(sizeof(*sngss7_event));
if (sngss7_event == NULL) {
SS7_ERROR("Failed to allocate memory for sngss7_event!\n");
SS7_FUNC_TRACE_EXIT(__FUNCTION__);

View File

@ -340,10 +340,9 @@ static void handle_hw_alarm(ftdm_event_t *e)
/* MONITIOR THREADS ***********************************************************/
static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
{
ftdm_interrupt_t *ftdm_sangoma_ss7_int[3];
ftdm_interrupt_t *ftdm_sangoma_ss7_int[2];
ftdm_span_t *ftdmspan = (ftdm_span_t *) obj;
ftdm_channel_t *ftdmchan = NULL;
ftdm_channel_t *peerchan = NULL;
ftdm_event_t *event = NULL;
sngss7_event_data_t *sngss7_event = NULL;
sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->signal_data;
@ -368,12 +367,6 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
goto ftdm_sangoma_ss7_run_exit;
}
/* get an interrupt queue for this span for peer channel events */
if (ftdm_queue_get_interrupt (sngss7_span->peer_chans, &ftdm_sangoma_ss7_int[2]) != FTDM_SUCCESS) {
SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for peer channel events queue!\n", ftdmspan->span_id);
goto ftdm_sangoma_ss7_run_exit;
}
while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) {
int x = 0;
if (b_alarm_test) {
@ -410,42 +403,26 @@ 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))) {
sngss7_chan_data_t *chan_info = ftdmchan->call_data;
/*first lock the channel */
ftdm_mutex_lock(ftdmchan->mutex);
/* process state changes for this channel until they are all done */
ftdm_channel_advance_states(ftdmchan);
if (chan_info->peer_data) {
/* clean out all pending stack events in the peer channel */
while ((sngss7_event = ftdm_queue_dequeue(chan_info->event_queue))) {
ftdm_sangoma_ss7_process_peer_stack_event(ftdmchan, sngss7_event);
ftdm_safe_free(sngss7_event);
}
}
/* unlock the channel */
ftdm_mutex_unlock (ftdmchan->mutex);
}
/* clean out all peer pending channel events */
while ((peerchan = ftdm_queue_dequeue (sngss7_span->peer_chans))) {
/* note that the channels being dequeued here may not belong to this span
they may belong to just about any other span that one of our channels
happens to be bridged to */
sngss7_chan_data_t *peer_info = peerchan->call_data;
sngss7_chan_data_t *chan_info = peer_info->peer_data;
ftdmchan = chan_info->ftdmchan;
/*
if there is any state changes at all, those will be done in the opposite channel
to peerchan (where the original event was received), therefore we must lock ftdmchan,
but do not need to lock peerchan as we only read its event queue, which is already
locked when dequeueing */
ftdm_channel_lock(ftdmchan);
/* clean out all pending stack events in the peer channel */
while ((sngss7_event = ftdm_queue_dequeue(peer_info->event_queue))) {
ftdm_sangoma_ss7_process_peer_stack_event(ftdmchan, sngss7_event);
ftdm_safe_free(sngss7_event);
}
ftdm_channel_unlock(ftdmchan);
}
/* clean out all pending stack events */
while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) {
ftdm_sangoma_ss7_process_stack_event(sngss7_event);
@ -561,16 +538,16 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
ftdm_channel_advance_states(ftdmchan);
if (sngss7_event->event_id == SNGSS7_CON_IND_EVENT) {
/* this is the first event in a call, flush the event queue */
sngss7_flush_queue(sngss7_info->event_queue);
/* clear the peer if any */
sngss7_info->peer_data = NULL;
clone_event++;
}
/* if the call has already started and the event is not a release confirmation, clone the event */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED) &&
sngss7_event->event_id != SNGSS7_REL_CFM_EVENT) {
/* If the call has already started (we only bridge events related to calls)
* and the event is not a release confirmation, then clone the event.
* We do not clone release cfm events because that is the only event (final event) that is not
* bridged to the other leg, the first Spirou customer we had explicitly requested to send
* release confirm as soon as the release is received and therefore not wait for the other leg
* to send release confirm (hence, not need to clone and enqueue in the other leg) */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED) && sngss7_event->event_id != SNGSS7_REL_CFM_EVENT) {
clone_event++;
}
@ -597,11 +574,38 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
event_clone = ftdm_calloc(1, sizeof(*sngss7_event));
if (event_clone) {
memcpy(event_clone, sngss7_event, sizeof(*sngss7_event));
ftdm_queue_enqueue(sngss7_info->event_queue, event_clone);
/* if we have already a peer channel then enqueue the event in their queue */
if (sngss7_info->peer_data) {
sngss7_span_data_t *sngss7_peer_span = (sngss7_span_data_t *)sngss7_info->peer_data->ftdmchan->span->signal_data;
ftdm_span_t *peer_span = sngss7_info->peer_data->ftdmchan->span;
if (sngss7_info->peer_event_transfer_cnt) {
sngss7_event_data_t *peer_event = NULL;
int qi = 0;
/* looks like for the first time we found our peer, transfer any messages we enqueued */
for (qi = 0; qi < sngss7_info->peer_event_transfer_cnt; qi++) {
peer_event = ftdm_queue_dequeue(sngss7_info->event_queue);
if (peer_event) {
ftdm_queue_enqueue(sngss7_info->peer_data->event_queue, peer_event);
} else {
/* This should never happen! */
SS7_CRIT_CHAN(ftdmchan,"[CIC:%d]What!? someone stole my messages!\n", sngss7_info->circuit->cic);
}
}
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Transferred %d messages into my peer's queue\n",
sngss7_info->circuit->cic, sngss7_info->peer_event_transfer_cnt);
sngss7_info->peer_event_transfer_cnt = 0;
}
/* we already have a peer attached, wake him up */
ftdm_queue_enqueue(sngss7_peer_span->peer_chans, sngss7_info->ftdmchan);
ftdm_queue_enqueue(sngss7_info->peer_data->event_queue, event_clone);
ftdm_queue_enqueue(peer_span->pendingchans, sngss7_info->peer_data->ftdmchan);
} else {
/* we don't have a peer yet, save the event on our own queue for later
* only the first event in this queue is directly consumed by our peer (IAM), subsequent events
* must be transferred by us to their queue as soon as we find our peer */
ftdm_queue_enqueue(sngss7_info->event_queue, event_clone);
if (sngss7_event->event_id != SNGSS7_CON_IND_EVENT) {
/* This could be an SAM, save it for transfer once we know who our peer is (if we ever find that) */
sngss7_info->peer_event_transfer_cnt++;
}
}
}
}
@ -614,25 +618,7 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case SNGSS7_REL_CFM_EVENT:
{
if (sngss7_info->peer_data) {
ftdm_channel_t *peer_chan = sngss7_info->peer_data->ftdmchan;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
if (peer_chan) {
/* we need to unlock our chan or we risk deadlock */
ftdm_channel_advance_states(ftdmchan);
ftdm_channel_unlock(ftdmchan);
ftdm_channel_lock(peer_chan);
if (peer_chan->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_set_state(peer_chan, FTDM_CHANNEL_STATE_DOWN);
}
ftdm_channel_unlock(peer_chan);
ftdm_channel_lock(ftdmchan);
}
}
}
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
default:
break;
@ -1011,7 +997,11 @@ static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t
ftdm_channel_t *close_chan = ftdmchan;
sngss7_clear_ckt_flag(sngss7_info, FLAG_SUS_RECVD);
sngss7_clear_ckt_flag(sngss7_info, FLAG_T6_CANCELED);
sngss7_clear_ckt_flag (sngss7_info, FLAG_SENT_ACM);
sngss7_clear_ckt_flag (sngss7_info, FLAG_SENT_CPG);
sngss7_flush_queue(sngss7_info->event_queue);
sngss7_info->peer_data = NULL;
ftdm_channel_close (&close_chan);
}
break;
@ -1026,9 +1016,22 @@ static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t
case FTDM_CHANNEL_STATE_TERMINATING:
{
ft_to_sngss7_rlc(ftdmchan);
/* Release confirm is sent immediately, since Spirou customer asked us not to wait for the second call leg
* to come back with a release confirm ... */
/* when receiving REL we move to TERMINATING and notify the user that the bridge is ending */
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_STOP);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP)) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP);
} else {
/* Notify the user and wait for their ack before sending RLC */
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_STOP);
}
}
break;
case FTDM_CHANNEL_STATE_HANGUP:
{
ft_to_sngss7_rlc(ftdmchan);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
}
break;
@ -1053,11 +1056,11 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan)
sngss7_info->blk_flags);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
/* DIALING is the only state we process normally when doing an outgoing call that is natively bridged */
/* DIALING is the only state we process normally when doing an outgoing call that is natively bridged,
* all other states are run by a different state machine (and the freetdm core does not do any checking) */
if (ftdmchan->state != FTDM_CHANNEL_STATE_DIALING) {
return ftdm_sangoma_ss7_native_bridge_state_change(ftdmchan);
}
sngss7_info->peer_data = NULL;
}
/*check what state we are supposed to be in */
@ -1080,23 +1083,91 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan)
}
/* check if the end of pulsing (ST) character has arrived or the right number of digits */
if (ftdmchan->caller_data.dnis.digits[i-1] == 'F') {
if (ftdmchan->caller_data.dnis.digits[i-1] == 'F'
|| sngss7_test_ckt_flag(sngss7_info, FLAG_FULL_NUMBER) )
{
SS7_DEBUG_CHAN(ftdmchan, "Received the end of pulsing character %s\n", "");
/* remove the ST */
ftdmchan->caller_data.dnis.digits[i-1] = '\0';
/*now go to the RING state */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
if (!sngss7_test_ckt_flag(sngss7_info, FLAG_FULL_NUMBER)) {
/* remove the ST */
ftdmchan->caller_data.dnis.digits[i-1] = '\0';
sngss7_set_ckt_flag(sngss7_info, FLAG_FULL_NUMBER);
}
if (sngss7_test_ckt_flag(sngss7_info, FLAG_INR_TX)) {
if (!sngss7_test_ckt_flag(sngss7_info, FLAG_INR_SENT) ) {
ft_to_sngss7_inr(ftdmchan);
sngss7_set_ckt_flag(sngss7_info, FLAG_INR_SENT);
SS7_DEBUG_CHAN (ftdmchan, "Scheduling T.39 timer %s \n", " ");
/* start ISUP t39 */
if (ftdm_sched_timer (sngss7_info->t39.sched,
"t39",
sngss7_info->t39.beat,
sngss7_info->t39.callback,
&sngss7_info->t39,
&sngss7_info->t39.hb_timer_id))
{
SS7_ERROR ("Unable to schedule timer T39, hanging up call!\n");
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
/* end the call */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
}
}else {
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
} else {
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
} else if (i >= sngss7_info->circuit->min_digits) {
SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, sngss7_info->circuit->min_digits);
/*now go to the RING state */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
if (sngss7_test_ckt_flag(sngss7_info, FLAG_INR_TX)) {
if (!sngss7_test_ckt_flag(sngss7_info, FLAG_INR_SENT) ) {
ft_to_sngss7_inr(ftdmchan);
sngss7_set_ckt_flag(sngss7_info, FLAG_INR_SENT);
SS7_DEBUG_CHAN (ftdmchan, "Scheduling T.39 timer %s\n", " " );
/* start ISUP t39 */
if (ftdm_sched_timer (sngss7_info->t39.sched,
"t39",
sngss7_info->t39.beat,
sngss7_info->t39.callback,
&sngss7_info->t39,
&sngss7_info->t39.hb_timer_id))
{
SS7_ERROR ("Unable to schedule timer T39, hanging up call!\n");
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
sngss7_set_ckt_flag (sngss7_info, FLAG_LOCAL_REL);
/* end the call */
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
}
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_IDLE);
}else {
if (sngss7_test_ckt_flag(sngss7_info, FLAG_INF_RX_DN) ) {
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
}
} else {
state_flag = 0;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
} else {
/* if we are coming from idle state then we have already been here once before */
if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) {
@ -1152,6 +1223,15 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan)
/**************************************************************************/
case FTDM_CHANNEL_STATE_RING: /*incoming call request */
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_SENT);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INR_RX_DN);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_TX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_SENT);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX);
sngss7_clear_ckt_flag(sngss7_info, FLAG_INF_RX_DN);
if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) {
SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n");
break;
@ -1162,6 +1242,11 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan)
ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id);
}
/* cancel t39 timer */
if (sngss7_info->t39.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t39.sched, sngss7_info->t39.hb_timer_id);
}
SS7_DEBUG_CHAN(ftdmchan, "Sending incoming call from %s to %s to FTDM core\n",
ftdmchan->caller_data.ani.digits,
ftdmchan->caller_data.dnis.digits);
@ -1512,19 +1597,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan)
if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) {
ftdm_channel_t *close_chan = ftdmchan;
/* detach native bridging if needed (only the outbound leg is responsible for that)
Inbound leg was responsible of flushing its queue of events, but peer attach/detach
is left as an outbound leg responsibility
*/
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sngss7_chan_data_t *peer_info = sngss7_info->peer_data;
sngss7_info->peer_data = NULL;
if (peer_info) {
peer_info->peer_data = NULL;
}
}
/* close the channel */
SS7_DEBUG_CHAN(ftdmchan,"FTDM Channel Close %s\n", "");
sngss7_flush_queue(sngss7_info->event_queue);
@ -2404,12 +2476,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
return FTDM_FAIL;
}
/* create an peer channel queue for this span */
if ((ftdm_queue_create(&(ss7_span_info)->peer_chans, SNGSS7_PEER_CHANS_QUEUE_SIZE)) != FTDM_SUCCESS) {
SS7_CRITICAL("Unable to create peer chans queue!\n");
return FTDM_FAIL;
}
/*setup the span structure with the info so far */
g_ftdm_sngss7_data.sig_cb = sig_cb;
span->start = ftdm_sangoma_ss7_start;

View File

@ -395,6 +395,7 @@ typedef struct sng_isup_ckt {
uint16_t t16;
uint16_t t17;
uint32_t t35;
uint32_t t39;
uint16_t tval;
} sng_isup_ckt_t;
@ -466,6 +467,7 @@ typedef struct sng_ss7_cfg {
sng_nsap_t nsap[MAX_NSAPS+1];
sng_isap_t isap[MAX_ISAPS+1];
sng_glare_resolution glareResolution;
uint32_t force_inr;
} sng_ss7_cfg_t;
typedef struct ftdm_sngss7_data {
@ -517,12 +519,14 @@ typedef struct sngss7_chan_data {
sngss7_glare_data_t glare;
sngss7_timer_data_t t35;
sngss7_timer_data_t t10;
sngss7_timer_data_t t39;
sngss7_group_data_t rx_grs;
sngss7_group_data_t rx_gra;
sngss7_group_data_t tx_grs;
sngss7_group_data_t ucic;
ftdm_queue_t *event_queue;
struct sngss7_chan_data *peer_data;
struct sngss7_chan_data *peer_data;
uint8_t peer_event_transfer_cnt;
} sngss7_chan_data_t;
#define SNGSS7_RX_GRS_PENDING (1 << 0)
@ -536,7 +540,6 @@ typedef struct sngss7_span_data {
sngss7_group_data_t rx_cgu;
sngss7_group_data_t tx_cgu;
ftdm_queue_t *event_queue;
ftdm_queue_t *peer_chans;
} sngss7_span_data_t;
typedef struct sngss7_event_data
@ -584,6 +587,15 @@ typedef enum {
FLAG_SENT_CPG = (1 << 17),
FLAG_SUS_RECVD = (1 << 18),
FLAG_T6_CANCELED = (1 << 19),
FLAG_INR_TX = (1 << 20),
FLAG_INR_SENT = (1 << 21),
FLAG_INR_RX = (1 << 22),
FLAG_INR_RX_DN = (1 << 23),
FLAG_INF_TX = (1 << 24),
FLAG_INF_SENT = (1 << 25),
FLAG_INF_RX = (1 << 26),
FLAG_INF_RX_DN = (1 << 27),
FLAG_FULL_NUMBER = (1 << 28),
FLAG_RELAY_DOWN = (1 << 30),
FLAG_CKT_RECONFIG = (1 << 31)
} sng_ckt_flag_t;
@ -606,6 +618,14 @@ typedef enum {
"INF_RESUME", \
"INF_PAUSED", \
"TX_ACM_SENT" \
"TX_INR" \
"INR_SENT" \
"RX_INR" \
"RX_INR_DN" \
"TX_INF" \
"INF SENT" \
"RX_INF" \
"RX_INF_DN" \
"RELAY_DOWN", \
"CKT_RECONFIG"
FTDM_STR2ENUM_P(ftmod_ss7_ckt_state2flag, ftmod_ss7_ckt_flag2str, sng_ckt_flag_t)
@ -820,6 +840,9 @@ void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_itx (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_txa (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_inr(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_inf(ftdm_channel_t *ftdmchan, SiCnStEvnt *inr);
/* in ftmod_sangoma_ss7_in.c */
@ -949,6 +972,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);
void handle_isup_t10(void *userdata);
void handle_isup_t39(void *userdata);
/******************************************************************************/
@ -970,7 +994,7 @@ if (ftdmchan->state == new_state) { \
#define SS7_INFO_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_INFO, msg , ##args)
#define SS7_WARN_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_WARNING, msg , ##args)
#define SS7_ERROR_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_ERROR, msg , ##args)
#define SS7_CTRIT_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_CRIT, msg , ##args)
#define SS7_CRIT_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_CRIT, msg , ##args)
#ifdef SS7_CODE_DEVEL
#define SS7_DEVEL_DEBUG(a,...) ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ );

View File

@ -48,6 +48,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
SiConEvnt iam;
ftdm_bool_t native_going_up = FTDM_FALSE;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
sngss7_event_data_t *event_clone = NULL;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@ -75,28 +76,25 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Starting native bridge with peer CIC %d\n",
sngss7_info->circuit->cic, peer_info->circuit->cic);
/* retrieve only first message from the others guys queue (must be IAM) */
event_clone = ftdm_queue_dequeue(peer_info->event_queue);
/* make each one of us aware of the native bridge */
peer_info->peer_data = sngss7_info;
sngss7_info->peer_data = peer_info;
/* flush our own queue */
sngss7_flush_queue(sngss7_info->event_queue);
/* Go to up until release comes, note that state processing is done different and much simpler when there is a peer,
We can't go to UP state right away yet though, so do not set the state to UP here, wait until the end of this function
because moving from one state to another causes the ftdmchan->usrmsg structure to be wiped
because moving from one state to another causes the ftdmchan->usrmsg structure to be wiped
and we still need those variables for further IAM processing */
native_going_up = FTDM_TRUE;
}
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE) && sngss7_info->peer_data) {
sngss7_span_data_t *span_data = ftdmchan->span->signal_data;
sngss7_event_data_t *event_clone = ftdm_queue_dequeue(sngss7_info->peer_data->event_queue);
/* Retrieve IAM from our peer */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
if (!event_clone) {
SS7_ERROR_CHAN(ftdmchan, "No event clone in peer queue!%s\n", "");
SS7_ERROR_CHAN(ftdmchan, "No IAM event clone in peer queue!%s\n", "");
} else if (event_clone->event_id != SNGSS7_CON_IND_EVENT) {
/* first message in the queue should ALWAYS be an IAM */
SS7_ERROR_CHAN(ftdmchan, "Invalid initial peer message type '%d'\n", event_clone->event_id);
@ -141,9 +139,6 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
}
}
/* since this is the first time we dequeue an event from the peer, make sure our main thread process any other events,
this will trigger the interrupt in our span peer_chans queue which will wake up our main thread if it is sleeping */
ftdm_queue_enqueue(span_data->peer_chans, sngss7_info->peer_data->ftdmchan);
} else if (sngss7_info->circuit->transparent_iam &&
sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) {
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic);
@ -234,12 +229,107 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
the user sending FTDM_SIGEVENT_UP which can cause the application to misbehave (ie, no audio) */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
ftdm_channel_advance_states(ftdmchan);
}
}
ftdm_safe_free(event_clone);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
void ft_to_sngss7_inf(ftdm_channel_t *ftdmchan, SiCnStEvnt *inr)
{
SiCnStEvnt evnt;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
memset (&evnt, 0x0, sizeof (evnt));
evnt.infoInd.eh.pres = PRSNT_NODEF;
evnt.infoInd.cgPtyAddrRespInd.pres = PRSNT_NODEF;
evnt.infoInd.cgPtyCatRespInd.pres = PRSNT_NODEF;
evnt.infoInd.chrgInfoRespInd.pres = PRSNT_NODEF;
evnt.infoInd.chrgInfoRespInd.val = 0;
evnt.infoInd.solInfoInd.pres = PRSNT_NODEF;
evnt.infoInd.solInfoInd.val = 0;
evnt.infoInd.holdProvInd.pres = PRSNT_NODEF;
evnt.infoInd.holdProvInd.val = 0;
evnt.infoInd.spare.pres = PRSNT_NODEF;
evnt.infoInd.spare.val = 0;
if (inr->infoReqInd.eh.pres == PRSNT_NODEF) {
if ((inr->infoReqInd.holdingInd.pres == PRSNT_NODEF) && (inr->infoReqInd.holdingInd.val == HOLD_REQ)) {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting holding information. Holding is not supported in INF.\n", sngss7_info->circuit->cic);
}
if ((inr->infoReqInd.chrgInfoReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.chrgInfoReqInd.val == CHRGINFO_REQ)) {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting charging information. Charging is not supported in INF.\n", sngss7_info->circuit->cic);
}
if ((inr->infoReqInd.malCaIdReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.malCaIdReqInd.val == CHRGINFO_REQ)) {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR requesting malicious call id. Malicious call id is not supported in INF.\n", sngss7_info->circuit->cic);
}
if ((inr->infoReqInd.cgPtyAdReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.cgPtyAdReqInd.val == CGPRTYADDREQ_REQ)) {
evnt.infoInd.cgPtyAddrRespInd.val=CGPRTYADDRESP_INCL;
copy_cgPtyNum_to_sngss7 (ftdmchan, &evnt.cgPtyNum);
} else {
evnt.infoInd.cgPtyAddrRespInd.val=CGPRTYADDRESP_NOTINCL;
}
if ((inr->infoReqInd.cgPtyCatReqInd.pres == PRSNT_NODEF) && (inr->infoReqInd.cgPtyCatReqInd.val == CGPRTYCATREQ_REQ)) {
evnt.infoInd.cgPtyCatRespInd.val = CGPRTYCATRESP_INCL;
copy_cgPtyCat_to_sngss7 (ftdmchan, &evnt.cgPtyCat);
} else {
evnt.infoInd.cgPtyCatRespInd.val = CGPRTYCATRESP_NOTINCL;
}
}
else {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Received INR with no information request. Sending back default INF.\n", sngss7_info->circuit->cic);
}
sng_cc_inf(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&evnt,
INFORMATION);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx INF\n", sngss7_info->circuit->cic);
}
void ft_to_sngss7_inr(ftdm_channel_t *ftdmchan)
{
SiCnStEvnt evnt;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
memset (&evnt, 0x0, sizeof (evnt));
evnt.infoReqInd.eh.pres = PRSNT_NODEF;
evnt.infoReqInd.cgPtyAdReqInd.pres = PRSNT_NODEF;
evnt.infoReqInd.cgPtyAdReqInd.val=CGPRTYADDREQ_REQ;
evnt.infoReqInd.holdingInd.pres = PRSNT_NODEF;
evnt.infoReqInd.holdingInd.val = HOLD_REQ;
evnt.infoReqInd.cgPtyCatReqInd.pres = PRSNT_NODEF;
evnt.infoReqInd.cgPtyCatReqInd.val = CGPRTYCATREQ_REQ;
evnt.infoReqInd.chrgInfoReqInd.pres = PRSNT_NODEF;
evnt.infoReqInd.chrgInfoReqInd.val = CHRGINFO_REQ;
evnt.infoReqInd.malCaIdReqInd.pres = PRSNT_NODEF;
evnt.infoReqInd.malCaIdReqInd.val = MLBG_INFOREQ;
sng_cc_inr(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&evnt,
INFORMATREQ);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx INR\n", sngss7_info->circuit->cic);
}
void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);

View File

@ -186,7 +186,7 @@ ftdm_status_t copy_cgPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPt
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
cgPtyNum->natAddrInd.val = atoi(clg_nadi);
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number Presentation Ind %d\n", cgPtyNum->presRest.val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number NADI value %d\n", cgPtyNum->natAddrInd.val);
return copy_tknStr_to_sngss7(caller_data->cid_num.digits, &cgPtyNum->addrSig, &cgPtyNum->oddEven);
}
@ -257,7 +257,7 @@ ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *loc
locPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].loc_nadi;
locPtyNum->scrnInd.pres = pres_val;
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_screen_ind");
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_screen_ind");
if (!ftdm_strlen_zero(val)) {
locPtyNum->scrnInd.val = atoi(val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Screening Ind %d\n", locPtyNum->scrnInd.val);

View File

@ -49,7 +49,7 @@
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
void handle_isup_t35(void *userdata);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
@ -76,10 +76,13 @@ void handle_isup_t35(void *userdata)
/* end the call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
/* kill t10 if active */
/* kill t10 t39 if active */
if (sngss7_info->t10.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id);
}
if (sngss7_info->t39.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t39.sched, sngss7_info->t39.hb_timer_id);
}
/*unlock*/
ftdm_channel_unlock(ftdmchan);
@ -108,7 +111,43 @@ void handle_isup_t10(void *userdata)
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
void handle_isup_t39(void *userdata)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_timer_data_t *timer = userdata;
sngss7_chan_data_t *sngss7_info = timer->sngss7_info;
ftdm_channel_t *ftdmchan = sngss7_info->ftdmchan;
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_channel_lock(ftdmchan);
/* Q.764 2.2.5 Address incomplete (T35 expiry action is hangup with cause 28 according to Table A.1/Q.764) */
SS7_ERROR("[Call-Control] Timer 39 expired on CIC = %d\n", sngss7_info->circuit->cic);
/* set the flag to indicate this hangup is started from the local side */
sngss7_set_ckt_flag(sngss7_info, FLAG_LOCAL_REL);
/* hang up on timer expiry */
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_INVALID_NUMBER_FORMAT;
/* end the call */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
/* kill t10 t35 if active */
if (sngss7_info->t10.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t10.sched, sngss7_info->t10.hb_timer_id);
}
if (sngss7_info->t35.hb_timer_id) {
ftdm_sched_cancel_timer (sngss7_info->t35.sched, sngss7_info->t35.hb_timer_id);
}
/*unlock*/
ftdm_channel_unlock(ftdmchan);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
}
/******************************************************************************/
/* For Emacs:
* Local Variables:

View File

@ -146,6 +146,7 @@ typedef struct sng_ccSpan
uint32_t t16;
uint32_t t17;
uint32_t t35;
uint32_t t39;
uint32_t tval;
} sng_ccSpan_t;
@ -487,6 +488,7 @@ static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen)
/* Set the transparent_iam_max_size to default value */
g_ftdm_sngss7_data.cfg.transparent_iam_max_size=800;
g_ftdm_sngss7_data.cfg.force_inr = 0;
/* extract all the information from the parameters */
for (i = 0; i < num_parms; i++) {
@ -508,6 +510,14 @@ static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen)
ftmod_ss7_set_glare_resolution (parm->val);
SS7_DEBUG("Found glare resolution configuration = %d %s\n", g_ftdm_sngss7_data.cfg.glareResolution, parm->val );
}
else if (!strcasecmp(parm->var, "force-inr")) {
if (ftdm_true(parm->val)) {
g_ftdm_sngss7_data.cfg.force_inr = 1;
} else {
g_ftdm_sngss7_data.cfg.force_inr = 0;
}
SS7_DEBUG("Found INR force configuration = %s\n", parm->val );
}
else {
SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
return FTDM_FAIL;
@ -2004,7 +2014,6 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
flag_loc_nadi = 1;
sng_ccSpan.loc_nadi = atoi(parm->val);
SS7_DEBUG("Found default LOC_NADI parm->value = %d\n", sng_ccSpan.loc_nadi);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "lpa_on_cot")) {
/**********************************************************************/
@ -2062,6 +2071,11 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
sng_ccSpan.t35 = atoi(parm->val);
SS7_DEBUG("Found isup t35 = %d\n",sng_ccSpan.t35);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.t39")) {
/**********************************************************************/
sng_ccSpan.t39 = atoi(parm->val);
SS7_DEBUG("Found isup t39 = %d\n",sng_ccSpan.t39);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "isup.tval")) {
/**********************************************************************/
sng_ccSpan.tval = atoi(parm->val);
@ -3044,6 +3058,12 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t35 = ccSpan->t35;
}
if (ccSpan->t39 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t39 = 120;
} else {
g_ftdm_sngss7_data.cfg.isupCkt[x].t39 = ccSpan->t39;
}
if (ccSpan->tval == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].tval = 10;
} else {
@ -3148,6 +3168,13 @@ static int ftmod_ss7_fill_in_circuits(sng_span_t *sngSpan)
ss7_info->t10.callback = handle_isup_t10;
ss7_info->t10.sngss7_info = ss7_info;
/* prepare the timer structures */
ss7_info->t39.sched = ((sngss7_span_data_t *)(ftdmspan->signal_data))->sched;
ss7_info->t39.counter = 1;
ss7_info->t39.beat = (isupCkt->t39) * 100; /* beat is in ms, t39 is in 100ms */
ss7_info->t39.callback = handle_isup_t39;
ss7_info->t39.sngss7_info = ss7_info;
/**************************************************************************/
} /* for (i == 1; i < ftdmspan->chan_count; i++) */