freetdm: latest SPIROU fixes in releases.3.4 branch merged in releases.3.5

This commit is contained in:
James Zhang 2012-02-24 15:43:23 -05:00
parent a46c03ef65
commit 6ed6fd2c1a
6 changed files with 227 additions and 27 deletions

View File

@ -26,6 +26,7 @@
* Anthony Minessale II <anthm@freeswitch.org>
* Moises Silva <moy@sangoma.com>
* David Yat Sin <dyatsin@sangoma.com>
* James Zhang <jzhang@sangoma.com>
*
*
* mod_freetdm.c -- FreeTDM Endpoint Module
@ -1459,6 +1460,21 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
ftdm_set_string(caller_data.loc.digits, sipvar);
}
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-LOC-Screen");
if (sipvar) {
ftdm_usrmsg_add_var(&usrmsg, "ss7_loc_screen_ind", sipvar);
}
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-LOC-Presentation");
if (sipvar) {
ftdm_usrmsg_add_var(&usrmsg, "ss7_loc_pres_ind", sipvar);
}
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) {
caller_data.dnis.type = (uint8_t)atoi(sipvar);
@ -1573,6 +1589,23 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
if (sipvar) {
ftdm_usrmsg_add_var(&usrmsg, "ss7_rdinfo_reason", sipvar);
}
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-OCN");
if (sipvar) {
ftdm_usrmsg_add_var(&usrmsg, "ss7_ocn", sipvar);
}
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-OCN-NADI");
if (sipvar) {
ftdm_usrmsg_add_var(&usrmsg, "ss7_ocn_nadi", sipvar);
}
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-OCN-Plan");
if (sipvar) {
ftdm_usrmsg_add_var(&usrmsg, "ss7_ocn_plan", sipvar);
}
sipvar = switch_channel_get_variable(channel, "sip_h_X-FreeTDM-OCN-Presentation");
if (sipvar) {
ftdm_usrmsg_add_var(&usrmsg, "ss7_ocn_pres", sipvar);
}
}
if (switch_test_flag(outbound_profile, SWITCH_CPF_SCREEN)) {
@ -1675,11 +1708,13 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi
our_chan = switch_core_session_get_channel(*new_session);
/* Figure out if there is a native bridge requested through SIP x headers */
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);
peer_chan = switch_core_session_get_channel(network_peer);
switch_set_string(tech_pvt->network_peer_uuid, network_peer_uuid);
switch_set_string(peer_private->network_peer_uuid, my_uuid);
@ -1690,6 +1725,16 @@ 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"))
&& switch_true(var)
&& switch_core_session_compare(*new_session, session)) {
private_t *peer_pvt = switch_core_session_get_private(session);
peer_chan = switch_core_session_get_channel(session);
snprintf(sigbridge_peer, sizeof(sigbridge_peer), "%u:%u",
ftdm_channel_get_span_id(peer_pvt->ftdmchan), ftdm_channel_get_id(peer_pvt->ftdmchan));
}
caller_profile = switch_caller_profile_clone(*new_session, outbound_profile);
@ -1703,21 +1748,11 @@ 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);
@ -1999,10 +2034,28 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session
}
var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_loc_nadi");
printf ( "ss7_loc_nadi = %s \n " , var_value );
if (!ftdm_strlen_zero(var_value)) {
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-LOC-NADI", "%s", var_value);
}
var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_ocn");
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);
}
var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_ocn_plan");
if (!ftdm_strlen_zero(var_value)) {
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OCN-Plan", "%s", var_value);
}
var_value = ftdm_sigmsg_get_var(sigmsg, "ss7_ocn_pres");
if (!ftdm_strlen_zero(var_value)) {
switch_channel_set_variable_printf(channel, "sip_h_X-FreeTDM-OCN-Presentation", "%s", var_value);
}
}
/* Add any call variable to the dial plan */

View File

@ -48,9 +48,26 @@ 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
sanity check, as in the past we had at least one bug where the signaling module set the state and then accidentally changed the state to a new one
without calling ftdm_channel_advance_states(), meaning the state processor for the first state was not executed and that lead to unexpected behavior.
If we want to be able to perform this kind of sanity check it would be nice to add a new state status (FTDM_STATE_STATUS_PROCESSING), the function
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",
ftdm_channel_state2str(fchan->last_state), ftdm_channel_state2str(state), diff);
}
#endif
if (fchan->state_status == FTDM_STATE_STATUS_COMPLETED) {
ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL,
"State change flag set but state is not completed\n");
ftdm_assert_return(!ftdm_test_flag(fchan, FTDM_CHANNEL_STATE_CHANGE), FTDM_FAIL, "State change flag set but state is already completed\n");
return FTDM_SUCCESS;
}

