Merge branch 'releases.3.4' into releases.3.4.experimental_head

Conflicts:
	libs/freetdm/mod_freetdm/mod_freetdm.c
This commit is contained in:
Moises Silva 2012-01-31 15:37:33 -05:00
commit cafff50005
13 changed files with 815 additions and 42 deletions

View File

@ -124,6 +124,8 @@ struct private_object {
ftdm_channel_t *ftdmchan;
uint32_t write_error;
uint32_t read_error;
char network_peer_uuid[SWITCH_UUID_FORMATTED_LENGTH + 1];
};
/* private data attached to FTDM channels (only FXS for now) */
@ -626,11 +628,20 @@ static switch_status_t channel_on_hangup(switch_core_session_t *session)
case FTDM_CHAN_TYPE_CAS:
case FTDM_CHAN_TYPE_B:
{
const char *var = NULL;
ftdm_call_cause_t hcause = switch_channel_get_cause_q850(channel);
if (hcause < 1 || hcause > 127) {
hcause = FTDM_CAUSE_DESTINATION_OUT_OF_ORDER;
}
ftdm_channel_call_hangup_with_cause(tech_pvt->ftdmchan, hcause);
var = switch_channel_get_variable(channel, "ss7_rel_loc");
if (var) {
ftdm_usrmsg_t usrmsg;
memset(&usrmsg, 0, sizeof(ftdm_usrmsg_t));
ftdm_usrmsg_add_var(&usrmsg, "ss7_rel_loc", var);
ftdm_channel_call_hangup_with_cause_ex(tech_pvt->ftdmchan, hcause, &usrmsg);
} else {
ftdm_channel_call_hangup_with_cause(tech_pvt->ftdmchan, hcause);
}
}
break;
default:
@ -1304,10 +1315,15 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
int argc = 0;
const char *var;
const char *dest_num = NULL, *callerid_num = NULL;
const char *network_peer_uuid = NULL;
char sigbridge_peer[255];
switch_channel_t *peer_chan = NULL;
switch_channel_t *our_chan = NULL;
ftdm_hunting_scheme_t hunting;
ftdm_usrmsg_t usrmsg;
memset(&usrmsg, 0, sizeof(ftdm_usrmsg_t));
memset(sigbridge_peer, 0, sizeof(sigbridge_peer));
if (!outbound_profile) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Missing caller profile\n");
@ -1394,6 +1410,9 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
if (session && globals.sip_headers) {
switch_channel_t *channel = switch_core_session_get_channel(session);
const char *sipvar;
network_peer_uuid = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-TransUUID");
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-CallerName");
if (sipvar) {
ftdm_set_string(caller_data.cid_name, sipvar);
@ -1564,6 +1583,10 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
caller_data.pres = FTDM_PRES_RESTRICTED;
}
if ((var = channel_get_variable(session, var_event, "freetdm_iam_fwd_ind_isdn_access_ind"))) {
ftdm_usrmsg_add_var(&usrmsg, "iam_fwd_ind_isdn_access_ind", var);
}
if ((var = channel_get_variable(session, var_event, "freetdm_bearer_capability"))) {
caller_data.bearer_capability = (uint8_t)atoi(var);
}
@ -1650,6 +1673,25 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
goto fail;
}
our_chan = switch_core_session_get_channel(*new_session);
if (network_peer_uuid) {
switch_core_session_t *network_peer = switch_core_session_locate(network_peer_uuid);
if (network_peer) {
const char *my_uuid = switch_core_session_get_uuid(*new_session);
private_t *peer_private = switch_core_session_get_private(network_peer);
switch_set_string(tech_pvt->network_peer_uuid, network_peer_uuid);
switch_set_string(peer_private->network_peer_uuid, my_uuid);
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Session %s is network-bridged with %s\n",
my_uuid, network_peer_uuid);
snprintf(sigbridge_peer, sizeof(sigbridge_peer), "%u:%u",
ftdm_channel_get_span_id(peer_private->ftdmchan), ftdm_channel_get_id(peer_private->ftdmchan));
switch_core_session_rwunlock(network_peer);
}
}
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
caller_profile->destination_number = switch_core_strdup(caller_profile->pool, switch_str_nil(dest_num));
caller_profile->caller_id_number = switch_core_strdup(caller_profile->pool, switch_str_nil(callerid_num));
@ -1661,6 +1703,21 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
hunt_data.tech_pvt = tech_pvt;
caller_data.priv = &hunt_data;
if (session
&& (var = channel_get_variable(session, var_event, FREETDM_VAR_PREFIX "native_sigbridge"))
&& switch_true(var)
&& switch_core_session_compare(*new_session, session)) {
private_t *peer_pvt = switch_core_session_get_private(session);
snprintf(sigbridge_peer, sizeof(sigbridge_peer), "%u:%u",
ftdm_channel_get_span_id(peer_pvt->ftdmchan), ftdm_channel_get_id(peer_pvt->ftdmchan));
}
if (session && !zstr(sigbridge_peer)) {
peer_chan = switch_core_session_get_channel(session);
ftdm_usrmsg_add_var(&usrmsg, "sigbridge_peer", sigbridge_peer);
}
if ((status = ftdm_call_place_ex(&caller_data, &hunting, &usrmsg)) != FTDM_SUCCESS) {
if (tech_pvt->read_codec.implementation) {
switch_core_codec_destroy(&tech_pvt->read_codec);
@ -1678,6 +1735,12 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
goto fail;
}
if (our_chan && peer_chan) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO,
"Bridging native signaling of channel %s to channel %s\n",
switch_channel_get_name(peer_chan), switch_channel_get_name(our_chan));
}
return SWITCH_CAUSE_SUCCESS;
}
@ -1804,6 +1867,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
if (globals.sip_headers) {
switch_channel_set_variable(channel, "sip_h_X-FreeTDM-SpanName", ftdm_channel_get_span_name(sigmsg->channel));
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-TransUUID", "%s",switch_core_session_get_uuid(session));
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-SpanNumber", "%d", spanid);
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-ChanNumber", "%d", chanid);

View File

@ -52,9 +52,7 @@
struct tm *localtime_r(const time_t *clock, struct tm *result);
#endif
#define FORCE_HANGUP_TIMER 3000
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
#define FORCE_HANGUP_TIMER 30000
#define FTDM_READ_TRACE_INDEX 0
#define FTDM_WRITE_TRACE_INDEX 1
#define MAX_CALLIDS 6000
@ -2205,6 +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)) {
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));
goto done;
}
if (chan->state != FTDM_CHANNEL_STATE_DOWN) {
if (chan->state == FTDM_CHANNEL_STATE_HANGUP) {
/* make user's life easier, and just ignore double hangup requests */
@ -2231,6 +2235,8 @@ static ftdm_status_t _ftdm_channel_call_hangup_nl(const char *file, const char *
ftdm_channel_close(&chan);
}
}
done:
return status;
}
@ -2326,6 +2332,15 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch
ftdm_channel_lock(ftdmchan);
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG,
"Ignoring indication %s in channel in state %s (native bridge enabled)\n",
ftdm_channel_indication2str(indication),
ftdm_channel_state2str(ftdmchan->state));
status = FTDM_SUCCESS;
goto done;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_IND_ACK_PENDING)) {
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_WARNING, "Cannot indicate %s in channel with indication %s still pending in state %s\n",
ftdm_channel_indication2str(indication),
@ -2426,10 +2441,50 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_reset(const char *file, const char *func
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_get_channel_from_string(const char *string_id, ftdm_span_t **out_span, ftdm_channel_t **out_channel)
{
ftdm_status_t status = FTDM_SUCCESS;
int rc = 0;
ftdm_span_t *span = NULL;
ftdm_channel_t *ftdmchan = NULL;
unsigned span_id = 0;
unsigned chan_id = 0;
*out_span = NULL;
*out_channel = NULL;
rc = sscanf(string_id, "%u:%u", &span_id, &chan_id);
if (rc != 2) {
ftdm_log(FTDM_LOG_ERROR, "Failed to parse channel id string '%s'\n", string_id);
status = FTDM_EINVAL;
goto done;
}
status = ftdm_span_find(span_id, &span);
if (status != FTDM_SUCCESS || !span) {
ftdm_log(FTDM_LOG_ERROR, "Failed to find span for channel id string '%s'\n", string_id);
status = FTDM_EINVAL;
goto done;
}
if (chan_id > (FTDM_MAX_CHANNELS_SPAN+1) || !(ftdmchan = span->channels[chan_id])) {
ftdm_log(FTDM_LOG_ERROR, "Invalid channel id string '%s'\n", string_id);
status = FTDM_EINVAL;
goto done;
}
status = FTDM_SUCCESS;
*out_span = span;
*out_channel = ftdmchan;
done:
return status;
}
/* this function MUST be called with the channel lock held with lock recursivity of 1 exactly,
* and the caller must be aware we might unlock the channel for a brief period of time and then lock it again */
static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan, ftdm_usrmsg_t *usrmsg)
{
const char *var = NULL;
ftdm_status_t status = FTDM_FAIL;
ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel");
@ -2465,6 +2520,16 @@ static ftdm_status_t _ftdm_channel_call_place_nl(const char *file, const char *f
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_CALL_STARTED);
ftdm_call_set_call_id(ftdmchan, &ftdmchan->caller_data);
var = ftdm_usrmsg_get_var(usrmsg, "sigbridge_peer");
if (var) {
ftdm_span_t *peer_span = NULL;
ftdm_channel_t *peer_chan = NULL;
ftdm_set_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
ftdm_get_channel_from_string(var, &peer_span, &peer_chan);
if (peer_chan) {
ftdm_set_flag(peer_chan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
}
}
/* if the signaling stack left the channel in state down on success, is expecting us to move to DIALING */
if (ftdmchan->state == FTDM_CHANNEL_STATE_DOWN) {
@ -2666,6 +2731,7 @@ static ftdm_status_t ftdm_channel_done(ftdm_channel_t *ftdmchan)
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_ANSWERED);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_USER_HANGUP);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_DIGITAL_MEDIA);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE);
ftdm_mutex_lock(ftdmchan->pre_buffer_mutex);
ftdm_buffer_destroy(&ftdmchan->pre_buffer);
ftdmchan->pre_buffer_size = 0;
@ -5465,7 +5531,7 @@ static void execute_safety_hangup(void *data)
ftdm_channel_lock(fchan);
fchan->hangup_timer = 0;
if (fchan->state == FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER);
ftdm_log_chan(fchan, FTDM_LOG_WARNING, "Forcing hangup since the user did not confirmed our hangup after %dms\n", FORCE_HANGUP_TIMER);
_ftdm_channel_call_hangup_nl(__FILE__, __FUNCTION__, __LINE__, fchan, NULL);
} else {
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "Not performing safety hangup, channel state is %s\n", ftdm_channel_state2str(fchan->state));

