From 6ed6fd2c1a467a9ab9ec5138cbd6102c76e44973 Mon Sep 17 00:00:00 2001 From: James Zhang Date: Fri, 24 Feb 2012 15:43:23 -0500 Subject: [PATCH] freetdm: latest SPIROU fixes in releases.3.4 branch merged in releases.3.5 --- libs/freetdm/mod_freetdm/mod_freetdm.c | 75 ++++++++++-- libs/freetdm/src/ftdm_state.c | 21 +++- .../ftmod_sangoma_ss7_handle.c | 1 + .../ftmod_sangoma_ss7_main.h | 2 + .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c | 44 ++++++- .../ftmod_sangoma_ss7_support.c | 111 ++++++++++++++++-- 6 files changed, 227 insertions(+), 27 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 11f30019e8..699ce194e1 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -26,6 +26,7 @@ * Anthony Minessale II * Moises Silva * David Yat Sin + * James Zhang * * * 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 */ diff --git a/libs/freetdm/src/ftdm_state.c b/libs/freetdm/src/ftdm_state.c index 30ef3ce478..bd670d0062 100644 --- a/libs/freetdm/src/ftdm_state.c +++ b/libs/freetdm/src/ftdm_state.c @@ -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; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c index 2eed15e391..667dc09ba0 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -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); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index f288a78e5f..63d4ded203 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -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); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index 00d06905dd..fb91b834ec 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -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_USED; + 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; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 2088f240b6..5bd9799c8f 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -259,20 +259,20 @@ ftdm_status_t copy_locPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *loc 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); + 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; + 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); + 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; + 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;