View File

@ -200,6 +200,7 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
} else {
SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in IAM!%s\n", " ");
}
copy_ocn_from_sngss7(ftdmchan, &siConEvnt->origCdNum);
copy_redirgNum_from_sngss7(ftdmchan, &siConEvnt->redirgNum);
copy_redirgInfo_from_sngss7(ftdmchan, &siConEvnt->redirInfo);
copy_genNmb_from_sngss7(ftdmchan, &siConEvnt->genNmb);

View File

@ -890,6 +890,8 @@ ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *red
ftdm_status_t copy_redirgNum_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum);
ftdm_status_t copy_redirgInfo_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo);
ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *redirInfo);
ftdm_status_t copy_ocn_to_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum);
ftdm_status_t copy_ocn_from_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum);
ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum);
ftdm_status_t copy_locPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *locPtyNum);

View File

@ -46,6 +46,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
{
const char *var = NULL;
SiConEvnt iam;
ftdm_bool_t native_going_up = FTDM_FALSE;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@ -81,9 +82,11 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
/* 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);
/* 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
and we still need those variables for further IAM processing */
native_going_up = FTDM_TRUE;
}
}
}
@ -132,6 +135,11 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
/* Redirecting Information */
copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
}
if (iam.origCdNum.eh.pres != PRSNT_NODEF) {
/* Original Called Number */
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 */
@ -154,6 +162,9 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
/* Forward Call Indicators */
copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd);
/* Original Called Number */
copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
} else {
/* Nature of Connection Indicators */
copy_natConInd_to_sngss7(ftdmchan, &iam.natConInd);
@ -190,6 +201,8 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
/* Redirecting Information */
copy_redirgInfo_to_sngss7(ftdmchan, &iam.redirInfo);
/* Original Called Number */
copy_ocn_to_sngss7(ftdmchan, &iam.origCdNum);
/* Access Transport */
copy_accTrnspt_to_sngss7(ftdmchan, &iam.accTrnspt);
@ -211,6 +224,19 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
&iam,
0);
if (native_going_up) {
/*
Note that this function (ft_to_sngss7_iam) is run within the main SS7 processing loop in
response to the DIALING state handler, we can set the state to UP here and that will
implicitly complete the DIALING state, but we *MUST* also advance the state handler
right away for a native bridge, otherwise, the processing state function (ftdm_sangoma_ss7_process_state_change)
will complete the state without having executed the handler for FTDM_CHANNEL_STATE_UP, and we won't notify
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);
}
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
@ -221,6 +247,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiCnStEvnt acm;
const char *backwardInd = NULL;
memset (&acm, 0x0, sizeof (acm));
@ -238,8 +265,17 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
acm.bckCallInd.intInd.val = INTIND_NOINTW;
acm.bckCallInd.end2EndInfoInd.pres = PRSNT_NODEF;
acm.bckCallInd.end2EndInfoInd.val = E2EINF_NOINFO;
acm.bckCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF;
acm.bckCallInd.isdnUsrPrtInd.val = ISUP_NOTUSED;
backwardInd = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "acm_bi_iup");
if (!ftdm_strlen_zero(backwardInd)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied backward indicator ISDN user part indicator ACM, value \"%s\"\n", backwardInd);
if (atoi(backwardInd) != 0 ) {
acm.bckCallInd.isdnUsrPrtInd.val = ISUP_USED;
}
}
acm.bckCallInd.holdInd.pres = PRSNT_NODEF;
acm.bckCallInd.holdInd.val = HOLD_NOTREQD;
acm.bckCallInd.isdnAccInd.pres = PRSNT_NODEF;

View File

@ -260,19 +260,19 @@ ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *loc
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);
} else {
locPtyNum->scrnInd.val = caller_data->screen;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Location Reference Code Screening Ind %d\n", locPtyNum->scrnInd.val);
locPtyNum->presRest.pres = pres_val;
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_pres_ind");
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_loc_pres_ind");
if (!ftdm_strlen_zero(val)) {
locPtyNum->presRest.val = atoi(val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Presentation Ind %d\n", locPtyNum->presRest.val);
} else {
locPtyNum->presRest.val = caller_data->pres;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Calling Party Number Presentation Ind %d\n", locPtyNum->presRest.val);
locPtyNum->numPlan.pres = pres_val;
locPtyNum->numPlan.val = 0x01;
@ -286,11 +286,10 @@ ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *loc
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Location Reference NADI value \"%s\"\n", loc_nadi);
locPtyNum->natAddrInd.val = atoi(loc_nadi);
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied NADI value found for LOC, using \"%d\"\n", locPtyNum->natAddrInd.val);
locPtyNum->natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].loc_nadi;
locPtyNum->natAddrInd.val = 0x03;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "No user supplied NADI value found for LOC, using \"%d\"\n", locPtyNum->natAddrInd.val);
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Location Reference Presentation Ind %d\n", locPtyNum->presRest.val);
return copy_tknStr_to_sngss7(caller_data->loc.digits, &locPtyNum->addrSig, &locPtyNum->oddEven);
}
@ -439,7 +438,7 @@ ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *red
return FTDM_FAIL;
}
} else if (!ftdm_strlen_zero(caller_data->rdnis.digits)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Redirection Number\"%s\"\n", val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Redirection Number\"%s\"\n", caller_data->rdnis.digits);
if (copy_tknStr_to_sngss7(caller_data->rdnis.digits, &redirgNum->addrSig, &redirgNum->oddEven) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
@ -639,6 +638,98 @@ ftdm_status_t copy_redirgInfo_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirInfo *r
return FTDM_SUCCESS;
}
ftdm_status_t copy_ocn_from_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum)
{
char val[20];
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
if (origCdNum->eh.pres != PRSNT_NODEF ) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No Original Called Number available\n");
return FTDM_SUCCESS;
}
if (origCdNum->addrSig.pres == PRSNT_NODEF) {
copy_tknStr_from_sngss7(origCdNum->addrSig, val, origCdNum->oddEven);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number digits:%s\n", val);
sngss7_add_var(sngss7_info, "ss7_ocn", val);
}
if (origCdNum->natAddr.pres == PRSNT_NODEF) {
snprintf(val, sizeof(val), "%d", origCdNum->natAddr.val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - NADI:%s\n", val);
sngss7_add_var(sngss7_info, "ss7_ocn_nadi", val);
}
if (origCdNum->numPlan.pres == PRSNT_NODEF) {
snprintf(val, sizeof(val), "%d", origCdNum->numPlan.val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number -plan:%s\n", val);
sngss7_add_var(sngss7_info, "ss7_ocn_plan", val);
}
if (origCdNum->presRest.pres == PRSNT_NODEF) {
snprintf(val, sizeof(val), "%d", origCdNum->presRest.val);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Original Called Number - presentation:%s\n", val);
sngss7_add_var(sngss7_info, "ss7_ocn_pres", val);
}
return FTDM_SUCCESS;
}
ftdm_status_t copy_ocn_to_sngss7(ftdm_channel_t *ftdmchan, SiOrigCdNum *origCdNum)
{
const char *val = NULL;
int bProceed = 0;
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn");
if (!ftdm_strlen_zero(val)) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number \"%s\"\n", val);
if (copy_tknStr_to_sngss7((char*)val, &origCdNum->addrSig, &origCdNum->oddEven) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
origCdNum->addrSig.pres = 1;
} else {
return FTDM_SUCCESS;
}
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_nadi");
if (!ftdm_strlen_zero(val)) {
origCdNum->natAddr.val = atoi(val);
origCdNum->natAddr.pres = 1;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number NADI value \"%s\"\n", val);
bProceed = 1;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Original Called Number NADI value\n");
}
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_plan");
if (!ftdm_strlen_zero(val)) {
origCdNum->numPlan.val = atoi(val);
origCdNum->numPlan.pres = 1;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number Plan value \"%s\"\n", val);
bProceed = 1;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Original Called Number Plan value\n");
}
val = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_ocn_pres");
if (!ftdm_strlen_zero(val)) {
origCdNum->presRest.val = atoi(val);
origCdNum->presRest.pres = 1;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Found user supplied Original Called Number Presentation value \"%s\"\n", val);
bProceed = 1;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "No user supplied Original Called Number Presentation value\n");
}
if( bProceed == 1 ) {
origCdNum->eh.pres = PRSNT_NODEF;
} else {
origCdNum->eh.pres = NOTPRSNT;
}
return FTDM_SUCCESS;
}
ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat)
{
ftdm_caller_data_t *caller_data = &ftdmchan->caller_data;