View File

@ -263,6 +263,9 @@ static ftdm_status_t ftdm_core_set_state(const char *file, const char *func, int
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
goto perform_state_change;
}
if (ftdmchan->span->state_map) {
ok = ftdm_parse_state_map(ftdmchan, state, ftdmchan->span->state_map);
@ -354,6 +357,8 @@ end:
goto done;
}
perform_state_change:
ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_DEBUG, "Changed state from %s to %s\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state));
ftdmchan->last_state = ftdmchan->state;
ftdmchan->state = state;

View File

@ -77,9 +77,9 @@ int ft_to_sngss7_cfg_all(void)
int ret = 0;
/* check if we have done gen_config already */
if (!(g_ftdm_sngss7_data.gen_config)) {
if (g_ftdm_sngss7_data.gen_config == SNG_GEN_CFG_STATUS_INIT) {
/* update the global gen_config so we don't do it again */
g_ftdm_sngss7_data.gen_config = 1;
g_ftdm_sngss7_data.gen_config = SNG_GEN_CFG_STATUS_PENDING;
/* start of by checking if the license and sig file are valid */
if (sng_validate_license(g_ftdm_sngss7_data.cfg.license,
@ -209,13 +209,12 @@ int ft_to_sngss7_cfg_all(void)
}
} /* if (sngss7_test_flag(&g_ftdm_sngss7_data.cfg, SNGSS7_MTP2)) */
g_ftdm_sngss7_data.gen_config = 2;
g_ftdm_sngss7_data.gen_config = SNG_GEN_CFG_STATUS_DONE;
} /* if (!(g_ftdm_sngss7_data.gen_config)) */
/* FIXME: Please change number 2 to an ENUM that is more explanatory */
if (g_ftdm_sngss7_data.gen_config != 2) {
if (g_ftdm_sngss7_data.gen_config != SNG_GEN_CFG_STATUS_DONE) {
SS7_CRITICAL("General configuration FAILED!\n");
return 1;
}

View File

@ -460,7 +460,6 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
}
/**************************************************************************/
} else if (!strcasecmp(argv[c], "blo")) {
/**************************************************************************/
if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
c++;

View File

@ -252,7 +252,8 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sprintf(var, "%d", sngss7_info->circuit->cic);
sngss7_add_var(sngss7_info, "ss7_cic", var);
sprintf(var, "%d", g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].spc );
sprintf(var, "%d", g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].dpc );
sngss7_add_var(sngss7_info, "ss7_opc", var);
if (siConEvnt->callRef.callId.pres) {

View File

@ -55,6 +55,7 @@ ftdm_sngss7_data_t g_ftdm_sngss7_data;
/* PROTOTYPES *****************************************************************/
static void *ftdm_sangoma_ss7_run (ftdm_thread_t * me, void *obj);
static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event);
static void ftdm_sangoma_ss7_process_peer_stack_event (ftdm_channel_t *ftdmchan, sngss7_event_data_t *sngss7_event);
static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span);
static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span);
@ -338,9 +339,10 @@ 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[2];
ftdm_interrupt_t *ftdm_sangoma_ss7_int[3];
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;
@ -365,6 +367,12 @@ 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) {
@ -395,7 +403,7 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
}
/* check the channel state queue for an event*/
switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, 2, 100))) {
switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, ftdm_array_len(ftdm_sangoma_ss7_int), 100))) {
/**********************************************************************/
case FTDM_SUCCESS: /* process all pending state changes */
@ -412,6 +420,31 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj)
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);
@ -511,6 +544,8 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
{
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
sngss7_event_data_t *event_clone = NULL;
int clone_event = 0;
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(sngss7_event->circuit, &sngss7_info, &ftdmchan)) {
@ -524,6 +559,84 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
/* while there's a state change present on this channel process it */
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) {
clone_event++;
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
if (sngss7_event->event_id == SNGSS7_SUSP_IND_EVENT) {
sngss7_set_ckt_flag(sngss7_info, FLAG_SUS_RECVD);
sngss7_clear_ckt_flag(sngss7_info, FLAG_T6_CANCELED);
}
if (sngss7_test_ckt_flag(sngss7_info, FLAG_SUS_RECVD) &&
!sngss7_test_ckt_flag(sngss7_info, FLAG_T6_CANCELED)) {
if (sng_cancel_isup_tmr(sngss7_info->suInstId, ISUP_T6i) == RFAILED ) {
SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]could not stop timer T6 \n", sngss7_info->circuit->cic);
} else {
sngss7_set_ckt_flag(sngss7_info, FLAG_T6_CANCELED);
SS7_ERROR_CHAN(ftdmchan,"[CIC:%d] isup timer T6 has been cancelled. \n", sngss7_info->circuit->cic);
}
}
}
/* clone the event and save it for later usage, we do not clone RLC messages */
if (clone_event) {
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 (sngss7_info->peer_data) {
sngss7_span_data_t *sngss7_peer_span = (sngss7_span_data_t *)sngss7_info->peer_data->ftdmchan->span->signal_data;
/* we already have a peer attached, wake him up */
ftdm_queue_enqueue(sngss7_peer_span->peer_chans, sngss7_info->ftdmchan);
}
}
}
/* we could test for sngss7_info->peer_data too, bit this flag is set earlier, the earlier we know the better */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_NATIVE_SIGBRIDGE)) {
/* most messages are simply relayed in sig bridge mode, except for hangup which requires state changing */
switch (sngss7_event->event_id) {
case SNGSS7_REL_IND_EVENT:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case SNGSS7_REL_CFM_EVENT:
{
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);
}
}
break;
default:
break;
}
goto done;
}
/* figure out the type of event and send it to the right handler */
switch (sngss7_event->event_id) {
/**************************************************************************/
@ -576,6 +689,7 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
break;
/**************************************************************************/
case (SNGSS7_SSP_STA_CFM_EVENT):
SS7_ERROR("dazed and confused ... hu?!\n");
break;
/**************************************************************************/
default:
@ -584,6 +698,7 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
/**************************************************************************/
}
done:
/* while there's a state change present on this channel process it */
ftdm_channel_advance_states(ftdmchan);
@ -592,8 +707,337 @@ static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_ev
}
FTDM_ENUM_NAMES(SNG_EVENT_TYPE_NAMES, SNG_EVENT_TYPE_STRINGS)
FTDM_STR2ENUM(ftdm_str2sngss7_event, ftdm_sngss7_event2str, sng_event_type_t, SNG_EVENT_TYPE_NAMES, SNGSS7_INVALID_EVENT)
static void ftdm_sangoma_ss7_process_peer_stack_event (ftdm_channel_t *ftdmchan, sngss7_event_data_t *sngss7_event)
{
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
if (ftdmchan->state < FTDM_CHANNEL_STATE_UP && ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
ftdm_channel_advance_states(ftdmchan);
}
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Receiving message %s from bridged peer (our state = %s)\n",
sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id), ftdm_channel_state2str(ftdmchan->state));
switch (sngss7_event->event_id) {
case (SNGSS7_CON_IND_EVENT):
SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]Rx IAM while bridged??\n", sngss7_info->circuit->cic);
break;
case (SNGSS7_CON_CFM_EVENT):
/* send the ANM request to LibSngSS7 */
sng_cc_con_response(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&sngss7_event->event.siConEvnt,
5);
SS7_INFO_CHAN(ftdmchan, "[CIC:%d]Tx peer ANM\n", sngss7_info->circuit->cic);
break;
case (SNGSS7_CON_STA_EVENT):
switch (sngss7_event->evntType) {
/**************************************************************************/
case (ADDRCMPLT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ACM\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (MODIFY):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (MODCMPLT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY-COMPLETE\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (MODREJ):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MODIFY-REJECT\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (PROGRESS):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CPG\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (FRWDTRSFR):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer FOT\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (INFORMATION):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer INF\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (INFORMATREQ):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer INR\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (SUBSADDR):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer SAM\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (EXIT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer EXIT\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (NETRESMGT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer NRM\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (IDENTREQ):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer IDR\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (IDENTRSP):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer IRS\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (MALCLLPRNT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer MALICIOUS CALL\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (CHARGE):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (TRFFCHGE):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG-TARIFF\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (CHARGEACK):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CRG-ACK\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (CALLOFFMSG):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALL-OFFER\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (LOOPPRVNT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer LOP\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (TECT_TIMEOUT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ECT-Timeout\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (RINGSEND):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer RINGING-SEND\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (CALLCLEAR):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALL-LINE Clear\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (PRERELEASE):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer PRI\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (APPTRANSPORT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer APM\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (OPERATOR):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer OPERATOR\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (METPULSE):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer METERING-PULSE\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (CLGPTCLR):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer CALLING_PARTY_CLEAR\n", sngss7_info->circuit->cic);
break;
/**************************************************************************/
case (SUBDIRNUM):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer SUB-DIR\n", sngss7_info->circuit->cic);
break;
#ifdef SANGOMA_SPIROU
case (CHARGE_ACK):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer TXA\n", sngss7_info->circuit->cic);
break;
case (CHARGE_UNIT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer ITX\n", sngss7_info->circuit->cic);
break;
#endif
/**************************************************************************/
default:
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer Unknown Msg %d\n", sngss7_info->circuit->cic, sngss7_event->evntType);
break;
/**************************************************************************/
}
sng_cc_con_status (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&sngss7_event->event.siCnStEvnt,
sngss7_event->evntType);
break;
/**************************************************************************/
case (SNGSS7_REL_IND_EVENT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer REL cause=%d\n", sngss7_info->circuit->cic, sngss7_event->event.siRelEvnt.causeDgn.causeVal.val);
//handle_rel_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt);
sng_cc_rel_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&sngss7_event->event.siRelEvnt);
break;
/**************************************************************************/
case (SNGSS7_REL_CFM_EVENT):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer RLC\n", sngss7_info->circuit->cic);
sng_cc_rel_response (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&sngss7_event->event.siRelEvnt);
//handle_rel_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt);
break;
/**************************************************************************/
case (SNGSS7_DAT_IND_EVENT):
//handle_dat_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siInfoEvnt);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s\n", sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id));
sng_cc_dat_request(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&sngss7_event->event.siInfoEvnt);
break;
/**************************************************************************/
case (SNGSS7_FAC_IND_EVENT):
//handle_fac_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType,
//&sngss7_event->event.siFacEvnt);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s -> %d\n", sngss7_info->circuit->cic,
ftdm_sngss7_event2str(sngss7_event->event_id), sngss7_event->evntType);
sng_cc_fac_request(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
sngss7_event->evntType,
&sngss7_event->event.siFacEvnt);
break;
/**************************************************************************/
case (SNGSS7_FAC_CFM_EVENT):
//handle_fac_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit,
//sngss7_event->evntType, &sngss7_event->event.siFacEvnt);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s -> %d\n", sngss7_info->circuit->cic,
ftdm_sngss7_event2str(sngss7_event->event_id), sngss7_event->evntType);
sng_cc_fac_response(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
sngss7_event->evntType,
&sngss7_event->event.siFacEvnt);
break;
/**************************************************************************/
case (SNGSS7_UMSG_IND_EVENT):
//handle_umsg_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s\n", sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id));
sng_cc_umsg_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id);
break;
/**************************************************************************/
case (SNGSS7_STA_IND_EVENT):
//handle_sta_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->globalFlg, sngss7_event->evntType, &sngss7_event->event.siStaEvnt);
break;
/**************************************************************************/
case (SNGSS7_SUSP_IND_EVENT):
//handle_susp_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siSuspEvnt);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s\n", sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id));
sng_cc_susp_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&sngss7_event->event.siSuspEvnt);
break;
/**************************************************************************/
case (SNGSS7_RESM_IND_EVENT):
//handle_resm_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siResmEvnt);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx peer %s\n", sngss7_info->circuit->cic, ftdm_sngss7_event2str(sngss7_event->event_id));
sng_cc_resm_request(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&sngss7_event->event.siResmEvnt);
break;
/**************************************************************************/
case (SNGSS7_SSP_STA_CFM_EVENT):
SS7_CRITICAL("dazed and confused ... hu?!\n");
break;
/**************************************************************************/
default:
SS7_ERROR("Failed to relay unknown event id %d!\n", sngss7_event->event_id);
break;
/**************************************************************************/
}
if ((sngss7_event->event_id == SNGSS7_SUSP_IND_EVENT)) {
sngss7_set_ckt_flag(sngss7_info, FLAG_SUS_RECVD);
}
if (sngss7_test_ckt_flag(sngss7_info, FLAG_SUS_RECVD) &&
!sngss7_test_ckt_flag(sngss7_info, FLAG_T6_CANCELED)) {
if (sng_cancel_isup_tmr(sngss7_info->suInstId, ISUP_T6i) == RFAILED ) {
SS7_ERROR_CHAN(ftdmchan,"[CIC:%d]could not stop timer T6 \n", sngss7_info->circuit->cic);
} else {
sngss7_set_ckt_flag(sngss7_info, FLAG_T6_CANCELED);
SS7_ERROR_CHAN(ftdmchan,"[CIC:%d] isup timer T6 has been cancelled. \n", sngss7_info->circuit->cic);
}
}
}
static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t *ftdmchan);
static ftdm_status_t ftdm_sangoma_ss7_native_bridge_state_change(ftdm_channel_t *ftdmchan)
{
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
ftdm_channel_complete_state(ftdmchan);
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
{
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_flush_queue(sngss7_info->event_queue);
ftdm_channel_close (&close_chan);
}
break;
case FTDM_CHANNEL_STATE_UP:
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_UP);
}
}
break;
case FTDM_CHANNEL_STATE_TERMINATING:
{
ft_to_sngss7_rlc(ftdmchan);
/* when receiving REL we move to TERMINATING and notify the user that the bridge is ending */
sngss7_send_signal(sngss7_info, FTDM_SIGEVENT_STOP);
}
break;
default:
break;
}
return FTDM_SUCCESS;
}
/******************************************************************************/
ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
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;
@ -605,6 +1049,13 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
sngss7_info->ckt_flags,
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 */
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 */
switch (ftdmchan->state) {
@ -1058,8 +1509,22 @@ 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);
ftdm_channel_close (&close_chan);
}
@ -1653,8 +2118,10 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
/* 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;
SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, skipping channell!%s\n", " ");
/* Sig state will be down due to a block.
Right action is to hunt for another call */
goto outgoing_break;
}
/* check if there is a remote block */
@ -1679,6 +2146,14 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call)
goto outgoing_break;
}
/* This is a gracefull stack resource check.
Removing this function will cause unpredictable
ungracefule errors. */
if (sng_cc_resource_check()) {
goto outgoing_fail;
}
/* check the state of the channel */
switch (ftdmchan->state){
/**************************************************************************/
@ -1873,7 +2348,6 @@ static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t * span)
static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
{
sngss7_span_data_t *ss7_span_info;
int sngss7_retry_cnt=5;
ftdm_log (FTDM_LOG_INFO, "Configuring ftmod_sangoma_ss7 span = %s(%d)...\n",
span->name,
@ -1900,6 +2374,12 @@ 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;
@ -1923,20 +2403,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config)
/* parse the configuration and apply to the global config structure */
if (ftmod_ss7_parse_xml(ftdm_parameters, span)) {
ftdm_log (FTDM_LOG_CRIT, "Failed to parse configuration!\n");
ftdm_sleep (1000);
ftdm_sleep (100);
return FTDM_FAIL;
}
/* configure libsngss7 */
try_cfg_again:
if (ft_to_sngss7_cfg_all()) {
if (sngss7_retry_cnt--) {
ftdm_sleep (500);
ftdm_log (FTDM_LOG_DEBUG, "Failed to configure LibSngSS7 - retrying!\n");
goto try_cfg_again;
}
ftdm_log (FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n");
ftdm_sleep (1000);
ftdm_sleep (100);
return FTDM_FAIL;
}

View File

@ -56,6 +56,8 @@
#define MAX_CIC_MAP_LENGTH 1000
#define SNGSS7_EVENT_QUEUE_SIZE 100
#define SNGSS7_PEER_CHANS_QUEUE_SIZE 100
#define SNGSS7_CHAN_EVENT_QUEUE_SIZE 100
#define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */
@ -63,6 +65,14 @@
(switchtype == LSI_SW_ANS92) || \
(switchtype == LSI_SW_ANS95)
#define sngss7_flush_queue(queue) \
do { \
void *__queue_data = NULL; \
while ((__queue_data = ftdm_queue_dequeue(queue))) { \
ftdm_safe_free(__queue_data); \
} \
} while (0)
typedef struct ftdm2trillium {
uint8_t ftdm_val;
uint8_t trillium_val;
@ -81,8 +91,12 @@ typedef enum {
SNGSS7_STA_IND_EVENT,
SNGSS7_SUSP_IND_EVENT,
SNGSS7_RESM_IND_EVENT,
SNGSS7_SSP_STA_CFM_EVENT
SNGSS7_SSP_STA_CFM_EVENT,
SNGSS7_INVALID_EVENT,
} sng_event_type_t;
#define SNG_EVENT_TYPE_STRINGS "CON_IND", "CON_CFM", "CON_STA", "REL_IND", "REL_CFM", "DAT_IND", "FAC_IND", \
"FAC_CFM", "UMSG_IND", "STA_IND", "SUSP_IND", "RESM_IND", "SSP_STA_CFM", "INVALID"
FTDM_STR2ENUM_P(ftdm_str2sngss7_event, ftdm_sngss7_event2str, sng_event_type_t)
typedef enum {
SNG_BIT_A = (1 << 0),
@ -116,6 +130,12 @@ typedef enum {
SNG_CALLING = 2
} sng_addr_type_t;
typedef enum {
SNG_GEN_CFG_STATUS_INIT = 0,
SNG_GEN_CFG_STATUS_PENDING = 1,
SNG_GEN_CFG_STATUS_DONE = 2
} nsg_gen_cfg_type_t;
typedef struct sng_mtp2_error_type {
int init;
char sng_type[MAX_NAME_LEN];
@ -479,6 +499,8 @@ typedef struct sngss7_chan_data {
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;
} sngss7_chan_data_t;
#define SNGSS7_RX_GRS_PENDING (1 << 0)
@ -492,6 +514,7 @@ 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
@ -537,6 +560,8 @@ typedef enum {
FLAG_INFID_PAUSED = (1 << 15),
FLAG_SENT_ACM = (1 << 16),
FLAG_SENT_CPG = (1 << 17),
FLAG_SUS_RECVD = (1 << 18),
FLAG_T6_CANCELED = (1 << 19),
FLAG_RELAY_DOWN = (1 << 30),
FLAG_CKT_RECONFIG = (1 << 31)
} sng_ckt_flag_t;
@ -592,7 +617,7 @@ typedef enum {
FLAG_GRP_HW_UNBLK_TX = (1 << 24),
FLAG_GRP_HW_UNBLK_TX_DN = (1 << 25),
FLAG_GRP_MN_UNBLK_TX = (1 << 26),
FLAG_GRP_MN_UNBLK_TX_DN = (1 << 27)
FLAG_GRP_MN_UNBLK_TX_DN = (1 << 27),
} sng_ckt_block_flag_t;
#define BLK_FLAGS_STRING \

View File

@ -44,6 +44,7 @@
/* FUNCTIONS ******************************************************************/
void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
{
const char *var = NULL;
SiConEvnt iam;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
@ -55,9 +56,104 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
memset (&iam, 0x0, sizeof (iam));
if (sngss7_info->circuit->transparent_iam &&
var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "sigbridge_peer");
if (!ftdm_strlen_zero(var)) {
ftdm_span_t *peer_span = NULL;
ftdm_channel_t *peer_chan = NULL;
sngss7_chan_data_t *peer_info = NULL;
ftdm_get_channel_from_string(var, &peer_span, &peer_chan);
if (!peer_chan) {
SS7_ERROR_CHAN(ftdmchan, "Failed to find sigbridge peer from string '%s'\n", var);
} else {
if (peer_span->signal_type != FTDM_SIGTYPE_SS7) {
SS7_ERROR_CHAN(ftdmchan, "Peer channel '%s' has different signaling type %d'\n",
var, peer_span->signal_type);
} else {
peer_info = peer_chan->call_data;
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Starting native bridge with peer CIC %d\n",
sngss7_info->circuit->cic, peer_info->circuit->cic);
/* 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 up until release comes, note that state processing is done different and much simpler when there is a peer */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
ftdm_channel_advance_states(ftdmchan);
}
}
}
if (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 (!event_clone) {
SS7_ERROR_CHAN(ftdmchan, "No 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);
} else {
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged, dialing %s)\n", sngss7_info->circuit->cic, caller_data->dnis.digits);
/* copy original incoming IAM */
memcpy(&iam, &event_clone->event.siConEvnt, sizeof(iam));
/* Change DNIS to whatever was specified, do not change NADI or anything else! */
copy_tknStr_to_sngss7(caller_data->dnis.digits, &iam.cdPtyNum.addrSig, &iam.cdPtyNum.oddEven);
/* SPIROU certification hack
If the IAM already contain RDINF, just increment the count and set the RDNIS digits
otherwise, honor RDNIS and RDINF stuff coming from the user */
if (iam.redirInfo.eh.pres == PRSNT_NODEF) {
const char *val = NULL;
if (iam.redirInfo.redirCnt.pres) {
iam.redirInfo.redirCnt.val++;
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), redirect count incremented = %d\n", sngss7_info->circuit->cic, iam.redirInfo.redirCnt.val);
}
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_digits");
if (!ftdm_strlen_zero(val)) {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), found user supplied RDNIS digits = %s\n", sngss7_info->circuit->cic, val);
copy_tknStr_to_sngss7((char*)val, &iam.redirgNum.addrSig, &iam.redirgNum.oddEven);
} else {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), not found user supplied RDNIS digits\n", sngss7_info->circuit->cic);
}
} else {
SS7_DEBUG_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Bridged), redirect info not present, attempting to copy user supplied values\n", sngss7_info->circuit->cic);
/* Redirecting Number */
copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
/* Redirecting Information */
copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
}
}
/* 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);
/* Called Number information */
copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum);
/* Redirecting Number */
copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
/* Redirecting Information */
copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
/* Location Number information */
copy_locPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum1);
/* Forward Call Indicators */
copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd);
} else {
/* Nature of Connection Indicators */
copy_natConInd_to_sngss7(ftdmchan, &iam.natConInd);
@ -250,6 +346,7 @@ void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
/******************************************************************************/
void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
{
const char *loc_ind = NULL;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
@ -259,7 +356,15 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
rel.causeDgn.eh.pres = PRSNT_NODEF;
rel.causeDgn.location.pres = PRSNT_NODEF;
rel.causeDgn.location.val = 0x01;
loc_ind = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rel_loc");
if (!ftdm_strlen_zero(loc_ind)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied location indicator in REL, value \"%s\"\n", loc_ind);
rel.causeDgn.location.val = atoi(loc_ind);
} else {
rel.causeDgn.location.val = 0x01;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied location indicator in REL, using 0x01\"%s\"\n", "");
}
rel.causeDgn.cdeStand.pres = PRSNT_NODEF;
rel.causeDgn.cdeStand.val = 0x00;
rel.causeDgn.recommend.pres = NOTPRSNT;
@ -269,10 +374,10 @@ void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
/* send the REL request to LibSngSS7 */
sng_cc_rel_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&rel);
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&rel);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx REL cause=%d \n",
sngss7_info->circuit->cic,

