From 05ab7e8de634f0a9da26fcc3dc730bce2b1a34a4 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 1 Sep 2010 11:21:29 -0400 Subject: [PATCH 1/7] freetdm: added proper bearer capability and user layer 1 protocol types --- libs/freetdm/src/include/freetdm.h | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index af55370338..132fd303a2 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -239,6 +239,20 @@ typedef struct { uint8_t plan; } ftdm_number_t; +/*! \brief bearer capability */ +typedef enum { + FTDM_BEARER_CAP_SPEECH = 0x00, + FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02, + FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03 +} ftdm_bearer_cap_t; + +/*! \brief user information layer 1 protocol */ +typedef enum { + FTDM_USER_LAYER1_PROT_V110 = 0x01, + FTDM_USER_LAYER1_PROT_ULAW = 0x02, + FTDM_USER_LAYER1_PROT_ALAW = 0x03, +} ftdm_user_layer1_prot_t; + /*! \brief Caller information */ typedef struct ftdm_caller_data { char cid_date[8]; /*!< Caller ID date */ @@ -256,9 +270,9 @@ typedef struct ftdm_caller_data { uint32_t raw_data_len; /* !< Raw data length */ /* these 2 are undocumented right now, only used by boost: */ /* bearer capability */ - uint8_t bearer_capability; + ftdm_bearer_cap_t bearer_capability; /* user information layer 1 protocol */ - uint8_t bearer_layer1; + ftdm_user_layer1_prot_t bearer_layer1; } ftdm_caller_data_t; /*! \brief Tone type */ From 4fc415b6e893660cca6354e12417f2924d581dc9 Mon Sep 17 00:00:00 2001 From: Konrad Hammel Date: Tue, 31 Aug 2010 17:33:42 -0400 Subject: [PATCH 2/7] freetdm: implemented Trillium stack message queueing --- libs/freetdm/Makefile.am | 25 +- .../ftmod_sangoma_ss7_handle.c | 1930 +++++++++++++++++ .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c | 1906 ++-------------- .../ftmod_sangoma_ss7_main.c | 169 +- .../ftmod_sangoma_ss7_main.h | 75 +- 5 files changed, 2341 insertions(+), 1764 deletions(-) create mode 100644 libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index 6ccc473ce3..33a8b96936 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -268,18 +268,19 @@ ftmod_pritap_la_LIBADD = $(MYLIB) endif if SNGSS7 -ftmod_sangoma_ss7_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c +ftmod_sangoma_ss7_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c ftmod_sangoma_ss7_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE ftmod_sangoma_ss7_la_LDFLAGS = -module -avoid-version -lsng_ss7 ftmod_sangoma_ss7_la_LIBADD = $(MYLIB) 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 new file mode 100644 index 0000000000..d1f3a8b89c --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -0,0 +1,1930 @@ +/* + * Copyright (c) 2009 Konrad Hammel + * All rights reserved. + * + * Redistribution and use in source and binary forms|with or without + * modification|are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice|this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice|this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT + * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, + * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* INCLUDE ********************************************************************/ +#include "ftmod_sangoma_ss7_main.h" +/******************************************************************************/ + +/* DEFINES ********************************************************************/ +/******************************************************************************/ + +/* GLOBALS ********************************************************************/ +/******************************************************************************/ + +/* PROTOTYPES *****************************************************************/ +/* PROTOTYPES *****************************************************************/ +ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); +ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); +ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); +ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); +ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); +ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt); +ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); +ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); +ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); +ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); + +ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +/******************************************************************************/ + +/* FUNCTIONS ******************************************************************/ +ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n"); + + /* check if the circuit has a remote block */ + if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { + + /* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */ + sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + sngss7_clear_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); + sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); + + /* KONRAD FIX ME : check in case there is a ckt and grp block */ + } + + /* check whether the ftdm channel is in a state to accept a call */ + switch (ftdmchan->state) { + /**************************************************************************/ + case (FTDM_CHANNEL_STATE_DOWN): /* only state it is fully valid to get IAM */ + + /* fill in the channels SS7 Stack information */ + sngss7_info->suInstId = get_unique_id(); + sngss7_info->spInstId = spInstId; + + /* try to open the ftdm channel */ + if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { + SS7_ERROR("Failed to open span: %d, chan: %d\n", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id); + + /* set the flag to indicate this hangup is started from the local side */ + sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL); + + ftdmchan->caller_data.hangup_cause = 41; + + /* move the state to CANCEL */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + + } else { + + /* fill in cid/ani number */ + if (siConEvnt->cgPtyNum.addrSig.pres) { + copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig, + ftdmchan->caller_data.cid_num.digits, + siConEvnt->cgPtyNum.oddEven); + + /* fill in cid Name */ + ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits); + + ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits); + + } else { + SS7_INFO("No Calling party (ANI) information in IAM!\n"); + } + + /* fill in dnis */ + if (siConEvnt->cdPtyNum.addrSig.pres) { + copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, + ftdmchan->caller_data.dnis.digits, + siConEvnt->cdPtyNum.oddEven); + } else { + SS7_INFO("No Called party (DNIS) information in IAM!\n"); + } + + /* fill in rdnis */ + if (siConEvnt->redirgNum.addrSig.pres) { + copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig, + ftdmchan->caller_data.rdnis.digits, + siConEvnt->cgPtyNum.oddEven); + } else { + SS7_INFO("No RDNIS party information in IAM!\n"); + } + + /* fill in screening/presentation */ + ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val; + ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val; + + /* 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 (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) */ + + break; + /**************************************************************************/ + default: /* should not have gotten an IAM while in this state */ + SS7_ERROR("Got IAM in an invalid state (%s) on span=%d, chan=%d!\n", + ftdm_channel_state2str(ftdmchan->state), + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id); + + /* move the state of the channel to RESTART to force a reset */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + + break; + /**************************************************************************/ + } /* switch (ftdmchan->state) */ + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + } + + switch (evntType) { + /**************************************************************************/ + case (ADDRCMPLT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ACM\n"); + switch (ftdmchan->state) { + /**********************************************************************/ + case FTDM_CHANNEL_STATE_DIALING: + /* KONRAD: should we confirm the instance ids ? */ + + /* need to grab the sp instance id */ + sngss7_info->spInstId = spInstId; + + /* go to PROGRESS */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); + break; + /**********************************************************************/ + default: /* incorrect state...reset the CIC */ + /* go to RESTART */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); + break; + /**********************************************************************/ + } /* switch (ftdmchan->state) */ + /**************************************************************************/ + case (MODIFY): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY\n"); + break; + /**************************************************************************/ + case (MODCMPLT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY-COMPLETE\n"); + break; + /**************************************************************************/ + case (MODREJ): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY-REJECT\n"); + break; + /**************************************************************************/ + case (PROGRESS): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CPG\n"); + break; + /**************************************************************************/ + case (FRWDTRSFR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FOT\n"); + break; + /**************************************************************************/ + case (INFORMATION): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx INF\n"); + break; + /**************************************************************************/ + case (INFORMATREQ): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx INR\n"); + break; + /**************************************************************************/ + case (SUBSADDR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SAM\n"); + break; + /**************************************************************************/ + case (EXIT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx EXIT\n"); + break; + /**************************************************************************/ + case (NETRESMGT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx NRM\n"); + break; + /**************************************************************************/ + case (IDENTREQ): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IDR\n"); + break; + /**************************************************************************/ + case (IDENTRSP): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IRS\n"); + break; + /**************************************************************************/ + case (MALCLLPRNT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MALICIOUS CALL\n"); + break; + /**************************************************************************/ + case (CHARGE): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG\n"); + break; + /**************************************************************************/ + case (TRFFCHGE): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG-TARIFF\n"); + break; + /**************************************************************************/ + case (CHARGEACK): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG-ACK\n"); + break; + /**************************************************************************/ + case (CALLOFFMSG): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALL-OFFER\n"); + break; + /**************************************************************************/ + case (LOOPPRVNT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LOP\n"); + break; + /**************************************************************************/ + case (TECT_TIMEOUT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ECT-Timeout\n"); + break; + /**************************************************************************/ + case (RINGSEND): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RINGING-SEND\n"); + break; + /**************************************************************************/ + case (CALLCLEAR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALL-LINE Clear\n"); + break; + /**************************************************************************/ + case (PRERELEASE): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx PRI\n"); + break; + /**************************************************************************/ + case (APPTRANSPORT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx APM\n"); + break; + /**************************************************************************/ + case (OPERATOR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx OPERATOR\n"); + break; + /**************************************************************************/ + case (METPULSE): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx METERING-PULSE\n"); + break; + /**************************************************************************/ + case (CLGPTCLR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALLING_PARTY_CLEAR\n"); + break; + /**************************************************************************/ + case (SUBDIRNUM): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SUB-DIR\n"); + break; + /**************************************************************************/ + default: + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Unknown Msg\n"); + break; + /**************************************************************************/ + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + + /* check whether the ftdm channel is in a state to accept a call */ + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_PROGRESS: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ANM\n"); + + /* go to UP */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DIALING: + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CON\n"); + + /* go to UP */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + + break; + /**************************************************************************/ + default: /* incorrect state...reset the CIC */ + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ANM/CON\n"); + + /* throw the TX reset flag */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); + + /* go to RESTART */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + + break; + /**************************************************************************/ + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx REL\n"); + + /* check whether the ftdm channel is in a state to release a call */ + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DIALING: + + /* pass the release code up to FTDM */ + if (siRelEvnt->causeDgn.causeVal.pres) { + ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; + } else { + SS7_ERROR("REL does not have a cause code!\n"); + ftdmchan->caller_data.hangup_cause = 0; + } + + /* this is a remote hangup request */ + sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + + /* move the state of the channel to CANCEL to end the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RING: + case FTDM_CHANNEL_STATE_PROGRESS: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: + case FTDM_CHANNEL_STATE_UP: + + /* pass the release code up to FTDM */ + if (siRelEvnt->causeDgn.causeVal.pres) { + ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; + } else { + SS7_ERROR("REL does not have a cause code!\n"); + ftdmchan->caller_data.hangup_cause = 0; + } + + /* this is a remote hangup request */ + sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + + /* move the state of the channel to TERMINATING to end the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + + break; + /**************************************************************************/ + default: + + /* fill in the channels SS7 Stack information */ + sngss7_info->suInstId = get_unique_id(); + sngss7_info->spInstId = spInstId; + + /* throw the reset flag */ + sngss7_set_flag(sngss7_info, FLAG_RESET_RX); + + /* set the state to RESTART */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } /* switch (ftdmchan->state) */ + + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RLC\n"); + + /* check whether the ftdm channel is in a state to accept a call */ + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + + /* go to DOWN */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: + /* do nothing, just drop the message */ + break; + /**************************************************************************/ + default: + /* KONRAD: should just stop the call...but a reset is easier for now (since it does hangup the call) */ + + /* go to RESTART */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + + break; + /**************************************************************************/ + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx DATA IND\n"); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FAC\n"); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FAC-CON\n"); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx USER-USER msg\n"); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* 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; + } + + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + switch (evntType) { + /**************************************************************************/ + case SIT_STA_REATTEMPT: /* reattempt indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Reattempt indication\n"); + handle_reattempt(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_ERRORIND: /* error indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Error indication\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CONTCHK: /* continuity check */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT start\n"); + handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CONTREP: /* continuity report */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT report\n"); + handle_cot(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_STPCONTIN: /* stop continuity */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT stop\n"); + handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CGQRYRSP: /* circuit grp query response from far end forwarded to upper layer by ISUP */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CQM\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CONFUSION: /* confusion */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CFN\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LOOPBACKACK: /* loop-back acknowledge */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LPA\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRRSRVREQ: /* circuit reservation request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Ckt Resveration req\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRRSRVACK: /* circuit reservation acknowledgement */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Ckt Res ack\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRBLOREQ: /* circuit blocking request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx BLO\n"); + handle_blo_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRBLORSP: /* circuit blocking response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx BLA\n"); + handle_blo_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRUBLREQ: /* circuit unblocking request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UBL\n"); + handle_ubl_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRUBLRSP: /* circuit unblocking response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UBA\n"); + handle_ubl_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRRESREQ: /* circuit reset request - RSC */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RSC\n"); + handle_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRLOCRES: /* reset initiated locally by the software */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local RSC\n"); + handle_local_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRRESRSP: /* circuit reset response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RSC-RLC\n"); + handle_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CGBREQ: /* CGB request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGUREQ: /* CGU request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGU\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGQRYREQ: /* circuit group query request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CQM\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGBRSP: /* mntc. oriented CGB response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGB\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGURSP: /* mntc. oriented CGU response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGU\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_GRSREQ: /* circuit group reset request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx GRS\n"); + handle_grs_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRUNEQPD: /* circuit unequipped indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UCIC\n"); + handle_ucic(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_GRSRSP: /* circuit group reset response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx GRA\n"); + handle_grs_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_PAUSEIND: /* pause indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SUS\n"); + handle_pause(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_RESUMEIND: /* resume indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RES\n"); + handle_resume(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_USRPARTA: /* user part available */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UPA\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_RMTUSRUNAV: /* remote user not available */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Remote User not Available\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPCONG0: /* congestion indication level 0 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L0\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPCONG1: /* congestion indication level 1 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L1\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPCONG2: /* congestion indication level 2 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L2\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPCONG3: /* congestion indication level 3 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L3\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPSTPCONG: /* stop congestion indication level 0 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Stop Congestion\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRLOCALBLOIND: /* Mngmt local blocking */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local BLO\n"); + handle_local_blk(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRLOCALUBLIND: /* Mngmt local unblocking */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local UBL\n"); + handle_local_ubl(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_OVERLOAD: /* Overload */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Overload\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LMCGBREQ: /* when LM requests ckt grp blocking */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CGB\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LMCGUREQ: /* when LM requests ckt grp unblocking */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CGU\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LMGRSREQ: /* when LM requests ckt grp reset */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM RSC\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CQM\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRLOCGRS: /* group reset initiated locally by the software */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local GRS\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + default: + SS7_INFO("[SNG-CC] Received Unknown indication %d\n", evntType); + break; + } /* switch (evntType) */ + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; + +} + +/******************************************************************************/ +ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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 ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* glare, throw the flag, go to down state*/ + sngss7_set_flag(sngss7_info, FLAG_GLARE); + + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + int infId; + int i; + + /* extract the affect infId from the circuit structure */ + infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; + + /* go through all the circuits now and find any other circuits on this infId */ + i = 1; + while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) { + + /* check that the infId matches and that this is not a siglink */ + if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && + (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) { + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + i++; + continue; + } + + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + i++; + SS7_ASSERT; + }; + + /* check if the circuit is fully started */ + if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_IN_THREAD)) { + /* set the pause flag on the channel */ + sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED); + + /* set the statet o SUSPENDED to bring the sig status down */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */ + + /* move to the next circuit */ + i++; + + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */ + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + int infId; + int i; + + /* extract the affect infId from the circuit structure */ + infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; + + /* go through all the circuits now and find any other circuits on this infId */ + i = 1; + while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) { + + /* check that the infId matches and that this is not a siglink */ + if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && + (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) { + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + i++; + continue; + } + + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + i++; + SS7_ASSERT; + }; + + /* only resume if we are paused */ + if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { + /* set the resume flag on the channel */ + sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME); + + /* clear the paused flag */ + sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED); + + /* set the statet to SUSPENDED to bring the sig status up */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */ + + /* move to the next circuit */ + i++; + + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */ + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* 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); + /* KONRAD FIX ME */ + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + } + + /* tell the core to loop the channel */ + ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); + + /* switch to the IN_LOOP state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); + + /* store the sngss7 ids */ + if (suInstId == 0) { + sngss7_info->suInstId = get_unique_id(); + } else { + sngss7_info->suInstId = suInstId; + } + sngss7_info->spInstId = spInstId; + sngss7_info->globalFlg = globalFlg; + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* tell the core to stop looping the channel */ + ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); + + /* exit out of the LOOP state to the last state */ + ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + 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, + g_ftdm_sngss7_data.cfg.isupCkt[circuit].span, + g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan, + (siStaEvnt->contInd.contInd.val) ? "PASS" : "FAIL"); + } else { + SS7_ERROR("Recieved Continuity report containing no results!\n"); + } + + 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) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* check if the circuit is already blocked or not */ + if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { + SS7_WARN("Received BLO on circuit that is already blocked!\n"); + } + + /* throw the ckt block flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* 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_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* KONRAD FIX ME */ + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* check if the channel is blocked */ + if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) { + SS7_WARN("Received UBL on circuit that is not blocked!\n"); + } + + /* throw the unblock flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); + + /* clear the block flag */ + sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* KONRAD FIX ME */ + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* throw the reset flag */ + sngss7_set_flag(sngss7_info, FLAG_RESET_RX); + + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* go to idle so that we can redo the restart state*/ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + + break; + /**************************************************************************/ + default: + + /* set the state of the channel to restart...the rest is done by the chan monitor */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* throw the reset flag */ + sngss7_set_flag(sngss7_info, FLAG_RESET_RX); + + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* go to idle so that we can redo the restart state*/ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + + break; + /**************************************************************************/ + default: + + /* set the state of the channel to restart...the rest is done by the chan monitor */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + switch (ftdmchan->state) { + /**********************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + if ( sngss7_test_flag(sngss7_info, FLAG_RESET_TX) ) { + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP); + + /* go to DOWN */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + } else { + SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #, dropping\n", sngss7_info->circuit->cic); + } + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: + + /* do nothing, just drop the message */ + SS7_DEBUG("Receveived RSC-RLC in down state, dropping\n"); + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_TERMINATING: + case FTDM_CHANNEL_STATE_HANGUP: + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP); + + /* go to DOWN */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + break; + /**********************************************************************/ + default: + /* ITU Q764-2.9.5.1.c -> release the circuit */ + if ((siStaEvnt != NULL) && + (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && + (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { + ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val; + } else { + ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ + } + + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + break; + /**********************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} +/******************************************************************************/ +ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_span_data_t *span = NULL; + int range; + int x; + + 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; + } + + /* extract the range value from the event structure */ + if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { + range = siStaEvnt->rangStat.range.val; + } else { + SS7_ERROR("Received GRS with no range value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* loop over the cics starting from circuit until range+1 */ + for (x = circuit; x < (circuit + range + 1); x++) { + /* grab the circuit in question */ + if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x); + break; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_ASSERT; + }; + + /* fill in the span structure for this circuit */ + span = ftdmchan->span->mod_data; + span->grs.circuit = circuit; + span->grs.range = range; + + SS7_DEBUG_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); + + /* flag the channel as having received a reset */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX); + + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* go to idle so that we can redo the restart state*/ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + + break; + /**************************************************************************/ + default: + + /* set the state of the channel to restart...the rest is done by the chan monitor */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + int range; + int x; + + /* extract the range value from the event structure */ + if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { + range = siStaEvnt->rangStat.range.val; + } else { + SS7_ERROR("Received GRA with no range value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* go through all the circuits in the range */ + for ( x = circuit; x < (circuit + range + 1); x++) { + + /* grab the circuit in question */ + if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + break; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_ASSERT; + }; + + SS7_DEBUG_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); + + switch (ftdmchan->state) { + /**********************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); + + /* go to DOWN */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: + + /* do nothing, just drop the message */ + SS7_DEBUG("Receveived GRA in down state, dropping\n"); + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_TERMINATING: + case FTDM_CHANNEL_STATE_HANGUP: + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); + + break; + /**********************************************************************/ + default: + /* ITU Q764-2.9.5.1.c -> release the circuit */ + if ((siStaEvnt != NULL) && + (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && + (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { + ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val; + } else { + ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ + } + + /* go to terminating to hang up the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + break; + /**********************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* for (( x = 0; x < (circuit + range); x++) */ + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* check if the circuit is already blocked or not */ + if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { + SS7_WARN("Received local BLO on circuit that is already blocked!\n"); + } + + /* throw the ckt block flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* check if the circuit is already blocked or not */ + if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { + SS7_WARN("Received local UBL on circuit that is already unblocked!\n"); + } + + /* throw the ckt block flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + 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; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* throw the ckt block flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + + +/******************************************************************************/ +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c index 98554db6a4..34893cf5aa 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c @@ -53,31 +53,6 @@ void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); -static ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - /******************************************************************************/ /* FUNCTIONS ******************************************************************/ @@ -85,8 +60,9 @@ void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCo { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -95,119 +71,26 @@ void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCo return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n"); - - /* check if the circuit has a remote block */ - if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || - (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || - (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { - - /* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */ - sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - sngss7_clear_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); - sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); - - /* KONRAD FIX ME : check in case there is a ckt and grp block */ + return; } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case (FTDM_CHANNEL_STATE_DOWN): /* only state it is fully valid to get IAM */ + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_CON_IND_EVENT; + memcpy(&sngss7_event->event.siConEvnt, siConEvnt, sizeof(*siConEvnt)); - /* fill in the channels SS7 Stack information */ - sngss7_info->suInstId = get_unique_id(); - sngss7_info->spInstId = spInstId; - - /* try to open the ftdm channel */ - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - SS7_ERROR("Failed to open span: %d, chan: %d\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); - - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL); - - ftdmchan->caller_data.hangup_cause = 41; - - /* move the state to CANCEL */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - - } else { - - /* fill in cid/ani number */ - if (siConEvnt->cgPtyNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig, - ftdmchan->caller_data.cid_num.digits, - siConEvnt->cgPtyNum.oddEven); - - /* fill in cid Name */ - ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits); - - ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits); - - } else { - SS7_INFO("No Calling party (ANI) information in IAM!\n"); - } - - /* fill in dnis */ - if (siConEvnt->cdPtyNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, - ftdmchan->caller_data.dnis.digits, - siConEvnt->cdPtyNum.oddEven); - } else { - SS7_INFO("No Called party (DNIS) information in IAM!\n"); - } - - /* fill in rdnis */ - if (siConEvnt->redirgNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig, - ftdmchan->caller_data.rdnis.digits, - siConEvnt->cgPtyNum.oddEven); - } else { - SS7_INFO("No RDNIS party information in IAM!\n"); - } - - /* fill in screening/presentation */ - ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val; - ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val; - - /* 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 (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) */ - - break; - /**************************************************************************/ - default: /* should not have gotten an IAM while in this state */ - SS7_ERROR("Got IAM in an invalid state (%s) on span=%d, chan=%d!\n", - ftdm_channel_state2str(ftdmchan->state), - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); - - /* move the state of the channel to RESTART to force a reset */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) */ - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } /******************************************************************************/ @@ -215,8 +98,9 @@ void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCo { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -225,59 +109,26 @@ void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCo return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ANM\n"); - - /* go to UP */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CON\n"); - - /* go to UP */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - - break; - /**************************************************************************/ - default: /* incorrect state...reset the CIC */ - - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ANM/CON\n"); - - /* throw the TX reset flag */ - sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); - - /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - break; - /**************************************************************************/ + return; } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_CON_CFM_EVENT; + memcpy(&sngss7_event->event.siConEvnt, siConEvnt, sizeof(*siConEvnt)); + + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } /******************************************************************************/ @@ -285,8 +136,9 @@ void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCn { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -295,159 +147,27 @@ void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCn return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; + return; } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - switch (evntType) { - /**************************************************************************/ - case (ADDRCMPLT): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ACM\n"); - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - /* KONRAD: should we confirm the instance ids ? */ + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->evntType = evntType; + sngss7_event->event_id = SNGSS7_CON_STA_EVENT; + memcpy(&sngss7_event->event.siCnStEvnt, siCnStEvnt, sizeof(*siCnStEvnt)); - /* need to grab the sp instance id */ - sngss7_info->spInstId = spInstId; - - /* go to PROGRESS */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - break; - /**********************************************************************/ - default: /* incorrect state...reset the CIC */ - /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - break; - /**********************************************************************/ - } /* switch (ftdmchan->state) */ - /**************************************************************************/ - case (MODIFY): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY\n"); - break; - /**************************************************************************/ - case (MODCMPLT): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY-COMPLETE\n"); - break; - /**************************************************************************/ - case (MODREJ): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY-REJECT\n"); - break; - /**************************************************************************/ - case (PROGRESS): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CPG\n"); - break; - /**************************************************************************/ - case (FRWDTRSFR): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FOT\n"); - break; - /**************************************************************************/ - case (INFORMATION): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx INF\n"); - break; - /**************************************************************************/ - case (INFORMATREQ): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx INR\n"); - break; - /**************************************************************************/ - case (SUBSADDR): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SAM\n"); - break; - /**************************************************************************/ - case (EXIT): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx EXIT\n"); - break; - /**************************************************************************/ - case (NETRESMGT): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx NRM\n"); - break; - /**************************************************************************/ - case (IDENTREQ): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IDR\n"); - break; - /**************************************************************************/ - case (IDENTRSP): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IRS\n"); - break; - /**************************************************************************/ - case (MALCLLPRNT): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MALICIOUS CALL\n"); - break; - /**************************************************************************/ - case (CHARGE): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG\n"); - break; - /**************************************************************************/ - case (TRFFCHGE): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG-TARIFF\n"); - break; - /**************************************************************************/ - case (CHARGEACK): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG-ACK\n"); - break; - /**************************************************************************/ - case (CALLOFFMSG): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALL-OFFER\n"); - break; - /**************************************************************************/ - case (LOOPPRVNT): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LOP\n"); - break; - /**************************************************************************/ - case (TECT_TIMEOUT): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ECT-Timeout\n"); - break; - /**************************************************************************/ - case (RINGSEND): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RINGING-SEND\n"); - break; - /**************************************************************************/ - case (CALLCLEAR): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALL-LINE Clear\n"); - break; - /**************************************************************************/ - case (PRERELEASE): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx PRI\n"); - break; - /**************************************************************************/ - case (APPTRANSPORT): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx APM\n"); - break; - /**************************************************************************/ - case (OPERATOR): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx OPERATOR\n"); - break; - /**************************************************************************/ - case (METPULSE): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx METERING-PULSE\n"); - break; - /**************************************************************************/ - case (CLGPTCLR): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALLING_PARTY_CLEAR\n"); - break; - /**************************************************************************/ - case (SUBDIRNUM): - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SUB-DIR\n"); - break; - /**************************************************************************/ - default: - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Unknown Msg\n"); - break; - /**************************************************************************/ - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } /******************************************************************************/ @@ -455,8 +175,9 @@ void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRe { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -465,92 +186,36 @@ void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRe return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx REL\n"); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_REL_IND_EVENT; + memcpy(&sngss7_event->event.siRelEvnt, siRelEvnt, sizeof(*siRelEvnt)); - /* check whether the ftdm channel is in a state to release a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - - /* pass the release code up to FTDM */ - if (siRelEvnt->causeDgn.causeVal.pres) { - ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; - } else { - SS7_ERROR("REL does not have a cause code!\n"); - ftdmchan->caller_data.hangup_cause = 0; - } - - /* this is a remote hangup request */ - sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); - - /* move the state of the channel to CANCEL to end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RING: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: - - /* pass the release code up to FTDM */ - if (siRelEvnt->causeDgn.causeVal.pres) { - ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; - } else { - SS7_ERROR("REL does not have a cause code!\n"); - ftdmchan->caller_data.hangup_cause = 0; - } - - /* this is a remote hangup request */ - sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); - - /* move the state of the channel to TERMINATING to end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - - break; - /**************************************************************************/ - default: - - /* fill in the channels SS7 Stack information */ - sngss7_info->suInstId = get_unique_id(); - sngss7_info->spInstId = spInstId; - - /* throw the reset flag */ - sngss7_set_flag(sngss7_info, FLAG_RESET_RX); - - /* set the state to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) */ - - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } - /******************************************************************************/ void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -559,57 +224,36 @@ void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRe return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RLC\n"); - - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - /* do nothing, just drop the message */ - break; - /**************************************************************************/ - default: - /* KONRAD: should just stop the call...but a reset is easier for now (since it does hangup the call) */ - - /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - break; - /**************************************************************************/ + return; } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_REL_CFM_EVENT; + memcpy(&sngss7_event->event.siRelEvnt, siRelEvnt, sizeof(*siRelEvnt)); + + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } /******************************************************************************/ void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt) { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -618,33 +262,36 @@ void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiIn return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx DATA IND\n"); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_DAT_IND_EVENT; + memcpy(&sngss7_event->event.siInfoEvnt, siInfoEvnt, sizeof(*siInfoEvnt)); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } /******************************************************************************/ void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -653,33 +300,37 @@ void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FAC\n"); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->evntType = evntType; + sngss7_event->event_id = SNGSS7_FAC_IND_EVENT; + memcpy(&sngss7_event->event.siFacEvnt, siFacEvnt, sizeof(*siFacEvnt)); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } /******************************************************************************/ void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -688,33 +339,37 @@ void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FAC-CON\n"); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->evntType = evntType; + sngss7_event->event_id = SNGSS7_FAC_CFM_EVENT; + memcpy(&sngss7_event->event.siFacEvnt, siFacEvnt, sizeof(*siFacEvnt)); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } /******************************************************************************/ void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit) { SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -723,31 +378,35 @@ void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit) return; } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx USER-USER msg\n"); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_UMSG_IND_EVENT; - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; -} +} /* GENERAL STATUS *************************************************************/ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) { - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -756,1209 +415,32 @@ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint return; } - SS7_FUNC_TRACE_ENTER(__FUNCTION__); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - switch (evntType) { - /**************************************************************************/ - case SIT_STA_REATTEMPT: /* reattempt indication */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Reattempt indication\n"); - handle_reattempt(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_ERRORIND: /* error indication */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Error indication\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CONTCHK: /* continuity check */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT start\n"); - handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CONTREP: /* continuity report */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT report\n"); - handle_cot(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_STPCONTIN: /* stop continuity */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT stop\n"); - handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CGQRYRSP: /* circuit grp query response from far end forwarded to upper layer by ISUP */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CQM\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CONFUSION: /* confusion */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CFN\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LOOPBACKACK: /* loop-back acknowledge */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LPA\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRRSRVREQ: /* circuit reservation request */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Ckt Resveration req\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRRSRVACK: /* circuit reservation acknowledgement */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Ckt Res ack\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRBLOREQ: /* circuit blocking request */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx BLO\n"); - handle_blo_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRBLORSP: /* circuit blocking response */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx BLA\n"); - handle_blo_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUBLREQ: /* circuit unblocking request */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UBL\n"); - handle_ubl_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUBLRSP: /* circuit unblocking response */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UBA\n"); - handle_ubl_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRRESREQ: /* circuit reset request - RSC */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RSC\n"); - handle_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCRES: /* reset initiated locally by the software */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local RSC\n"); - handle_local_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRRESRSP: /* circuit reset response */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RSC-RLC\n"); - handle_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CGBREQ: /* CGB request */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGUREQ: /* CGU request */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGU\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGQRYREQ: /* circuit group query request */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CQM\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGBRSP: /* mntc. oriented CGB response */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGB\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGURSP: /* mntc. oriented CGU response */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGU\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_GRSREQ: /* circuit group reset request */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx GRS\n"); - handle_grs_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUNEQPD: /* circuit unequipped indication */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UCIC\n"); - handle_ucic(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_GRSRSP: /* circuit group reset response */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx GRA\n"); - handle_grs_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_PAUSEIND: /* pause indication */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SUS\n"); - handle_pause(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_RESUMEIND: /* resume indication */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RES\n"); - handle_resume(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_USRPARTA: /* user part available */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UPA\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_RMTUSRUNAV: /* remote user not available */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Remote User not Available\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG0: /* congestion indication level 0 */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L0\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG1: /* congestion indication level 1 */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L1\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG2: /* congestion indication level 2 */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L2\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG3: /* congestion indication level 3 */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L3\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPSTPCONG: /* stop congestion indication level 0 */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Stop Congestion\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCALBLOIND: /* Mngmt local blocking */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local BLO\n"); - handle_local_blk(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCALUBLIND: /* Mngmt local unblocking */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local UBL\n"); - handle_local_ubl(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_OVERLOAD: /* Overload */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Overload\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMCGBREQ: /* when LM requests ckt grp blocking */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CGB\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMCGUREQ: /* when LM requests ckt grp unblocking */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CGU\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMGRSREQ: /* when LM requests ckt grp reset */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM RSC\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CQM\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCGRS: /* group reset initiated locally by the software */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local GRS\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - default: - SS7_INFO("[SNG-CC] Received Unknown indication %d\n", evntType); - break; - } /* switch (evntType) */ + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->globalFlg = globalFlg; + sngss7_event->evntType = evntType; + sngss7_event->event_id = SNGSS7_STA_IND_EVENT; + if (siStaEvnt != NULL) { + memcpy(&sngss7_event->event.siStaEvnt, siStaEvnt, sizeof(*siStaEvnt)); + } + + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } -/******************************************************************************/ -static ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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 ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* glare, throw the flag, go to down state*/ - sngss7_set_flag(sngss7_info, FLAG_GLARE); - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int infId; - int i; - - /* extract the affect infId from the circuit structure */ - infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; - - /* go through all the circuits now and find any other circuits on this infId */ - i = 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) { - - /* check that the infId matches and that this is not a siglink */ - if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && - (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) { - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - i++; - continue; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - i++; - SS7_ASSERT; - }; - - /* check if the circuit is fully started */ - if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_IN_THREAD)) { - /* set the pause flag on the channel */ - sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED); - - /* set the statet o SUSPENDED to bring the sig status down */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */ - - /* move to the next circuit */ - i++; - - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */ - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int infId; - int i; - - /* extract the affect infId from the circuit structure */ - infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; - - /* go through all the circuits now and find any other circuits on this infId */ - i = 1; - while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) { - - /* check that the infId matches and that this is not a siglink */ - if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && - (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) { - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - i++; - continue; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - i++; - SS7_ASSERT; - }; - - /* only resume if we are paused */ - if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { - /* set the resume flag on the channel */ - sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME); - - /* clear the paused flag */ - sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED); - - /* set the statet to SUSPENDED to bring the sig status up */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */ - - /* move to the next circuit */ - i++; - - } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */ - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* 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); - /* KONRAD FIX ME */ - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - } - - /* tell the core to loop the channel */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); - - /* switch to the IN_LOOP state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); - - /* store the sngss7 ids */ - if (suInstId == 0) { - sngss7_info->suInstId = get_unique_id(); - } else { - sngss7_info->suInstId = suInstId; - } - sngss7_info->spInstId = spInstId; - sngss7_info->globalFlg = globalFlg; - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* tell the core to stop looping the channel */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); - - /* exit out of the LOOP state to the last state */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - 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, - g_ftdm_sngss7_data.cfg.isupCkt[circuit].span, - g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan, - (siStaEvnt->contInd.contInd.val) ? "PASS" : "FAIL"); - } else { - SS7_ERROR("Recieved Continuity report containing no results!\n"); - } - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ - - -/******************************************************************************/ -static ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* check if the circuit is already blocked or not */ - if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { - SS7_WARN("Received BLO on circuit that is already blocked!\n"); - } - - /* throw the ckt block flag */ - sngss7_set_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* KONRAD FIX ME */ - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* check if the channel is blocked */ - if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) { - SS7_WARN("Received UBL on circuit that is not blocked!\n"); - } - - /* throw the unblock flag */ - sngss7_set_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); - - /* clear the block flag */ - sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* KONRAD FIX ME */ - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* throw the reset flag */ - sngss7_set_flag(sngss7_info, FLAG_RESET_RX); - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* go to idle so that we can redo the restart state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**************************************************************************/ - default: - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* throw the reset flag */ - sngss7_set_flag(sngss7_info, FLAG_RESET_RX); - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* go to idle so that we can redo the restart state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**************************************************************************/ - default: - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - if ( sngss7_test_flag(sngss7_info, FLAG_RESET_TX) ) { - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP); - - /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } else { - SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #, dropping\n", sngss7_info->circuit->cic); - } - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - - /* do nothing, just drop the message */ - SS7_DEBUG("Receveived RSC-RLC in down state, dropping\n"); - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_TERMINATING: - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP); - - /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - break; - /**********************************************************************/ - default: - /* ITU Q764-2.9.5.1.c -> release the circuit */ - if ((siStaEvnt != NULL) && - (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && - (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { - ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val; - } else { - ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ - } - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /**********************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} -/******************************************************************************/ -static ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sngss7_span_data_t *span = NULL; - int range; - int x; - - 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; - } - - /* extract the range value from the event structure */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { - range = siStaEvnt->rangStat.range.val; - } else { - SS7_ERROR("Received GRS with no range value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* loop over the cics starting from circuit until range+1 */ - for (x = circuit; x < (circuit + range + 1); x++) { - /* grab the circuit in question */ - if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x); - break; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_ASSERT; - }; - - /* fill in the span structure for this circuit */ - span = ftdmchan->span->mod_data; - span->grs.circuit = circuit; - span->grs.range = range; - - SS7_DEBUG_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); - - /* flag the channel as having received a reset */ - sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX); - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* go to idle so that we can redo the restart state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); - - break; - /**************************************************************************/ - default: - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int range; - int x; - - /* extract the range value from the event structure */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { - range = siStaEvnt->rangStat.range.val; - } else { - SS7_ERROR("Received GRA with no range value on CIC = %d\n", sngss7_info->circuit->cic); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* go through all the circuits in the range */ - for ( x = circuit; x < (circuit + range + 1); x++) { - - /* grab the circuit in question */ - if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - break; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_ASSERT; - }; - - SS7_DEBUG_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", - g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, - (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); - - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); - - /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - - /* do nothing, just drop the message */ - SS7_DEBUG("Receveived GRA in down state, dropping\n"); - - break; - /**********************************************************************/ - case FTDM_CHANNEL_STATE_TERMINATING: - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - - /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ - sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); - - break; - /**********************************************************************/ - default: - /* ITU Q764-2.9.5.1.c -> release the circuit */ - if ((siStaEvnt != NULL) && - (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && - (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { - ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val; - } else { - ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ - } - - /* go to terminating to hang up the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /**********************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* for (( x = 0; x < (circuit + range); x++) */ - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* check if the circuit is already blocked or not */ - if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { - SS7_WARN("Received local BLO on circuit that is already blocked!\n"); - } - - /* throw the ckt block flag */ - sngss7_set_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); - - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* check if the circuit is already blocked or not */ - if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { - SS7_WARN("Received local UBL on circuit that is already unblocked!\n"); - } - - /* throw the ckt block flag */ - sngss7_set_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX); - - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_ASSERT; - }; - - /* throw the ckt block flag */ - sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); - - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - - -/******************************************************************************/ -#if 0 -{ - 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; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* fill in here */ - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -#endif /******************************************************************************/ /******************************************************************************/ 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 fc2c1a66b7..a9851bda3f 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 @@ -46,7 +46,8 @@ 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_state_change (ftdm_channel_t * ftdmchan); +static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan); +static void ftdm_sangoma_ss7_process_stack_event (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); @@ -268,11 +269,12 @@ ftdm_state_map_t sangoma_ss7_state_map = { /* MONITIOR THREADS ***********************************************************/ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) { - ftdm_interrupt_t *ftdm_sangoma_ss7_int = NULL; + ftdm_interrupt_t *ftdm_sangoma_ss7_int[2]; ftdm_span_t *ftdmspan = (ftdm_span_t *) obj; ftdm_channel_t *ftdmchan = NULL; sngss7_chan_data_t *sngss7_info = NULL; - sngss7_span_data_t *sngss7_span = NULL; + sngss7_event_data_t *sngss7_event = NULL; + sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data; int i; ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id); @@ -280,31 +282,53 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) /* set IN_THREAD flag so that we know this thread is running */ ftdm_set_flag (ftdmspan, FTDM_SPAN_IN_THREAD); - /* get an interrupt queue for this span */ - if (ftdm_queue_get_interrupt (ftdmspan->pendingchans, &ftdm_sangoma_ss7_int) != FTDM_SUCCESS) { - SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d!\n", ftdmspan->span_id); + /* get an interrupt queue for this span for channel state changes */ + if (ftdm_queue_get_interrupt (ftdmspan->pendingchans, &ftdm_sangoma_ss7_int[0]) != FTDM_SUCCESS) { + SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for channel state changes!\n", ftdmspan->span_id); + goto ftdm_sangoma_ss7_run_exit; + } + + /* get an interrupt queue for this span for Trillium events */ + if (ftdm_queue_get_interrupt (sngss7_span->event_queue, &ftdm_sangoma_ss7_int[1]) != FTDM_SUCCESS) { + SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for Trillium event queue!\n", ftdmspan->span_id); goto ftdm_sangoma_ss7_run_exit; } while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) { - /* find out why we returned from the interrupt queue */ - switch ((ftdm_interrupt_wait (ftdm_sangoma_ss7_int, 100))) { + /* check the channel state queue for an event*/ + switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, 2, 100))) { /**********************************************************************/ - case FTDM_SUCCESS: /* there was a state change on the span */ - /* process all pending state changes */ + case FTDM_SUCCESS: /* process all pending state changes */ + /* clean out all pending channel state changes */ while ((ftdmchan = ftdm_queue_dequeue (ftdmspan->pendingchans))) { /* double check that this channel has a state change pending */ if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + /*first lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + ftdm_sangoma_ss7_process_state_change (ftdmchan); + + /* unlock the channel */ + ftdm_mutex_unlock (ftdmchan->mutex); } else { - SS7_ERROR("ftdm_core reported state change, but state change flag not set on ft-span = %d, ft-chan = %d\n", + /* since we handle state changes again after handling the trillium queue + * this can occur since we'll clear the flag for the event but can't pop + * the channel out of pendingchans + */ +/* SS7_ERROR("ftdm_core reported state change, but state change flag not set on ft-span = %d, ft-chan = %d\n", ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); + ftdmchan->physical_chan_id);*/ } }/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans))) */ + /* clean out all pending stack events */ + while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) { + ftdm_sangoma_ss7_process_stack_event(sngss7_event); + ftdm_safe_free(sngss7_event); + }/* while ((sngss7_event = ftdm_queue_dequeue(ftdmspan->signal_data->event_queue))) */ + break; /**********************************************************************/ case FTDM_TIMEOUT: @@ -412,6 +436,81 @@ ftdm_sangoma_ss7_run_exit: return NULL; } +/******************************************************************************/ +static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event) +{ + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(sngss7_event->circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", sngss7_event->circuit); + return; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* figure out the type of event and send it to the right handler */ + switch (sngss7_event->event_id) { + /**************************************************************************/ + case (SNGSS7_CON_IND_EVENT): + handle_con_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siConEvnt); + break; + /**************************************************************************/ + case (SNGSS7_CON_CFM_EVENT): + handle_con_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siConEvnt); + break; + /**************************************************************************/ + case (SNGSS7_CON_STA_EVENT): + handle_con_sta(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siCnStEvnt, sngss7_event->evntType); + break; + /**************************************************************************/ + case (SNGSS7_REL_IND_EVENT): + handle_rel_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt); + break; + /**************************************************************************/ + case (SNGSS7_REL_CFM_EVENT): + 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); + 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); + 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); + break; + /**************************************************************************/ + case (SNGSS7_UMSG_IND_EVENT): + handle_umsg_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit); + 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; + /**************************************************************************/ + default: + SS7_ERROR("Unknown Event Id!\n"); + break; + /**************************************************************************/ + } /* switch (sngss7_event->event_id) */ + + /* while there's a state change present on this channel process it */ + while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_ss7_process_state_change(ftdmchan); + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + return; +} + /******************************************************************************/ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) { @@ -426,9 +525,6 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) sigev.span_id = ftdmchan->span_id; sigev.channel = ftdmchan; - /*first lock the channel */ - ftdm_mutex_lock (ftdmchan->mutex); - SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state)); /* clear the state change flag...since we might be setting a new state */ @@ -1052,9 +1148,6 @@ suspend_goto_restart: /**************************************************************************/ }/*switch (ftdmchan->state) */ - /*unlock */ - ftdm_mutex_unlock (ftdmchan->mutex); - return; } @@ -1254,7 +1347,7 @@ static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t * span) /* SIG_FUNCTIONS ***************************************************************/ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config) { - sngss7_span_data_t *ss7_span_info; + sngss7_span_data_t *ss7_span_info; ftdm_log (FTDM_LOG_INFO, "Configuring ftmod_sangoma_ss7 span = %s(%d)...\n", span->name, @@ -1264,29 +1357,20 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config) ss7_span_info = ftdm_calloc (1, sizeof (sngss7_span_data_t)); /* create a timer schedule */ - if (ftdm_sched_create (&ss7_span_info->sched, "SngSS7_Schedule")) { - SS7_CRITICAL ("Unable to create timer schedule!\n"); + if (ftdm_sched_create(&ss7_span_info->sched, "SngSS7_Schedule")) { + SS7_CRITICAL("Unable to create timer schedule!\n"); return FTDM_FAIL; } /* start the free run thread for the schedule */ - if (ftdm_sched_free_run (ss7_span_info->sched)) { - SS7_CRITICAL ("Unable to schedule free run!\n"); + if (ftdm_sched_free_run(ss7_span_info->sched)) { + SS7_CRITICAL("Unable to schedule free run!\n"); return FTDM_FAIL; } - /* attach the span info to the span */ - span->mod_data = ss7_span_info; - - /* 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"); - return FTDM_FAIL; - } - - /* configure libsngss7 */ - if (ft_to_sngss7_cfg_all()) { - ftdm_log (FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n"); + /* create an event queue for this span */ + if ((ftdm_queue_create(&(ss7_span_info)->event_queue, SNGSS7_EVENT_QUEUE_SIZE)) != FTDM_SUCCESS) { + SS7_CRITICAL("Unable to create event queue!\n"); return FTDM_FAIL; } @@ -1302,9 +1386,22 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config) span->get_channel_sig_status = ftdm_sangoma_ss7_get_sig_status; span->set_channel_sig_status = ftdm_sangoma_ss7_set_sig_status; span->state_map = &sangoma_ss7_state_map; + span->mod_data = ss7_span_info; ftdm_set_flag (span, FTDM_SPAN_USE_CHAN_QUEUE); + /* 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"); + return FTDM_FAIL; + } + + /* configure libsngss7 */ + if (ft_to_sngss7_cfg_all()) { + ftdm_log (FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n"); + return FTDM_FAIL; + } + ftdm_log (FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_ss7 span = %s(%d)...\n", span->name, span->span_id); @@ -1336,7 +1433,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init) /* message (IAM, ACM, ANM, etc) trace initizalation */ g_ftdm_sngss7_data.message_trace = 1; - g_ftdm_sngss7_data.message_trace_level = 7; + g_ftdm_sngss7_data.message_trace_level = 6; /* setup the call backs needed by Sangoma_SS7 library */ sng_event.cc.sng_con_ind = sngss7_con_ind; 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 6bfc38e588..3bf12ae307 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 @@ -50,12 +50,26 @@ /******************************************************************************/ /* DEFINES ********************************************************************/ -#define MAX_NAME_LEN 10 -#define MAX_PATH 255 +#define MAX_NAME_LEN 10 +#define MAX_PATH 255 -#define MAX_CIC_LENGTH 5 -#define MAX_CIC_MAP_LENGTH 1000 +#define MAX_CIC_LENGTH 5 +#define MAX_CIC_MAP_LENGTH 1000 +#define SNGSS7_EVENT_QUEUE_SIZE 100 + +typedef enum { + SNGSS7_CON_IND_EVENT = 0, + SNGSS7_CON_CFM_EVENT, + SNGSS7_CON_STA_EVENT, + SNGSS7_REL_IND_EVENT, + SNGSS7_REL_CFM_EVENT, + SNGSS7_DAT_IND_EVENT, + SNGSS7_FAC_IND_EVENT, + SNGSS7_FAC_CFM_EVENT, + SNGSS7_UMSG_IND_EVENT, + SNGSS7_STA_IND_EVENT +} sng_event_type_t; typedef enum { VOICE = 0, @@ -334,8 +348,31 @@ typedef struct sngss7_chan_data { typedef struct sngss7_span_data { ftdm_sched_t *sched; sngss7_group_data_t grs; + ftdm_queue_t *event_queue; }sngss7_span_data_t; +typedef struct sngss7_event_data +{ + uint32_t event_id; + uint32_t spId; + uint32_t suId; + uint32_t spInstId; + uint32_t suInstId; + uint32_t circuit; + uint8_t globalFlg; + uint8_t evntType; + union + { + SiConEvnt siConEvnt; + SiCnStEvnt siCnStEvnt; + SiRelEvnt siRelEvnt; + SiInfoEvnt siInfoEvnt; + SiFacEvnt siFacEvnt; + SiStaEvnt siStaEvnt; + } event; +} sngss7_event_data_t; + + typedef enum { @@ -441,6 +478,36 @@ void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); +ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); +ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); +ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); +ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); +ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); +ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt); +ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); +ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); +ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); +ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); + +ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); + 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); From ce34d86c704e7f4bf95cc2a6a1beebf872c96901 Mon Sep 17 00:00:00 2001 From: Konrad Hammel Date: Wed, 1 Sep 2010 12:44:28 -0400 Subject: [PATCH 3/7] freetdm: ss7 - updated to allow TMR/bearer cap pass-through --- .../ftmod_sangoma_ss7_handle.c | 78 +++++++---- .../ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c | 130 +++++++++--------- 2 files changed, 117 insertions(+), 91 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 d1f3a8b89c..a0bf95b09c 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 @@ -41,7 +41,6 @@ /* GLOBALS ********************************************************************/ /******************************************************************************/ -/* PROTOTYPES *****************************************************************/ /* PROTOTYPES *****************************************************************/ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); @@ -140,43 +139,68 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ } else { - /* fill in cid/ani number */ - if (siConEvnt->cgPtyNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig, - ftdmchan->caller_data.cid_num.digits, - siConEvnt->cgPtyNum.oddEven); + /* fill in calling party information */ + if (siConEvnt->cgPtyNum.eh.pres) { + if (siConEvnt->cgPtyNum.addrSig.pres) { + /* fill in cid_num */ + copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig, + ftdmchan->caller_data.cid_num.digits, + siConEvnt->cgPtyNum.oddEven); - /* fill in cid Name */ - ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits); + /* fill in cid Name */ + ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits); - ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits); + /* fill in ANI */ + ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits); + } + if (siConEvnt->cgPtyNum.scrnInd.pres) { + /* fill in the screening indication value */ + ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val; + } + + if (siConEvnt->cgPtyNum.presRest.pres) { + /* fill in the presentation value */ + ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val; + } } else { - SS7_INFO("No Calling party (ANI) information in IAM!\n"); + SS7_INFO_CHAN(ftdmchan,"No Calling party (ANI) information in IAM!%s\n", " "); } - /* fill in dnis */ - if (siConEvnt->cdPtyNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, - ftdmchan->caller_data.dnis.digits, - siConEvnt->cdPtyNum.oddEven); + /* fill in called party infomation */ + if (siConEvnt->cdPtyNum.eh.pres) { + if (siConEvnt->cdPtyNum.addrSig.pres) { + /* fill in the called number/dnis */ + copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, + ftdmchan->caller_data.dnis.digits, + siConEvnt->cdPtyNum.oddEven); + } + } else { + SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in IAM!%s\n", " "); + } + + /* fill in rdnis information*/ + if (siConEvnt->redirgNum.eh.pres) { + if (siConEvnt->redirgNum.addrSig.pres) { + /* fill in the rdnis digits */ + copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig, + ftdmchan->caller_data.rdnis.digits, + siConEvnt->cgPtyNum.oddEven); + } } else { - SS7_INFO("No Called party (DNIS) information in IAM!\n"); + SS7_DEBUG_CHAN(ftdmchan,"No RDNIS party information in IAM!%s\n", " "); } - /* fill in rdnis */ - if (siConEvnt->redirgNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig, - ftdmchan->caller_data.rdnis.digits, - siConEvnt->cgPtyNum.oddEven); - } else { - SS7_INFO("No RDNIS party information in IAM!\n"); + /* fill in the TMR/bearer capability */ + if (siConEvnt->txMedReq.eh.pres) { + if (siConEvnt->txMedReq.trMedReq.pres) { + /* fill in the bearer type */ + ftdmchan->caller_data.bearer_capability = siConEvnt->txMedReq.trMedReq.val; + } + } else { + SS7_DEBUG_CHAN(ftdmchan,"No TMR/Bearer Cap information in IAM!%s\n", " "); } - /* fill in screening/presentation */ - ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val; - ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val; - /* 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); 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 53d0f9d937..600a52910c 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 @@ -64,70 +64,72 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan); void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) { - SS7_FUNC_TRACE_ENTER (__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; - SiConEvnt iam; - - sngss7_info->suInstId = get_unique_id (); - sngss7_info->spInstId = 0; - sngss7_info->spId = 1; - - memset (&iam, 0x0, sizeof (iam)); - - /* copy down the nature of connection indicators */ - iam.natConInd.eh.pres = PRSNT_NODEF; - iam.natConInd.satInd.pres = PRSNT_NODEF; - iam.natConInd.satInd.val = 0; - iam.natConInd.contChkInd.pres = PRSNT_NODEF; - iam.natConInd.contChkInd.val = 0x00; - iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF; - iam.natConInd.echoCntrlDevInd.val = 0x01; - - /* copy down the forward call indicators */ - iam.fwdCallInd.eh.pres = PRSNT_NODEF; - iam.fwdCallInd.natIntCallInd.pres = PRSNT_NODEF; - iam.fwdCallInd.natIntCallInd.val = 0x00; - iam.fwdCallInd.end2EndMethInd.pres = PRSNT_NODEF; - iam.fwdCallInd.end2EndMethInd.val = 0x00; - iam.fwdCallInd.intInd.pres = PRSNT_NODEF; - iam.fwdCallInd.intInd.val = 0x01; - iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF; - iam.fwdCallInd.end2EndInfoInd.val = 0x00; - iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtInd.val = 0x01; - iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtPrfInd.val = 0x02; - iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnAccInd.val = 0x01; - iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF; - iam.fwdCallInd.sccpMethInd.val = 0x00; - - /* copy down the calling number information */ - iam.cgPtyCat.eh.pres = PRSNT_NODEF; - iam.cgPtyCat.cgPtyCat.pres = PRSNT_NODEF; - iam.cgPtyCat.cgPtyCat.val = 0x0a; - - /* copy down the transmission medium requirements */ - iam.txMedReq.eh.pres = PRSNT_NODEF; - iam.txMedReq.trMedReq.pres = PRSNT_NODEF; - iam.txMedReq.trMedReq.val = 0; /* SPEECH = 0, 3.1Khz = 3, 64k unres = 2 */ - - /* copy down the called number information */ - copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum); - - /* copy down the calling number information */ - copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum); - - sng_cc_con_request (sngss7_info->spId, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, &iam, 0); - - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx IAM\n"); - - SS7_FUNC_TRACE_EXIT (__FUNCTION__); - return; + SS7_FUNC_TRACE_ENTER (__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; + SiConEvnt iam; + + sngss7_info->suInstId = get_unique_id (); + sngss7_info->spInstId = 0; + sngss7_info->spId = 1; + + memset (&iam, 0x0, sizeof (iam)); + + /* copy down the nature of connection indicators */ + iam.natConInd.eh.pres = PRSNT_NODEF; + iam.natConInd.satInd.pres = PRSNT_NODEF; + iam.natConInd.satInd.val = 0; /* no satellite circuit */ + iam.natConInd.contChkInd.pres = PRSNT_NODEF; + iam.natConInd.contChkInd.val = CONTCHK_NOTREQ; + iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF; + iam.natConInd.echoCntrlDevInd.val = ECHOCDEV_INCL; + + /* copy down the forward call indicators */ + iam.fwdCallInd.eh.pres = PRSNT_NODEF; + iam.fwdCallInd.natIntCallInd.pres = PRSNT_NODEF; + iam.fwdCallInd.natIntCallInd.val = 0x00; + iam.fwdCallInd.end2EndMethInd.pres = PRSNT_NODEF; + iam.fwdCallInd.end2EndMethInd.val = E2EMTH_NOMETH; + iam.fwdCallInd.intInd.pres = PRSNT_NODEF; + iam.fwdCallInd.intInd.val = INTIND_NOINTW; + iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF; + iam.fwdCallInd.end2EndInfoInd.val = E2EINF_NOINFO; + iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; + iam.fwdCallInd.isdnUsrPrtInd.val = ISUP_USED; + iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF; + iam.fwdCallInd.isdnUsrPrtPrfInd.val = PREF_REQAW; + iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF; + iam.fwdCallInd.isdnAccInd.val = ISDNACC_ISDN; + iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF; + iam.fwdCallInd.sccpMethInd.val = SCCPMTH_NOIND; + + /* copy down the calling number information */ + iam.cgPtyCat.eh.pres = PRSNT_NODEF; + iam.cgPtyCat.cgPtyCat.pres = PRSNT_NODEF; + iam.cgPtyCat.cgPtyCat.val = CAT_ORD; /* ordinary suscriber */ + + /* copy down the transmission medium requirements */ + iam.txMedReq.eh.pres = PRSNT_NODEF; + iam.txMedReq.trMedReq.pres = PRSNT_NODEF; + iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability; + + /* copy down the called number information */ + copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum); + + /* copy down the calling number information */ + copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum); + + sng_cc_con_request (sngss7_info->spId, + sngss7_info->suInstId, + sngss7_info->spInstId, + sngss7_info->circuit->id, + &iam, + 0); + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx IAM\n"); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); + return; } /******************************************************************************/ From a278b6b403cc58e65dae32ca7ded444746e0cab3 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 1 Sep 2010 14:42:34 -0400 Subject: [PATCH 4/7] freetdm: added channel variable iterator for signaling specific data --- libs/freetdm/mod_freetdm/mod_freetdm.c | 20 +++- libs/freetdm/src/ftdm_io.c | 107 ++++++++++++++---- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 6 +- libs/freetdm/src/include/freetdm.h | 22 +++- libs/freetdm/src/include/private/ftdm_core.h | 1 - 5 files changed, 122 insertions(+), 34 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 890d9d9d43..0117fcedf1 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -40,7 +40,7 @@ #define FREETDM_LIMIT_REALM "__freetdm" #define FREETDM_VAR_PREFIX "freetdm_" -#define FREETDM_VAR_PREFIX_LEN 8 +#define FREETDM_VAR_PREFIX_LEN (sizeof(FREETDM_VAR_PREFIX)-1) SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown); @@ -1302,11 +1302,14 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } } - ftdm_channel_clear_vars(ftdmchan); + span_id = ftdm_channel_get_span_id(ftdmchan); + chan_id = ftdm_channel_get_id(ftdmchan); + for (h = var_event->headers; h; h = h->next) { if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) { char *v = h->name + FREETDM_VAR_PREFIX_LEN; if (!zstr(v)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); ftdm_channel_add_var(ftdmchan, v, h->value); } } @@ -1317,9 +1320,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_caller_profile_t *caller_profile; switch_channel_t *channel = switch_core_session_get_channel(*new_session); - span_id = ftdm_channel_get_span_id(ftdmchan); - chan_id = ftdm_channel_get_id(ftdmchan); - switch_core_session_add_stream(*new_session, NULL); if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { tech_init(tech_pvt, *new_session, ftdmchan); @@ -1403,6 +1403,9 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_core_session_t *session = NULL; private_t *tech_pvt = NULL; switch_channel_t *channel = NULL; + ftdm_iterator_t *iter = NULL; + const char *var_name = NULL; + const char *var_value = NULL; uint32_t spanid, chanid; char name[128]; ftdm_caller_data_t *channel_caller_data = ftdm_channel_get_caller_data(sigmsg->channel); @@ -1511,6 +1514,13 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session if (channel_caller_data->raw_data_len) { switch_channel_set_variable_printf(channel, "freetdm_custom_call_data", "%s", channel_caller_data->raw_data); } + /* Add any channel variable to the dial plan */ + iter = ftdm_channel_get_var_iterator(sigmsg->channel); + for ( ; iter; iter = ftdm_iterator_next(iter)) { + ftdm_channel_get_current_var(iter, &var_name, &var_value); + snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name); + switch_channel_set_variable_printf(channel, name, "%s", var_value); + } switch_channel_set_state(channel, CS_INIT); if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 238a9fc060..b087881e1d 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -400,8 +400,6 @@ static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan) ftdm_buffer_destroy(&ftdmchan->fsk_buffer); ftdmchan->pre_buffer_size = 0; - hashtable_destroy(ftdmchan->variable_hash); - ftdm_safe_free(ftdmchan->dtmf_hangup_buf); if (ftdmchan->tone_session.buffer) { @@ -812,7 +810,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t ftdm_buffer_create(&new_chan->digit_buffer, 128, 128, 0); ftdm_buffer_create(&new_chan->gen_dtmf_buffer, 128, 128, 0); - new_chan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); new_chan->dtmf_hangup_buf = ftdm_calloc (span->dtmf_hangup_len + 1, sizeof (char)); @@ -2213,9 +2210,10 @@ static void close_dtmf_debug(ftdm_channel_t *ftdmchan) } #endif +static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) { - assert(ftdmchan != NULL); + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n"); ftdm_mutex_lock(ftdmchan->mutex); @@ -2243,6 +2241,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) #ifdef FTDM_DEBUG_DTMF close_dtmf_debug(ftdmchan); #endif + ftdm_channel_clear_vars(ftdmchan); ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN; ftdmchan->state = FTDM_CHANNEL_STATE_DOWN; @@ -3368,8 +3367,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat ftdm_size_t max = datasize; unsigned int i = 0; - assert(ftdmchan != NULL); - assert(ftdmchan->fio != NULL); + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel on write!\n"); + ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "null I/O on write!\n"); if (!ftdmchan->buffer_delay && ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) || @@ -3421,16 +3420,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat return status; } -FT_DECLARE(ftdm_status_t) ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan) +static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan) { - if(ftdmchan->variable_hash) { + ftdm_channel_lock(ftdmchan); + + if (ftdmchan->variable_hash) { hashtable_destroy(ftdmchan->variable_hash); } - ftdmchan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + ftdmchan->variable_hash = NULL; - if(!ftdmchan->variable_hash) - return FTDM_FAIL; - + ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } @@ -3438,34 +3437,98 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_var(ftdm_channel_t *ftdmchan, const c { char *t_name = 0, *t_val = 0; - if(!ftdmchan->variable_hash || !var_name || !value) - { + ftdm_status_t status = FTDM_FAIL; + + if (!var_name || !value) { return FTDM_FAIL; } + ftdm_channel_lock(ftdmchan); + + if (!ftdmchan->variable_hash) { + /* initialize on first use */ + ftdmchan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + if (!ftdmchan->variable_hash) { + goto done; + } + } + t_name = ftdm_strdup(var_name); t_val = ftdm_strdup(value); - if(hashtable_insert(ftdmchan->variable_hash, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE)) { - return FTDM_SUCCESS; - } - return FTDM_FAIL; + hashtable_insert(ftdmchan->variable_hash, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); + + status = FTDM_SUCCESS; + +done: + ftdm_channel_unlock(ftdmchan); + + return status; } FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name) { - if(!ftdmchan->variable_hash || !var_name) - { + const char *var = NULL; + + ftdm_channel_lock(ftdmchan); + + if (!ftdmchan->variable_hash || !var_name) { + goto done; + } + + var = (const char *)hashtable_search(ftdmchan->variable_hash, (void *)var_name); + +done: + ftdm_channel_unlock(ftdmchan); + + return var; +} + +FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan) +{ + ftdm_hash_iterator_t *iter = NULL; + + ftdm_channel_lock(ftdmchan); + + iter = ftdmchan->variable_hash == NULL ? NULL : hashtable_first(ftdmchan->variable_hash); + + ftdm_channel_unlock(ftdmchan); + + return iter; +} + +FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val) +{ + const void *key = NULL; + void *val = NULL; + + *var_name = NULL; + *var_val = NULL; + + if (!iter) { + return FTDM_FAIL; + } + + hashtable_this(iter, &key, NULL, &val); + + *var_name = key; + *var_val = val; + + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter) +{ + if (!iter) { return NULL; } - return (const char *) hashtable_search(ftdmchan->variable_hash, (void *)var_name); + return hashtable_next(iter); } static struct { ftdm_io_interface_t *pika_interface; } interfaces; - FT_DECLARE(char *) ftdm_api_execute(const char *cmd) { ftdm_io_interface_t *fio = NULL; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index b47660b076..a98429da73 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -35,7 +35,6 @@ #include "ftmod_sangoma_isdn.h" -#define FTDM_DEBUG_CHAN_MEMORY #ifdef FTDM_DEBUG_CHAN_MEMORY #include @@ -472,7 +471,10 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) case FTDM_CHANNEL_STATE_RING: /* incoming call request */ { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits); - + ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1"); + ftdm_channel_add_var(ftdmchan, "isdn_crap", "morecrap"); + ftdm_channel_add_var(ftdmchan, "isdn_stuff", "s"); + ftdm_channel_add_var(ftdmchan, "isdn_d", "asdsadasdasdsad"); /* we have enough information to inform FTDM of the call*/ sigev.event_id = FTDM_SIGEVENT_START; ftdm_span_send_signal(ftdmchan->span, &sigev); diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 132fd303a2..61d37c8878 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -381,6 +381,9 @@ typedef struct ftdm_conf_parameter { void *ptr; } ftdm_conf_parameter_t; +/*! \brief Opaque general purpose iterator */ +typedef void ftdm_iterator_t; + /*! \brief Channel commands that can be executed through ftdm_channel_command() */ typedef enum { FTDM_COMMAND_NOOP, @@ -1014,14 +1017,25 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data */ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t datasize, ftdm_size_t *datalen); -/*! \brief Add a custom variable to the channel */ +/*! \brief Add a custom variable to the channel + * \note This variables may be used by signaling modules to override signaling parameters + * \todo Document which signaling variables are available + * */ FT_DECLARE(ftdm_status_t) ftdm_channel_add_var(ftdm_channel_t *ftdmchan, const char *var_name, const char *value); -/*! \brief Get a custom variable from the channel */ +/*! \brief Get a custom variable from the channel. + * \note The variable pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. */ FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name); -/*! \brief Clear custom channel variables from the channel */ -FT_DECLARE(ftdm_status_t) ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); +/*! \brief Get an iterator to iterate over the channel variables + * \note The iterator pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. */ +FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan); + +/*! \brief Get variable name and value for the current iterator position */ +FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val); + +/*! \brief Advance iterator */ +FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter); /*! \brief Get the span pointer associated to the channel */ FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan); diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 95f34b4dd2..eb9a84a84a 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -579,7 +579,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t * */ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, const char *dtmf); - /*! \brief Assert condition */ From 3f3d412b4b4ebdec6a699d19e08d8aede5880bb9 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Tue, 31 Aug 2010 18:13:56 -0400 Subject: [PATCH 5/7] freetdm: add asynchronous signal notification --- libs/freetdm/src/ftdm_io.c | 52 ++++++++++++++++--- libs/freetdm/src/include/freetdm.h | 35 +++++++------ libs/freetdm/src/include/private/ftdm_core.h | 4 ++ libs/freetdm/src/include/private/ftdm_types.h | 4 ++ 4 files changed, 71 insertions(+), 24 deletions(-) diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index b087881e1d..7f27177024 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -51,6 +51,7 @@ #include "ftdm_cpu_monitor.h" #define SPAN_PENDING_CHANS_QUEUE_SIZE 1000 +#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000 #define FTDM_READ_TRACE_INDEX 0 #define FTDM_WRITE_TRACE_INDEX 1 @@ -461,6 +462,9 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span) if (span->pendingchans) { ftdm_queue_destroy(&span->pendingchans); } + if (span->pendingsignals) { + ftdm_queue_destroy(&span->pendingsignals); + } ftdm_mutex_unlock(span->mutex); ftdm_mutex_destroy(&span->mutex); ftdm_safe_free(span->signal_data); @@ -4160,6 +4164,9 @@ static ftdm_status_t post_configure_span_channels(ftdm_span_t *span) if (ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) { status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE); } + if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) { + status = ftdm_queue_create(&span->pendingsignals, SPAN_PENDING_SIGNALS_QUEUE_SIZE); + } return status; } @@ -4425,10 +4432,39 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na return status; } +static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) +{ + return span->signal_cb(sigmsg); +} + +static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) +{ + ftdm_sigmsg_t *new_sigmsg = NULL; + + ftdm_assert_return((sigmsg->raw_data == NULL), FTDM_FAIL, "No raw data should be used with asynchronous notification\n"); + + new_sigmsg = ftdm_calloc(1, sizeof(*sigmsg)); + if (!new_sigmsg) { + return FTDM_FAIL; + } + memcpy(new_sigmsg, sigmsg, sizeof(*sigmsg)); + + ftdm_queue_enqueue(span->pendingsignals, new_sigmsg); + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span) +{ + ftdm_sigmsg_t *sigmsg = NULL; + while ((sigmsg = ftdm_queue_dequeue(span->pendingsignals))) { + ftdm_span_trigger_signal(span, sigmsg); + ftdm_safe_free(sigmsg); + } + return FTDM_SUCCESS; +} + FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) { - ftdm_status_t status = FTDM_FAIL; - if (sigmsg->channel) { ftdm_mutex_lock(sigmsg->channel->mutex); } @@ -4463,10 +4499,12 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t break; } - - /* call the user callback only if set */ - if (span->signal_cb) { - status = span->signal_cb(sigmsg); + + /* if the signaling module uses a queue for signaling notifications, then enqueue it */ + if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) { + ftdm_span_queue_signal(span, sigmsg); + } else { + ftdm_span_trigger_signal(span, sigmsg); } done: @@ -4474,7 +4512,7 @@ done: ftdm_mutex_unlock(sigmsg->channel->mutex); } - return status; + return FTDM_SUCCESS; } static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj) diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 61d37c8878..7501bb4977 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -331,23 +331,6 @@ typedef struct ftdm_channel_config { float txgain; } ftdm_channel_config_t; -/*! \brief Generic signaling message */ -struct ftdm_sigmsg { - ftdm_signal_event_t event_id; /*!< The type of message */ - ftdm_channel_t *channel; /*!< Related channel */ - uint32_t chan_id; /*!< easy access to chan id */ - uint32_t span_id; /*!< easy access to span_id */ - void *raw_data; /*!< Message specific data if any */ - uint32_t raw_data_len; /*!< Data len in case is needed */ -}; - -/*! \brief Crash policy - * Useful for debugging only, default policy is never, if you wish to crash on asserts then use ftdm_global_set_crash_policy */ -typedef enum { - FTDM_CRASH_NEVER = 0, - FTDM_CRASH_ON_ASSERT -} ftdm_crash_policy_t; - /*! \brief Signaling status on a given span or specific channel on protocols that support it */ @@ -366,6 +349,24 @@ typedef enum { /*! \brief Move from string to ftdm_signaling_status_t and viceversa */ FTDM_STR2ENUM_P(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t) +/*! \brief Generic signaling message */ +struct ftdm_sigmsg { + ftdm_signal_event_t event_id; /*!< The type of message */ + ftdm_channel_t *channel; /*!< Related channel */ + uint32_t chan_id; /*!< easy access to chan id */ + uint32_t span_id; /*!< easy access to span_id */ + ftdm_signaling_status_t sigstatus; /*!< Signaling status (valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED) */ + void *raw_data; /*!< Message specific data if any */ + uint32_t raw_data_len; /*!< Data len in case is needed */ +}; + +/*! \brief Crash policy + * Useful for debugging only, default policy is never, if you wish to crash on asserts then use ftdm_global_set_crash_policy */ +typedef enum { + FTDM_CRASH_NEVER = 0, + FTDM_CRASH_ON_ASSERT +} ftdm_crash_policy_t; + /*! \brief I/O waiting flags */ typedef enum { FTDM_NO_FLAGS = 0, diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index eb9a84a84a..74bea8148c 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -466,6 +466,7 @@ struct ftdm_span { ftdm_state_map_t *state_map; ftdm_caller_data_t default_caller_data; ftdm_queue_t *pendingchans; + ftdm_queue_t *pendingsignals; struct ftdm_span *next; }; @@ -579,6 +580,9 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t * */ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, const char *dtmf); +/* dequeue pending signals and notify the user via the span signal callback */ +FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span); + /*! \brief Assert condition */ diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index 572e63299b..d8e8b5c2e6 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -176,6 +176,10 @@ typedef enum { FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6), FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7), FTDM_SPAN_USE_AV_RATE = (1 << 8), + /* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals + * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal + * for later delivery */ + FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 9), } ftdm_span_flag_t; /*! \brief Channel supported features */ From e4b5c49fc105c3f13c31db8dd5be0c5cd8a8c655 Mon Sep 17 00:00:00 2001 From: David Yat Sin Date: Tue, 31 Aug 2010 19:05:37 -0400 Subject: [PATCH 6/7] freetdm: fix code using raw_data as an integer when is actually null --- libs/freetdm/mod_freetdm/mod_freetdm.c | 6 +++--- libs/freetdm/src/ftdm_io.c | 11 +++++++---- .../src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c | 5 +++-- .../ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c | 2 +- 4 files changed, 14 insertions(+), 10 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 0117fcedf1..55f899e5c0 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2117,10 +2117,10 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) } break; case FTDM_SIGEVENT_SIGSTATUS_CHANGED: - { - ftdm_signaling_status_t *sigstatus = (ftdm_signaling_status_t*)(sigmsg->raw_data); + { + ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to :%s\n", - spanid, chanid, ftdm_signaling_status2str(*sigstatus)); + spanid, chanid, ftdm_signaling_status2str(sigstatus)); } break; default: diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 7f27177024..dcb74d94fc 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -4473,10 +4473,13 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t switch (sigmsg->event_id) { case FTDM_SIGEVENT_SIGSTATUS_CHANGED: - if (*((ftdm_signaling_status_t*)(sigmsg->raw_data)) == FTDM_SIG_STATE_UP) { - ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); - } else { - ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + { + ftdm_signaling_status_t sigstatus = ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE) ? sigmsg->sigstatus : *((ftdm_signaling_status_t*)(sigmsg->raw_data)); + if (sigstatus == FTDM_SIG_STATE_UP) { + ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + } else { + ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + } } break; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index a98429da73..ef440634c8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -278,11 +278,11 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) ftdm_channel_unlock(ftdmchan); } - /* Check if there are any timers to process */ while ((sngisdn_event = ftdm_queue_dequeue(signal_data->event_queue))) { ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event); ftdm_safe_free(sngisdn_event); - } + } + ftdm_span_trigger_signals(span); break; case FTDM_TIMEOUT: /* twiddle */ @@ -793,6 +793,7 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) span->set_channel_sig_status = ftdm_sangoma_isdn_set_sig_status; span->state_map = &sangoma_isdn_state_map; ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); + ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || span->trunk_type == FTDM_TRUNK_BRI) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c index 5299c91b44..7aba6a66ce 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c @@ -48,7 +48,7 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.raw_data = &status; + sig.sigstatus = status; ftdm_span_send_signal(ftdmchan->span, &sig); return; } From cd0cc2e4a30398b3a2e1eb8f5e10c2df3e041fa0 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Thu, 2 Sep 2010 12:38:43 -0400 Subject: [PATCH 7/7] freetdm: only notify interrupt waiters if there is not a notification already pending --- libs/freetdm/src/ftdm_threadmutex.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c index 79bd28f7d9..56bd49ca18 100644 --- a/libs/freetdm/src/ftdm_threadmutex.c +++ b/libs/freetdm/src/ftdm_threadmutex.c @@ -376,9 +376,19 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *interrupt) } #else int err; - if ((err = write(interrupt->writefd, "w", 1)) != 1) { - ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt: %s\n", errno, strerror(errno)); - return FTDM_FAIL; + struct pollfd testpoll; + testpoll.revents = 0; + testpoll.events = POLLIN; + testpoll.fd = interrupt->readfd; + err = poll(&testpoll, 1, 0); + if (err == 0 && !(testpoll.revents & POLLIN)) { + /* we just try to notify if there is nothing on the read fd already, + * otherwise users that never call interrupt wait eventually will + * eventually have the pipe buffer filled */ + if ((err = write(interrupt->writefd, "w", 1)) != 1) { + ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt: %s\n", errno, strerror(errno)); + return FTDM_FAIL; + } } #endif return FTDM_SUCCESS;