From 3ad8a33b622b1bbcd7a27c969ac13ddcb2a2dad2 Mon Sep 17 00:00:00 2001 From: Konrad Hammel Date: Mon, 25 Oct 2010 16:55:03 -0400 Subject: [PATCH] freetdm: ss7, bug fix in obci_bita handling freetdm: ss7, added support for SAM freetdm: ss7, updated support for COT in IAM --- .../ftmod_sangoma_ss7_handle.c | 106 ++++++++++++++++-- .../ftmod_sangoma_ss7_main.c | 54 ++++----- .../ftmod_sangoma_ss7_main.h | 2 + .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c | 3 +- .../ftmod_sangoma_ss7_support.c | 44 ++++++++ 5 files changed, 172 insertions(+), 37 deletions(-) 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 807b3b62c7..c4922654eb 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 @@ -216,8 +216,20 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val); ftdm_channel_add_var(ftdmchan, "ss7_cld_nadi", nadi); - /* set the state of the channel to collecting...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); + + /* check if a COT test is requested */ + if ((siConEvnt->natConInd.eh.pres) && (siConEvnt->natConInd.contChkInd.pres)) { + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Found COT Request\n", sngss7_info->circuit->cic); + + /* tell the core to loop the channel */ + ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); + + /* move to in loop state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); + } else { + /* set the state of the channel to collecting...the rest is done by the chan monitor */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); + } } /* if (channel is usable */ @@ -256,6 +268,9 @@ handle_glare: default: /* should not have gotten an IAM while in this state */ SS7_ERROR_CHAN(ftdmchan, "Got IAM on channel in invalid state(%s)...reset!\n", ftdm_channel_state2str (ftdmchan->state)); + /* reset the cic */ + sngss7_set_flag(sngss7_info, FLAG_RESET_TX); + /* move the state of the channel to RESTART to force a reset */ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); @@ -292,6 +307,7 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ /**************************************************************************/ case (ADDRCMPLT): SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ACM\n", sngss7_info->circuit->cic); + switch (ftdmchan->state) { /**********************************************************************/ case FTDM_CHANNEL_STATE_DIALING: @@ -315,14 +331,22 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } - break; + break; /**********************************************************************/ default: /* incorrect state...reset the CIC */ + SS7_ERROR_CHAN(ftdmchan, "RX ACM in invalid state :%s...resetting CIC\n", + ftdm_channel_state2str (ftdmchan->state)); + + /* reset the cic */ + sngss7_set_flag(sngss7_info, FLAG_RESET_TX); + /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - break; + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; /**********************************************************************/ } /* switch (ftdmchan->state) */ + + break; /**************************************************************************/ case (MODIFY): SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx MODIFY\n", sngss7_info->circuit->cic); @@ -354,6 +378,34 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ /**************************************************************************/ case (SUBSADDR): SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx SAM\n", sngss7_info->circuit->cic); + + /* check the channel state */ + switch (ftdmchan->state) { + /**********************************************************************/ + case (FTDM_CHANNEL_STATE_COLLECT): + + /* confirm that the event contains the subsquent number field */ + if (siCnStEvnt->subNum.eh.pres && siCnStEvnt->subNum.addrSig.pres) { + /* add the digits to the ftdm channel variable */ + append_tknStr_from_sngss7(siCnStEvnt->subNum.addrSig, + ftdmchan->caller_data.dnis.digits, + siCnStEvnt->subNum.oddEven); + } else { + SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in SAM!%s\n", " "); + } + + /* go to idle so that collect state is processed again */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + + break; + /**********************************************************************/ + default: + SS7_ERROR_CHAN(ftdmchan, "RX SAM in invalid state :%s...ignoring\n", + ftdm_channel_state2str (ftdmchan->state)); + break; + /**********************************************************************/ + } /* switch (ftdmchan->state) */ + break; /**************************************************************************/ case (EXIT): @@ -830,7 +882,7 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ break; /**************************************************************************/ case SIT_STA_CONTCHK: /* continuity check */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx COT start\n", sngss7_info->circuit->cic); + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CCR start\n", sngss7_info->circuit->cic); handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ @@ -840,7 +892,7 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ break; /**************************************************************************/ case SIT_STA_STPCONTIN: /* stop continuity */ - SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx COT stop\n", sngss7_info->circuit->cic); + SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx CCR stop\n", sngss7_info->circuit->cic); handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ @@ -1225,7 +1277,7 @@ ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t ci /* open the channel if it is not open */ if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - SS7_ERROR("Failed to open CIC %d for COT test!\n", sngss7_info->circuit->cic); + SS7_ERROR("Failed to open CIC %d for CCR test!\n", sngss7_info->circuit->cic); /* KONRAD FIX ME */ SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_FAIL; @@ -1290,6 +1342,38 @@ ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, { SS7_FUNC_TRACE_ENTER(__FUNCTION__); + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + + switch (ftdmchan->state) { + /**************************************************************************/ + case (FTDM_CHANNEL_STATE_IN_LOOP): + /* tell the core to stop looping the channel */ + ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); + + /* exit out of the LOOP state and go to collect */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); + + break; + /**************************************************************************/ + default: + /* exit out of the LOOP state to the last state */ + ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); + + break; + /**************************************************************************/ + } /* switch (ftdmchan->state) */ + if ( (siStaEvnt->contInd.eh.pres > 0) && (siStaEvnt->contInd.contInd.pres > 0)) { SS7_INFO("Continuity Test result for CIC = %d (span %d, chan %d) is: \"%s\"\n", g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, @@ -1300,13 +1384,13 @@ ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SS7_ERROR("Recieved Continuity report containing no results!\n"); } + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); return FTDM_SUCCESS; } -/******************************************************************************/ - - /******************************************************************************/ ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 587242d94e..ebb4efa311 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -79,7 +79,7 @@ ftdm_state_map_t sangoma_ss7_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_IDLE, FTDM_END}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_END} + {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_COLLECT, FTDM_END} }, { ZSD_INBOUND, @@ -100,7 +100,8 @@ ftdm_state_map_t sangoma_ss7_state_map = { ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_COLLECT, FTDM_END}, {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, - FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_RING, FTDM_END} + FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_RING, + FTDM_CHANNEL_STATE_IDLE, FTDM_END} }, { ZSD_INBOUND, @@ -526,29 +527,32 @@ void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); } else { - SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n", - i, - g_ftdm_sngss7_data.min_digits, - ftdmchan->caller_data.dnis.digits); - - /* start ISUP t35 */ - if (ftdm_sched_timer (sngss7_info->t35.sched, - "t35", - sngss7_info->t35.beat, - sngss7_info->t35.callback, - &sngss7_info->t35, - &sngss7_info->t35.hb_timer_id)) { - - SS7_ERROR ("Unable to schedule timer, hanging up call!\n"); - - ftdmchan->caller_data.hangup_cause = 41; - - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL); - - /* end the call */ - ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - } /* if (ftdm_sched_timer(sngss7_info->t35.sched, */ + /* if we are coming from idle state then we have already been here once before */ + if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) { + SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n", + i, + g_ftdm_sngss7_data.min_digits, + ftdmchan->caller_data.dnis.digits); + + /* start ISUP t35 */ + if (ftdm_sched_timer (sngss7_info->t35.sched, + "t35", + sngss7_info->t35.beat, + sngss7_info->t35.callback, + &sngss7_info->t35, + &sngss7_info->t35.hb_timer_id)) { + + SS7_ERROR ("Unable to schedule timer, hanging up call!\n"); + + ftdmchan->caller_data.hangup_cause = 41; + + /* set the flag to indicate this hangup is started from the local side */ + sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL); + + /* end the call */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + } /* if (ftdm_sched_timer(sngss7_info->t35.sched, */ + } /* if (ftdmchan->last_state != FTDM_CHANNEL_STATE_IDLE) */ } /* checking ST/#digits */ break; 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 27833cb2a2..378b50e0ad 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 @@ -581,6 +581,8 @@ uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum); uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum); uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum); uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); +uint8_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); + int check_for_state_change(ftdm_channel_t *ftdmchan); int check_cics_in_range(sngss7_chan_data_t *sngss7_info); int check_for_reset(sngss7_chan_data_t *sngss7_info); 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 8cbe6d9498..f2e34e6c2c 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 @@ -341,9 +341,10 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan) /* fill in any optional parameters */ if (sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA)) { + SS7_DEBUG_CHAN(ftdmchan, "Found ACM_OBCI_BITA flag:0x%X\n", isup_intf->options); acm.optBckCalInd.eh.pres = PRSNT_NODEF; acm.optBckCalInd.inbndInfoInd.pres = PRSNT_NODEF; - acm.optBckCalInd.inbndInfoInd.val = sngss7_test_options(isup_intf, SNGSS7_ACM_OBCI_BITA); + acm.optBckCalInd.inbndInfoInd.val = 0x1; acm.optBckCalInd.caFwdMayOcc.pres = PRSNT_DEF; acm.optBckCalInd.simpleSegmInd.pres = PRSNT_DEF; acm.optBckCalInd.mlppUserInd.pres = PRSNT_DEF; 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 718663950a..4d514caf86 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 @@ -44,6 +44,7 @@ uint32_t sngss7_id; /* PROTOTYPES *****************************************************************/ uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); +uint8_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven); uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum); uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum); uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum); @@ -343,6 +344,49 @@ uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven) return 0; } +/******************************************************************************/ +uint8_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven) +{ + int i = 0; + int j = 0; + + /* check if the token string is present */ + if (str.pres == 1) { + /* find the length of the digits so far */ + j = strlen(ftdm); + + /* confirm that we found an acceptable length */ + if ( j > 25 ) { + SS7_ERROR("string length exceeds maxium value...aborting append!\n"); + return 1; + } /* if ( j > 25 ) */ + + /* copy in digits */ + for (i = 0; i < str.len; i++) { + /* convert 4 bit integer to char and copy into lower nibblet*/ + sprintf(&ftdm[j], "%X", (str.val[i] & 0x0F)); + /* move along */ + j++; + /* convert 4 bit integer to char and copy into upper nibblet */ + sprintf(&ftdm[j], "%X", ((str.val[i] & 0xF0) >> 4)); + /* move along */ + j++; + } /* for (i = 0; i < str.len; i++) */ + + /* if the odd flag is up the last digit is a fake "0" */ + if ((oddEven.pres == 1) && (oddEven.val == 1)) { + ftdm[j-1] = '\0'; + } else { + ftdm[j] = '\0'; + } /* if ((oddEven.pres == 1) && (oddEven.val == 1)) */ + } else { + SS7_ERROR("Asked to copy tknStr that is not present!\n"); + return 1; + } /* if (str.pres == 1) */ + + return 0; +} + /******************************************************************************/ int check_for_state_change(ftdm_channel_t *ftdmchan) {