View File

@ -243,15 +243,20 @@ ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *loc
{
const char *val = NULL;
const char *loc_nadi = NULL;
int pres_val = PRSNT_NODEF;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;
locPtyNum->eh.pres = PRSNT_NODEF;
locPtyNum->natAddrInd.pres = PRSNT_NODEF;
if (!strcasecmp(caller_data->loc.digits, "NULL")) {
pres_val = NOTPRSNT;
}
locPtyNum->eh.pres = pres_val;
locPtyNum->natAddrInd.pres = pres_val;
locPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].loc_nadi;
locPtyNum->scrnInd.pres = PRSNT_NODEF;
locPtyNum->scrnInd.pres = pres_val;
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_screen_ind");
if (!ftdm_strlen_zero(val)) {
locPtyNum->scrnInd.val = atoi(val);
@ -260,7 +265,7 @@ ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *loc
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Location Reference Code Screening Ind %d\n", locPtyNum->scrnInd.val);
locPtyNum->presRest.pres = PRSNT_NODEF;
locPtyNum->presRest.pres = pres_val;
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_pres_ind");
if (!ftdm_strlen_zero(val)) {
locPtyNum->presRest.val = atoi(val);
@ -269,10 +274,10 @@ ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *loc
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number Presentation Ind %d\n", locPtyNum->presRest.val);
locPtyNum->numPlan.pres = PRSNT_NODEF;
locPtyNum->numPlan.pres = pres_val;
locPtyNum->numPlan.val = 0x01;
locPtyNum->niInd.pres = PRSNT_NODEF;
locPtyNum->niInd.pres = pres_val;
locPtyNum->niInd.val = 0x00;
/* check if the user would like a custom NADI value for the Location Reference */
@ -439,6 +444,13 @@ ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *red
return FTDM_FAIL;
}
} else {
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdnis_pres_ind");
if (!ftdm_strlen_zero(val)) {
redirgNum->presRest.val = atoi(val);
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Redirecting Number Address Presentation Restricted Ind:%d\n", redirgNum->presRest.val);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Number\n");
return FTDM_SUCCESS;
}
@ -585,6 +597,7 @@ ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *r
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_indicator");
if (!ftdm_strlen_zero(val)) {
redirInfo->redirInd.val = atoi(val);
redirInfo->redirInd.pres = 1;
bProceed = 1;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Indicator\n");
@ -593,6 +606,7 @@ ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *r
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_orig");
if (!ftdm_strlen_zero(val)) {
redirInfo->origRedirReas.val = atoi(val);
redirInfo->origRedirReas.pres = 1;
bProceed = 1;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Original Reasons\n");
@ -601,6 +615,7 @@ ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *r
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_count");
if (!ftdm_strlen_zero(val)) {
redirInfo->redirCnt.val = atoi(val);
redirInfo->redirCnt.pres= 1;
bProceed = 1;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Count\n");
@ -609,6 +624,7 @@ ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *r
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_rdinfo_reason");
if (!ftdm_strlen_zero(val)) {
redirInfo->redirReas.val = atoi(val);
redirInfo->redirReas.pres = 1;
bProceed = 1;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Redirection Information on Redirection Reasons\n");
@ -749,6 +765,8 @@ ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *na
ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd)
{
const char *val = NULL;
int acc_val = ISDNACC_ISDN;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
fwdCallInd->eh.pres = PRSNT_NODEF;
@ -765,7 +783,13 @@ ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *
fwdCallInd->isdnUsrPrtPrfInd.pres = PRSNT_NODEF;
fwdCallInd->isdnUsrPrtPrfInd.val = PREF_PREFAW;
fwdCallInd->isdnAccInd.pres = PRSNT_NODEF;
fwdCallInd->isdnAccInd.val = ISDNACC_ISDN;
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "iam_fwd_ind_isdn_access_ind");
if (!ftdm_strlen_zero(val)) {
acc_val = (int)atoi(val);
}
fwdCallInd->isdnAccInd.val = acc_val;
fwdCallInd->sccpMethInd.pres = PRSNT_NODEF;
fwdCallInd->sccpMethInd.val = SCCPMTH_NOIND;

View File

@ -1923,7 +1923,7 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
SS7_DEBUG("Found transparent_iam %d\n", sng_ccSpan.transparent_iam);
#endif
} else if (!strcasecmp(parm->var, "transparent_iam_max_size")) {
sng_ccSpan.transparent_iam_max_size = ftdm_true(parm->val);
sng_ccSpan.transparent_iam_max_size = atoi(parm->val);
SS7_DEBUG("Found transparent_iam_max_size %d\n", sng_ccSpan.transparent_iam_max_size);
} else if (!strcasecmp(parm->var, "cpg_on_progress_media")) {
sng_ccSpan.cpg_on_progress_media = ftdm_true(parm->val);
@ -2925,6 +2925,9 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
/* prepare the global info sturcture */
ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t));
ss7_info->ftdmchan = NULL;
if (ftdm_queue_create(&ss7_info->event_queue, SNGSS7_CHAN_EVENT_QUEUE_SIZE) != FTDM_SUCCESS) {
SS7_CRITICAL("Failed to create ss7 cic event queue\n");
}
ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x];
g_ftdm_sngss7_data.cfg.isupCkt[x].obj = ss7_info;

View File

@ -130,6 +130,9 @@
extern "C" {
#endif
#define SPAN_PENDING_CHANS_QUEUE_SIZE 1000
#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000
#define GOTO_STATUS(label,st) status = st; goto label ;
#define ftdm_copy_string(x,y,z) strncpy(x, y, z - 1)
@ -686,6 +689,9 @@ FT_DECLARE(ftdm_status_t) ftdm_sigmsg_remove_var(ftdm_sigmsg_t *sigmsg, const ch
*/
FT_DECLARE(ftdm_status_t) ftdm_sigmsg_set_raw_data(ftdm_sigmsg_t *sigmsg, void *data, ftdm_size_t datalen);
/*! \brief Retrieve a span and channel data structure from a string in the format 'span_id:chan_id'*/
FT_DECLARE(ftdm_status_t) ftdm_get_channel_from_string(const char *string_id, ftdm_span_t **out_span, ftdm_channel_t **out_channel);
/*!
\brief Assert condition
*/

View File

@ -265,6 +265,8 @@ typedef enum {
#define FTDM_CHANNEL_BLOCKING (1ULL << 35)
/*!< Media is digital */
#define FTDM_CHANNEL_DIGITAL_MEDIA (1ULL << 36)
/*!< Native signaling bridge is enabled */
#define FTDM_CHANNEL_NATIVE_SIGBRIDGE (1ULL << 37)
#include "ftdm_state.h"