freetdm: merged konrad and david signaling work

This commit is contained in:
Moises Silva 2010-08-31 13:29:31 -04:00
parent e8958479bb
commit 80363af697
27 changed files with 11764 additions and 7370 deletions

View File

@ -41,6 +41,9 @@ INCS += -I$(FT_SRCDIR)/$(SRC)/ftmod/ftmod_sangoma_boost
if SNGSS7
INCS += -I/usr/include/sng_ss7/
endif
if SNGISDN
INCS += -I/usr/include/sng_isdn/
endif
MY_CFLAGS = $(INCS) $(FTDM_CFLAGS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@
COMPILE = $(CC) $(MY_CFLAGS) $(INCS)
@ -70,6 +73,7 @@ $(SRC)/hashtable_itr.c \
$(SRC)/ftdm_io.c \
$(SRC)/ftdm_queue.c \
$(SRC)/ftdm_sched.c \
$(SRC)/ftdm_call_utils.c \
$(SRC)/ftdm_config.c \
$(SRC)/ftdm_callerid.c \
$(SRC)/fsk.c \
@ -271,7 +275,11 @@ ftmod_sangoma_ss7_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7
$(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_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)
@ -285,17 +293,16 @@ ftmod_sangoma_isdn_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_is
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c \
$(SRC)/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c
ftmod_sangoma_isdn_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)
ftmod_sangoma_isdn_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE
ftmod_sangoma_isdn_la_LDFLAGS = -module -avoid-version -lsng_isdn
ftmod_sangoma_isdn_la_LIBADD = $(MYLIB)
endif
if OPENR2
ftmod_r2_la_SOURCES = $(SRC)/ftmod/ftmod_r2/ftmod_r2.c
ftmod_r2_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS)

View File

@ -193,6 +193,18 @@ AM_CONDITIONAL([SNGISDN],[test "${have_sng_isdn}" = "yes"])
AC_CHECK_LIB([openr2], [openr2_context_set_io_type], [have_openr2="yes"])
AM_CONDITIONAL([OPENR2],[test "${have_openr2}" = "yes"])
if test "${have_sng_isdn}" = "yes"; then
if test "${build}" == "${host}"
then
case "${host}" in
x86_64-*)
# X86_64 machines need additional flags when compiling against libsng_isdn
CFLAGS="$CFLAGS -DBIT_64 -DALIGN_64BIT"
;;
esac
fi
fi
COMP_VENDOR_CFLAGS="$COMP_VENDOR_CFLAGS"
AC_SUBST(COMP_VENDOR_CFLAGS)
AC_CONFIG_FILES([Makefile

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* David Yat Sin <dyatsin@sangoma.com>
* 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 "private/ftdm_core.h"
#include <ctype.h>
FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target)
{
if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) {
*target = FTDM_NPI_ISDN;
} else if (!strcasecmp(npi_string, "data")) {
*target = FTDM_NPI_DATA;
} else if (!strcasecmp(npi_string, "telex")) {
*target = FTDM_NPI_TELEX;
} else if (!strcasecmp(npi_string, "national")) {
*target = FTDM_NPI_NATIONAL;
} else if (!strcasecmp(npi_string, "private")) {
*target = FTDM_NPI_PRIVATE;
} else if (!strcasecmp(npi_string, "reserved")) {
*target = FTDM_NPI_RESERVED;
} else if (!strcasecmp(npi_string, "unknown")) {
*target = FTDM_NPI_UNKNOWN;
} else {
ftdm_log(FTDM_LOG_WARNING, "Invalid NPI value (%s)\n", npi_string);
*target = FTDM_NPI_UNKNOWN;
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target)
{
if (!strcasecmp(ton_string, "national")) {
*target = FTDM_TON_NATIONAL;
} else if (!strcasecmp(ton_string, "international")) {
*target = FTDM_TON_INTERNATIONAL;
} else if (!strcasecmp(ton_string, "local")) {
*target = FTDM_TON_SUBSCRIBER_NUMBER;
} else if (!strcasecmp(ton_string, "unknown")) {
*target = FTDM_TON_UNKNOWN;
} else {
ftdm_log(FTDM_LOG_WARNING, "Invalid TON value (%s)\n", ton_string);
*target = FTDM_TON_UNKNOWN;
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number)
{
if (!number) {
return FTDM_FAIL;
}
for ( ; *number; number++) {
if (!isdigit(*number)) {
return FTDM_FAIL;
}
}
return FTDM_SUCCESS;
}

View File

@ -46,116 +46,28 @@
#include <sng_isdn.h>
#define MAX_SPANS_PER_NFAS_LINK 8 /* TODO: Confirm this value */
#define NUM_E1_CHANNELS_PER_SPAN 32
#define NUM_T1_CHANNELS_PER_SPAN 24
#define NUM_BRI_CHANNELS_PER_SPAN 2
/* Theoretical limit for MAX_SPANS_PER_NFAS_LINK is 31,
but set to 8 for now to save some memor */
/* Should never have DEBUG_MODE defined when used in production */
#if 0
#undef DEBUG_MODE
#define FORCE_SEFGAULT
#else
#define DEBUG_MODE
#define FORCE_SEGFAULT *(int *) 0 = 0;
#endif
#define MAX_SPANS_PER_NFAS_LINK 8
#define NUM_E1_CHANNELS_PER_SPAN 32
#define NUM_T1_CHANNELS_PER_SPAN 24
#define NUM_BRI_CHANNELS_PER_SPAN 2
#define SNGISDN_EVENT_QUEUE_SIZE 100
#define SNGISDN_EVENT_POLL_RATE 100
/* TODO: rename all *_cc_* to *_an_* */
typedef struct sngisdn_glare_data {
int16_t suId;
uint32_t suInstId;
uint32_t spInstId;
int16_t dChan;
ConEvnt setup;
uint8_t ces;
}sngisdn_glare_data_t;
/* Channel specific data */
typedef struct sngisdn_chan_data {
ftdm_channel_t *ftdmchan;
uint32_t flags;
uint8_t ces; /* not used for now */
uint8_t dchan_id;
uint32_t suInstId; /* instance ID generated locally */
uint32_t spInstId; /* instance ID generated by stack */
uint8_t globalFlg;
sngisdn_glare_data_t glare;
} sngisdn_chan_data_t;
/* Span specific data */
typedef struct sngisdn_span_data {
ftdm_span_t *ftdm_span;
uint8_t link_id;
uint8_t switchtype;
uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
uint8_t cc_id;
uint8_t dchan_id;
uint8_t span_id;
uint8_t tei;
uint8_t keep_link_up;
uint8_t trace_flags;
} sngisdn_span_data_t;
/* dchan_data can have more than 1 span when running NFAS */
typedef struct sngisdn_dchan_data {
uint8_t num_spans;
sngisdn_span_data_t *spans[MAX_L1_LINKS+1];
uint16_t num_chans;
/* worst case for number of channel is when using NFAS, and NFAS is only used on T1,
so we can use MAX_SPANS_PER_NFAS_LINK*NUM_T1_CHANNELS_PER_SPAN instead of
MAX_SPANS_PER_NFAS_LINK*NUM_E1_CHANNELS_PER_SPAN
*/
/* Never seen NFAS on E1 yet, so use NUM_T1_CHANNELS_PER_SPAN */
/* b-channels are arranged by physical id's not logical */
sngisdn_chan_data_t *channels[MAX_SPANS_PER_NFAS_LINK*NUM_T1_CHANNELS_PER_SPAN];
}sngisdn_dchan_data_t;
typedef struct sngisdn_cc {
/* TODO: use flags instead of config_done and activation_done */
uint8_t config_done;
uint8_t activation_done;
uint8_t switchtype;
ftdm_trunk_type_t trunktype;
uint32_t last_suInstId;
ftdm_mutex_t *request_mutex;
sngisdn_chan_data_t *active_spInstIds[MAX_INSTID];
sngisdn_chan_data_t *active_suInstIds[MAX_INSTID];
}sngisdn_cc_t;
/* Global sngisdn data */
typedef struct ftdm_sngisdn_data {
uint8_t gen_config_done;
uint8_t num_cc; /* 1 ent per switchtype */
struct sngisdn_cc ccs[MAX_VARIANTS+1];
uint8_t num_dchan;
sngisdn_dchan_data_t dchans[MAX_L1_LINKS+1];
}ftdm_sngisdn_data_t;
typedef enum {
FLAG_RESET_RX = (1 << 0),
FLAG_RESET_TX = (1 << 1),
FLAG_REMOTE_REL = (1 << 2),
FLAG_LOCAL_REL = (1 << 3),
FLAG_REMOTE_ABORT = (1 << 4),
FLAG_LOCAL_ABORT = (1 << 4),
FLAG_GLARE = (1 << 5),
FLAG_INFID_RESUME = (1 << 17),
FLAG_INFID_PAUSED = (1 << 18),
FLAG_CKT_MN_BLOCK_RX = (1 << 19),
FLAG_CKT_MN_BLOCK_TX = (1 << 20),
FLAG_CKT_MN_UNBLK_RX = (1 << 21),
FLAG_CKT_MN_UNBLK_TX = (1 << 22),
FLAG_GRP_HW_BLOCK_RX = (1 << 23),
FLAG_GRP_HW_BLOCK_TX = (1 << 24),
FLAG_GRP_MN_BLOCK_RX = (1 << 25),
FLAG_GRP_MN_BLOCK_TX = (1 << 28),
FLAG_GRP_HW_UNBLK_RX = (1 << 27),
FLAG_GRP_HW_UNBLK_TX = (1 << 28),
FLAG_GRP_MN_UNBLK_RX = (1 << 29),
FLAG_GRP_MN_UNBLK_TX = (1 << 30)
FLAG_LOCAL_ABORT = (1 << 5),
FLAG_GLARE = (1 << 6),
FLAG_DELAYED_REL = (1 << 7),
FLAG_SENT_PROCEED = (1 << 8),
} sngisdn_flag_t;
@ -182,62 +94,222 @@ typedef enum {
SNGISDN_TRACE_Q931 = 2,
} sngisdn_tracetype_t;
typedef enum {
SNGISDN_OPT_DEFAULT = 0,
SNGISDN_OPT_TRUE = 1,
SNGISDN_OPT_FALSE = 2,
} sngisdn_opt_t;
#define sngisdn_set_flag(obj, flag) ((obj)->flags |= (flag))
#define sngisdn_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
#define sngisdn_test_flag(obj, flag) ((obj)->flags & flag)
#define sngisdn_set_trace_flag(obj, flag) ((obj)->trace_flags |= (flag))
#define sngisdn_clear_trace_flag(obj, flag) ((obj)->trace_flags &= ~(flag))
#define sngisdn_test_trace_flag(obj, flag) ((obj)->trace_flags & flag)
typedef enum {
SNGISDN_AVAIL_DOWN = 1,
SNGISDN_AVAIL_PWR_SAVING = 5,
SNGISDN_AVAIL_UP = 10,
} sngisdn_avail_t;
typedef enum {
SNGISDN_EVENT_CON_IND = 1,
SNGISDN_EVENT_CON_CFM,
SNGISDN_EVENT_CNST_IND,
SNGISDN_EVENT_DISC_IND,
SNGISDN_EVENT_REL_IND,
SNGISDN_EVENT_DAT_IND,
SNGISDN_EVENT_SSHL_IND,
SNGISDN_EVENT_SSHL_CFM,
SNGISDN_EVENT_RMRT_IND,
SNGISDN_EVENT_RMRT_CFM,
SNGISDN_EVENT_FLC_IND,
SNGISDN_EVENT_FAC_IND,
SNGISDN_EVENT_STA_CFM,
SNGISDN_EVENT_SRV_IND,
SNGISDN_EVENT_SRV_CFM,
SNGISDN_EVENT_RST_CFM,
SNGISDN_EVENT_RST_IND,
} ftdm_sngisdn_event_id_t;
typedef struct sngisdn_glare_data {
int16_t suId;
uint32_t suInstId;
uint32_t spInstId;
int16_t dChan;
ConEvnt setup;
uint8_t ces;
}sngisdn_glare_data_t;
/* Channel specific data */
typedef struct sngisdn_chan_data {
ftdm_channel_t *ftdmchan;
uint32_t flags;
uint8_t ces; /* used only for BRI, otherwise always 0 */
uint8_t dchan_id;
uint32_t suInstId; /* instance ID generated locally */
uint32_t spInstId; /* instance ID generated by stack */
uint8_t globalFlg;
sngisdn_glare_data_t glare;
} sngisdn_chan_data_t;
/* Span specific data */
typedef struct sngisdn_span_data {
ftdm_span_t *ftdm_span;
uint8_t link_id;
uint8_t switchtype;
uint8_t signalling; /* SNGISDN_SIGNALING_CPE or SNGISDN_SIGNALING_NET */
uint8_t cc_id;
uint8_t dchan_id;
uint8_t span_id;
uint8_t tei;
uint8_t min_digits;
uint8_t trace_flags; /* TODO: change to flags, so we can use ftdm_test_flag etc.. */
uint8_t overlap_dial;
uint8_t setup_arb;
uint8_t facility;
ftdm_sched_t *sched;
ftdm_queue_t *event_queue;
} sngisdn_span_data_t;
typedef struct sngisdn_event_data {
int16_t suId;
int16_t dChan;
uint32_t suInstId;
uint32_t spInstId;
uint8_t ces;
uint8_t action;
uint8_t evntType;
sngisdn_chan_data_t *sngisdn_info;
sngisdn_span_data_t *signal_data;
ftdm_sngisdn_event_id_t event_id;
union
{
ConEvnt conEvnt;
CnStEvnt cnStEvnt;
DiscEvnt discEvnt;
RelEvnt relEvnt;
InfoEvnt infoEvnt;
SsHlEvnt ssHlEvnt;
RmRtEvnt rmRtEvnt;
StaEvnt staEvnt;
FacEvnt facEvnt;
Srv srvEvnt;
Rst rstEvnt;
}event;
} sngisdn_event_data_t;
/* dchan_data can have more than 1 span when running NFAS */
typedef struct sngisdn_dchan_data {
uint8_t num_spans;
sngisdn_span_data_t *spans[MAX_L1_LINKS+1];
uint16_t num_chans;
/* worst case for number of channel is when using NFAS, and NFAS is only used on T1,
so we can use MAX_SPANS_PER_NFAS_LINK*NUM_T1_CHANNELS_PER_SPAN instead of
MAX_SPANS_PER_NFAS_LINK*NUM_E1_CHANNELS_PER_SPAN
*/
/* Never seen NFAS on E1 yet, so use NUM_T1_CHANNELS_PER_SPAN */
/* b-channels are arranged by physical id's not logical */
sngisdn_chan_data_t *channels[MAX_SPANS_PER_NFAS_LINK*NUM_T1_CHANNELS_PER_SPAN];
}sngisdn_dchan_data_t;
typedef struct sngisdn_cc {
/* TODO: use flags instead of config_done and activation_done */
uint8_t config_done;
uint8_t activation_done;
uint8_t switchtype;
ftdm_trunk_type_t trunktype;
uint32_t last_suInstId;
ftdm_mutex_t *mutex;
sngisdn_chan_data_t *active_spInstIds[MAX_INSTID];
sngisdn_chan_data_t *active_suInstIds[MAX_INSTID];
}sngisdn_cc_t;
/* Global sngisdn data */
typedef struct ftdm_sngisdn_data {
uint8_t gen_config_done;
uint8_t num_cc; /* 1 ent per switchtype */
struct sngisdn_cc ccs[MAX_VARIANTS+1];
uint8_t num_dchan;
sngisdn_dchan_data_t dchans[MAX_L1_LINKS+1];
}ftdm_sngisdn_data_t;
/* TODO implement these 2 functions */
#define ISDN_FUNC_TRACE_ENTER(a)
#define ISDN_FUNC_TRACE_EXIT(a)
/* Global Structs */
extern ftdm_sngisdn_data_t g_sngisdn_data;
/* Configuration functions */
ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span);
/* Support functions */
uint32_t get_unique_suInstId(uint8_t cc_id);
void clear_call_data(sngisdn_chan_data_t *sngisdn_info);
void clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info);
void stack_hdr_init(Header *hdr);
void stack_pst_init(Pst *pst);
ftdm_status_t get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data);
ftdm_status_t get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data);
ftdm_status_t check_for_state_change(ftdm_channel_t *ftdmchan);
ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail);
/* Outbound Call Control functions */
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan);
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan);
void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
void sngisdn_snd_alert(ftdm_channel_t *ftdmchan);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
void sngisdn_snd_reset(ftdm_channel_t *ftdmchan);
void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan);
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan);
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan);
/* Inbound Call Control functions */
void sngisdn_rcv_con_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, signed short dChan, uint8_t ces);
void sngisdn_rcv_con_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, signed short dChan, uint8_t ces);
void sngisdn_rcv_cnst_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, signed short dChan, uint8_t ces);
void sngisdn_rcv_disc_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
void sngisdn_rcv_rel_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
void sngisdn_rcv_dat_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
void sngisdn_rcv_sshl_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
void sngisdn_rcv_sshl_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
void sngisdn_rcv_rmrt_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
void sngisdn_rcv_rmrt_cfm (signed short suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
void sngisdn_rcv_flc_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
void sngisdn_rcv_fac_ind (signed short suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, signed short dChan, uint8_t ces);
void sngisdn_rcv_sta_cfm ( signed short suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
void sngisdn_rcv_srv_ind ( signed short suId, Srv *srvEvnt, signed short dChan, uint8_t ces);
void sngisdn_rcv_srv_cfm ( signed short suId, Srv *srvEvnt, signed short dChan, uint8_t ces);
void sngisdn_rcv_rst_cfm ( signed short suId, Rst *rstEvnt, signed short dChan, uint8_t ces, uint8_t evtType);
void sngisdn_rcv_rst_ind ( signed short suId, Rst *rstEvnt, signed short dChan, uint8_t ces, uint8_t evtType);
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt);
void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt);
void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt);
void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action);
void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action);
void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces);
void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt);
void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces);
void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
void sngisdn_rcv_rst_ind ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType);
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_dat_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_sshl_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_sshl_cfm (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_rmrt_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_rmrt_cfm (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_srv_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event);
void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event);
void sngisdn_rcv_phy_ind(SuId suId, Reason reason);
void sngisdn_rcv_q921_ind(BdMngmt *status);
@ -246,14 +318,38 @@ void sngisdn_rcv_q931_ind(InMngmt *status);
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf);
void sngisdn_rcv_cc_ind(CcMngmt *status);
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...);
void sngisdn_rcv_sng_assert(char *message);
static __inline__ uint32_t sngisdn_test_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag)
{
return (uint32_t) sngisdn_info->flags & flag;
}
static __inline__ void sngisdn_clear_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag)
{
sngisdn_info->flags &= ~flag;
}
static __inline__ void sngisdn_set_flag(sngisdn_chan_data_t *sngisdn_info, sngisdn_flag_t flag)
{
sngisdn_info->flags |= flag;
}
#define sngisdn_set_trace_flag(obj, flag) ((obj)->trace_flags |= (flag))
#define sngisdn_clear_trace_flag(obj, flag) ((obj)->trace_flags &= ~(flag))
#define sngisdn_test_trace_flag(obj, flag) ((obj)->trace_flags & flag)
void handle_sng_log(uint8_t level, char *fmt,...);
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status);
void sngisdn_delayed_release(void* p_sngisdn_info);
void sngisdn_delayed_connect(void* p_sngisdn_info);
void sngisdn_delayed_disconnect(void* p_sngisdn_info);
/* Stack management functions */
ftdm_status_t sng_isdn_stack_cfg(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span);
#endif /* __FTMOD_SNG_ISDN_H__ */

View File

@ -47,7 +47,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
switch(span->trunk_type) {
case FTDM_TRUNK_T1:
if (!strcasecmp(switch_name, "ni2")) {
if (!strcasecmp(switch_name, "ni2") ||
!strcasecmp(switch_name, "national")) {
signal_data->switchtype = SNGISDN_SWITCH_NI2;
} else if (!strcasecmp(switch_name, "5ess")) {
signal_data->switchtype = SNGISDN_SWITCH_5ESS;
@ -127,6 +128,7 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
dchan_data->num_chans++;
}
return FTDM_SUCCESS;
}
@ -144,7 +146,7 @@ ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
signal_data->signalling = SNGISDN_SIGNALING_CPE;
} else {
ftdm_log(FTDM_LOG_ERROR, "Unsupported signalling %s\n", signalling);
ftdm_log(FTDM_LOG_ERROR, "Unsupported signalling/interface %s\n", signalling);
return FTDM_FAIL;
}
return FTDM_SUCCESS;
@ -156,10 +158,29 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
const char *var, *val;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
/* Set defaults here */
signal_data->keep_link_up = 1;
signal_data->tei = 0;
signal_data->min_digits = 8;
signal_data->overlap_dial = SNGISDN_OPT_DEFAULT;
signal_data->setup_arb = SNGISDN_OPT_DEFAULT;
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
ftdm_span_set_npi("unknown", &span->default_caller_data.dnis.plan);
ftdm_span_set_ton("unknown", &span->default_caller_data.dnis.type);
ftdm_span_set_npi("unknown", &span->default_caller_data.cid_num.plan);
ftdm_span_set_ton("unknown", &span->default_caller_data.cid_num.type);
ftdm_span_set_npi("unknown", &span->default_caller_data.rdnis.plan);
ftdm_span_set_ton("unknown", &span->default_caller_data.rdnis.type);
} else {
ftdm_span_set_npi("e164", &span->default_caller_data.dnis.plan);
ftdm_span_set_ton("national", &span->default_caller_data.dnis.type);
ftdm_span_set_npi("e164", &span->default_caller_data.cid_num.plan);
ftdm_span_set_ton("national", &span->default_caller_data.cid_num.type);
ftdm_span_set_npi("e164", &span->default_caller_data.rdnis.plan);
ftdm_span_set_ton("national", &span->default_caller_data.rdnis.type);
}
for (paramindex = 0; ftdm_parameters[paramindex].var; paramindex++) {
ftdm_log(FTDM_LOG_DEBUG, "Sangoma ISDN key=value, %s=%s\n", ftdm_parameters[paramindex].var, ftdm_parameters[paramindex].val);
var = ftdm_parameters[paramindex].var;
@ -169,7 +190,8 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
if (parse_switchtype(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
} else if (!strcasecmp(var, "signalling")) {
} else if (!strcasecmp(var, "signalling") ||
!strcasecmp(var, "interface")) {
if (parse_signalling(val, span) != FTDM_SUCCESS) {
return FTDM_FAIL;
}
@ -180,15 +202,44 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
return FTDM_FAIL;
}
signal_data->tei = tei;
} else if (!strcasecmp(var, "keep_link_up")) {
} else if (!strcasecmp(var, "overlap")) {
if (!strcasecmp(val, "yes")) {
signal_data->keep_link_up = 1;
signal_data->overlap_dial = SNGISDN_OPT_TRUE;
} else if (!strcasecmp(val, "no")) {
signal_data->keep_link_up = 0;
signal_data->overlap_dial = SNGISDN_OPT_FALSE;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid keep_link_up value, valid values are (yes/no)");
return FTDM_FAIL;
ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
}
} else if (!strcasecmp(var, "setup arbitration")) {
if (!strcasecmp(val, "yes")) {
signal_data->setup_arb = SNGISDN_OPT_TRUE;
} else if (!strcasecmp(val, "no")) {
signal_data->setup_arb = SNGISDN_OPT_FALSE;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
}
} else if (!strcasecmp(var, "facility")) {
if (!strcasecmp(val, "yes")) {
signal_data->facility = SNGISDN_OPT_TRUE;
} else if (!strcasecmp(val, "no")) {
signal_data->facility = SNGISDN_OPT_FALSE;
} else {
ftdm_log(FTDM_LOG_ERROR, "Invalid value for parameter:%s:%s\n", var, val);
}
} else if (!strcasecmp(var, "min_digits")) {
signal_data->min_digits = atoi(val);
} else if (!strcasecmp(var, "outbound-called-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.dnis.type);
} else if (!strcasecmp(var, "outbound-called-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.dnis.plan);
} else if (!strcasecmp(var, "outbound-calling-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.cid_num.type);
} else if (!strcasecmp(var, "outbound-calling-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.cid_num.plan);
} else if (!strcasecmp(var, "outbound-rdnis-ton")) {
ftdm_span_set_ton(val, &span->default_caller_data.rdnis.type);
} else if (!strcasecmp(var, "outbound-rdnis-npi")) {
ftdm_span_set_npi(val, &span->default_caller_data.rdnis.plan);
} else {
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}

View File

@ -223,17 +223,17 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
switch(span->trunk_type) {
case FTDM_TRUNK_E1:
cfg.t.cfg.s.l1PSAP.chan = 16;
cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_PRI;
cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI;
break;
case FTDM_TRUNK_T1:
case FTDM_TRUNK_J1:
cfg.t.cfg.s.l1PSAP.chan = 24;
cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_PRI;
cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI;
break;
case FTDM_TRUNK_BRI:
case FTDM_TRUNK_BRI_PTMP:
cfg.t.cfg.s.l1PSAP.chan = 3;
cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_BRI;
cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_BRI;
break;
default:
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunk type %d\n", span->name, span->trunk_type);
@ -280,10 +280,10 @@ ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
cfg.t.cfg.s.bdGen.nmbASPLnks = MAX_L1_LINKS+1;
#ifdef LAPD_3_4
cfg.t.cfg.s.bdGen.timeRes = 10; /* timer resolution */
cfg.t.cfg.s.bdGen.timeRes = 100; /* timer resolution = 1 sec */
#endif
cfg.t.cfg.s.bdGen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */
cfg.t.cfg.s.bdGen.poolTrLower = POOL_LW_TR; /* lower pool threshold */
cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */
cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */
if (sng_isdn_q921_config(&pst, &cfg)) {
return FTDM_FAIL;
@ -315,9 +315,9 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.lnkNmb = signal_data->link_id;
cfg.t.cfg.s.bdMSAP.maxOutsFrms = 2; /* MAC window */
cfg.t.cfg.s.bdMSAP.tQUpperTrs = 16; /* Tx Queue Upper Threshold */
cfg.t.cfg.s.bdMSAP.tQLowerTrs = 8; /* Tx Queue Lower Threshold */
cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24; /* MAC window */
cfg.t.cfg.s.bdMSAP.tQUpperTrs = 32; /* Tx Queue Upper Threshold */
cfg.t.cfg.s.bdMSAP.tQLowerTrs = 24; /* Tx Queue Lower Threshold */
cfg.t.cfg.s.bdMSAP.selector = 0; /* Selector 0 */
/* TODO: check if bdMSAP parameters can be initialized by calling stack_pst_init */
cfg.t.cfg.s.bdMSAP.mem.region = S_REG; /* Memory region */
@ -327,8 +327,8 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.dstProcId = SFndProcId(); /* destination proc id */
cfg.t.cfg.s.bdMSAP.dstEnt = ENTL1; /* entity */
cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */
cfg.t.cfg.s.bdMSAP.t201Tmr = 5; /* T201 */
cfg.t.cfg.s.bdMSAP.t202Tmr = 200; /* T202 */
cfg.t.cfg.s.bdMSAP.t201Tmr = 1; /* T201 - should be equal to t200Tmr */
cfg.t.cfg.s.bdMSAP.t202Tmr = 2; /* T202 */
cfg.t.cfg.s.bdMSAP.bndRetryCnt = 2; /* bind retry counter */
cfg.t.cfg.s.bdMSAP.tIntTmr = 200; /* bind retry timer */
cfg.t.cfg.s.bdMSAP.n202 = 3; /* N202 */
@ -341,7 +341,21 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.kpL1Up = TRUE; /* flag to keep l1 up or not */
}
cfg.t.cfg.s.bdMSAP.type = sng_isdn_stack_switchtype(signal_data->switchtype);
switch(signal_data->switchtype) {
case SNGISDN_SWITCH_NI2:
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
case SNGISDN_SWITCH_DMS100:
cfg.t.cfg.s.bdMSAP.type = SW_NI2;
break;
case SNGISDN_SWITCH_INSNET:
cfg.t.cfg.s.bdMSAP.type = SW_CCITT;
break;
case SNGISDN_SWITCH_EUROISDN:
case SNGISDN_SWITCH_QSIG:
cfg.t.cfg.s.bdMSAP.type = SW_ETSI;
break;
}
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
cfg.t.cfg.s.bdMSAP.teiChkTmr = 20; /* Tei check timer */
@ -357,6 +371,12 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE; /* set up arbitration */
}
/* Overwrite setUpArb value if user forced it */
if (signal_data->setup_arb == SNGISDN_OPT_TRUE) {
cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE;
} else if (signal_data->setup_arb == SNGISDN_OPT_FALSE) {
cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE;
}
if (sng_isdn_q921_config(&pst, &cfg)) {
return FTDM_FAIL;
@ -389,11 +409,18 @@ ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t managemen
cfg.t.cfg.s.bdDLSAP.lnkNmb = signal_data->link_id;
cfg.t.cfg.s.bdDLSAP.n201 = 1028; /* n201 */
cfg.t.cfg.s.bdDLSAP.k = 7; /* k */
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP ||
span->trunk_type == FTDM_TRUNK_BRI) {
cfg.t.cfg.s.bdDLSAP.k = 1; /* Based on q.921 recommendations */
} else {
cfg.t.cfg.s.bdDLSAP.k = 7; /* k */
}
cfg.t.cfg.s.bdDLSAP.n200 = 3; /* n200 */
cfg.t.cfg.s.bdDLSAP.congTmr = 300; /* congestion timer */
cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */
cfg.t.cfg.s.bdDLSAP.t203Tmr = 3; /* t3 changed from 50 */
cfg.t.cfg.s.bdDLSAP.t200Tmr = 1; /* t1 changed from 25 */
cfg.t.cfg.s.bdDLSAP.t203Tmr = 10; /* t3 changed from 50 */
cfg.t.cfg.s.bdDLSAP.mod = 128; /* modulo */
cfg.t.cfg.s.bdDLSAP.selector = 0; /* Selector 0 */
cfg.t.cfg.s.bdDLSAP.mem.region = S_REG; /* Memory region */
@ -483,7 +510,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_gen(void)
/* upper pool threshold */
cfg.t.cfg.s.inGen.poolTrUpper = INGEN_POOL_UP_TR;
/* time resolution */
cfg.t.cfg.s.inGen.timeRes = 10;
cfg.t.cfg.s.inGen.timeRes = 100; /* timer resolution = 1 sec */
cfg.t.cfg.s.inGen.sm.dstEnt = ENTSM;
@ -594,6 +621,12 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.tCbId = signal_data->cc_id;
if (signal_data->facility == SNGISDN_OPT_TRUE) {
cfg.t.cfg.s.inDLSAP.facilityHandling = IN_FACILITY_STANDRD;
} else {
cfg.t.cfg.s.inDLSAP.facilityHandling = 0;
}
/* TODO : NFAS configuration */
cfg.t.cfg.s.inDLSAP.nfasInt = FALSE; /* pass this later */
@ -687,38 +720,46 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.cndSubsc = TRUE; /* calling adddress delivery service subscription */
/* TODO: Fill in these timers with proper values - eventually pass them */
cfg.t.cfg.s.inDLSAP.tmr.t301.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t301.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t302.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t302.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t303.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t303.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t301.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t301.val = 180;
cfg.t.cfg.s.inDLSAP.tmr.t302.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t302.val = 15;
cfg.t.cfg.s.inDLSAP.tmr.t303.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t303.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t304.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t304.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t304.val = 30;
cfg.t.cfg.s.inDLSAP.tmr.t305.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t305.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t305.val = 30;
cfg.t.cfg.s.inDLSAP.tmr.t306.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t306.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t307.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t307.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t308.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t308.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t312.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t308.val = 4;
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 10;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t312.val = cfg.t.cfg.s.inDLSAP.tmr.t303.val+2;
} else {
cfg.t.cfg.s.inDLSAP.tmr.t310.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t310.val = 120;
cfg.t.cfg.s.inDLSAP.tmr.t312.enb = FALSE;
}
cfg.t.cfg.s.inDLSAP.tmr.t313.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t313.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t313.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t316.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t316.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t316c.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t316.val = 120;
cfg.t.cfg.s.inDLSAP.tmr.t316c.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t316c.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t318.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t318.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t319.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t319.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t318.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t318.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t319.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t319.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t322.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t322.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.t322.val = 4;
cfg.t.cfg.s.inDLSAP.tmr.t332.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t332.val = 35;
cfg.t.cfg.s.inDLSAP.tmr.tRst.enb = TRUE;
@ -893,8 +934,9 @@ ftdm_status_t sng_isdn_stack_cfg_cc_gen(void)
stack_pst_init(&cfg.t.cfg.s.ccGenCfg.smPst);
cfg.t.cfg.s.ccGenCfg.smPst.dstEnt = ENTSM;
cfg.t.cfg.s.ccGenCfg.poolTrLower = 2;
cfg.t.cfg.s.ccGenCfg.poolTrUpper = 4;
cfg.t.cfg.s.ccGenCfg.poolTrUpper = 2;
cfg.t.cfg.s.ccGenCfg.poolTrLower = 1;
cfg.t.cfg.s.ccGenCfg.nmbSaps = MAX_VARIANTS+1; /* Set to number of variants + 1 */
if (sng_isdn_cc_config(&pst, &cfg)) {
@ -1013,7 +1055,7 @@ uint8_t sng_isdn_stack_switchtype(sngisdn_switchtype_t switchtype)
case SNGISDN_SWITCH_QSIG:
return SW_QSIG;
case SNGISDN_SWITCH_INSNET:
return SW_QSIG;
return SW_INSNET;
case SNGISDN_SWITCH_INVALID:
ftdm_log(FTDM_LOG_ERROR, "%s:Invalid switchtype:%d\n", switchtype);
break;

View File

@ -46,8 +46,11 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_status_t sng_isdn_cntrl_q931(ftdm_span_t *span, uint8_t action, uint8_t subaction);
ftdm_status_t sng_isdn_cntrl_q921(ftdm_span_t *span, uint8_t action, uint8_t subaction);
extern ftdm_sngisdn_data_t g_sngisdn_data;
ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span)
{
@ -77,6 +80,12 @@ ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span)
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span)
{
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span)
{
@ -302,6 +311,7 @@ void stack_resp_hdr_init(Header *hdr)
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -0,0 +1,978 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* David Yat Sin <dyatsin@sangoma.com>
* 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 "ftmod_sangoma_isdn.h"
extern ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
extern ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
extern ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
extern ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display);
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ConEvnt *conEvnt = &sngisdn_event->event.conEvnt;
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Processing SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE) ||
ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP but channel is in USE, saving call for later processing\n");
/* the flag the channel as having a collision */
sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
/* save the SETUP for processing once the channel has gone to DOWN */
memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
sngisdn_info->glare.suId = suId;
sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
sngisdn_info->glare.spInstId = spInstId;
sngisdn_info->glare.dChan = dChan;
sngisdn_info->glare.ces = ces;
break;
}
sngisdn_info->suInstId = get_unique_suInstId(suId);
sngisdn_info->spInstId = spInstId;
/* If this is a glared call that was previously saved, we moved
all the info to the current call, so clear the glared saved data */
if (sngisdn_info->glare.spInstId == spInstId) {
clear_call_glare_data(sngisdn_info);
}
ftdm_assert(g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] == NULL, "Con Ind on busy spInstId");
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND);
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
signal_data->signalling == SNGISDN_SIGNALING_NET) {
sngisdn_info->ces = ces;
}
/* try to open the channel */
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
break;
}
/* Fill in call information */
cpy_calling_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
cpy_calling_name_from_sngisdn(&ftdmchan->caller_data, &conEvnt->display);
if (signal_data->switchtype == SNGISDN_SWITCH_NI2) {
if (conEvnt->shift11.eh.pres && conEvnt->ni2OctStr.eh.pres) {
if (conEvnt->ni2OctStr.str.len == 4 && conEvnt->ni2OctStr.str.val[0] == 0x37) {
snprintf(ftdmchan->caller_data.aniII, 5, "%.2d", conEvnt->ni2OctStr.str.val[3]);
}
}
if (conEvnt->facilityStr.eh.pres) {
/* Verify whether the Caller Name will come in a subsequent FACILITY message */
uint16_t ret_val;
uint8_t facility_str[255];
char retrieved_str[255];
memcpy(facility_str, (uint8_t*)&conEvnt->facilityStr.facilityStr.val, conEvnt->facilityStr.facilityStr.len);
ret_val = sng_isdn_retrieve_facility_caller_name(facility_str, conEvnt->facilityStr.facilityStr.len, retrieved_str);
/*
return values for "sng_isdn_retrieve_facility_information_following":
If there will be no information following, or fails to decode IE, returns -1
If there will be no information following, but current FACILITY IE contains a caller name, returns 0
If there will be information following, returns 1
*/
if (ret_val == 1) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID);
break;
} else if (ret_val == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
}
}
}
if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
} else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
}
break;
case FTDM_CHANNEL_STATE_TERMINATING:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in TERMINATING state, saving SETUP info for later processing\n");
ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare");
sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
/* save the SETUP for processing once the channel has gone to DOWN */
memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
sngisdn_info->glare.suId = suId;
sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
sngisdn_info->glare.spInstId = spInstId;
sngisdn_info->glare.dChan = dChan;
sngisdn_info->glare.ces = ces;
/* We need to register the spInstId in case we get a release for that call while it is still stored in sngisdn_info->glare */
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
break;
case FTDM_CHANNEL_STATE_DIALING: /* glare */
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
/* Save inbound call info so we can send a RELEASE when this channel goes to a different state */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP in DIALING state, rejecting inbound call\n");
sngisdn_set_flag(sngisdn_info, FLAG_DELAYED_REL);
sngisdn_info->glare.suId = suId;
sngisdn_info->glare.suInstId = get_unique_suInstId(suId);
sngisdn_info->glare.spInstId = spInstId;
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
sngisdn_info->glare.dChan = dChan;
sngisdn_info->glare.ces = ces;
ftdmchan->caller_data.hangup_cause = 0x2C; /* Channel requested not available */
ftdm_sched_timer(signal_data->sched, "delayed_release", 1, sngisdn_delayed_release, (void*) sngisdn_info, NULL);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Processing SETUP in DIALING state, saving SETUP info for later processing\n");
/* the flag the channel as having a collision */
ftdm_assert(!sngisdn_test_flag(sngisdn_info, FLAG_GLARE), "Trying to save GLARE info, but we already had a glare");
sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
/* save the SETUP for processing once the channel has gone to DOWN */
memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
sngisdn_info->glare.suId = suId;
sngisdn_info->glare.suInstId = suInstId; /* Do not generate a suInstId now, we will generate when glared call gets extracted */
sngisdn_info->glare.spInstId = spInstId;
sngisdn_info->glare.dChan = dChan;
sngisdn_info->glare.ces = ces;
/* We need to register the spInstId in case we get a release for that call while it is still stored in sngisdn_info->glare */
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
}
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/* Remote side transmit a CONNECT or CONNECT ACK */
void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
uint8_t ces = sngisdn_event->ces;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
/* Function does not require any info from conStEvnt struct for now */
/* CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; */
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces);
if (!sngisdn_info->spInstId) {
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
}
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
if(sngisdn_info->ces == CES_MNGMNT) {
/* We assign the call to the first TE */
sngisdn_info->ces = ces;
} else {
/* We already assigned this call, do nothing */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_DIALING:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
/* Start the disconnect procedure */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
}
} else {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* This is the only valid state we should get a CONNECT ACK on */
/* do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
/* Start the disconnect procedure */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
}
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
uint8_t ces = sngisdn_event->ces;
uint8_t evntType = sngisdn_event->evntType;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt;
if (!sngisdn_info->spInstId) {
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
}
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n",
(evntType == MI_ALERTING)?"ALERT":
(evntType == MI_CALLPROC)?"PROCEED":
(evntType == MI_PROGRESS)?"PROGRESS":
(evntType == MI_SETUPACK)?"SETUP ACK":
(evntType == MI_INFO)?"INFO":"UNKNOWN",
suId, suInstId, spInstId, ces);
switch(evntType) {
case MI_ALERTING:
case MI_CALLPROC:
case MI_PROGRESS:
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_DIALING:
if (evntType == MI_PROGRESS) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
if (evntType == MI_PROGRESS) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* We are already in progress media, we can't go to any higher state except up */
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing ALERT/PROCEED/PROGRESS in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
/* Start the disconnect procedure */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
}
break;
case MI_SETUPACK:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Processing SETUP_ACK, but overlap sending not implemented (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
break;
case MI_INFO:
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing INFO (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
if (cnStEvnt->cdPtyNmb.eh.pres) {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_COLLECT:
{
ftdm_size_t min_digits = ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->min_digits;
ftdm_size_t num_digits;
cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &cnStEvnt->cdPtyNmb);
num_digits = strlen(ftdmchan->caller_data.dnis.digits);
if (cnStEvnt->sndCmplt.eh.pres || num_digits >= min_digits) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "received %d of %d digits\n", num_digits, min_digits);
}
}
break;
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Receiving more digits %s, but we already proceeded with call\n", cnStEvnt->cdPtyNmb.nmbDigits.val);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "\n", suId, suInstId, spInstId);
break;
}
}
break;
default:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Unhandled STATUS event\n");
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_disc_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
DiscEvnt *discEvnt = &sngisdn_event->event.discEvnt;
if (!sngisdn_info->spInstId) {
ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex);
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex);
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n");
ftdmchan->caller_data.hangup_cause = 0;
}
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_GET_CALLERID:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* somehow we are in down, nothing we can do locally */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT but we are in DOWN state\n");
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* This is a race condition. We just sent a DISCONNECT, on this channel */
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
/* start reset procedure */
/* Start the release procedure */
ftdm_set_flag(sngisdn_info, FLAG_REMOTE_REL);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_rel_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
RelEvnt *relEvnt = &sngisdn_event->event.relEvnt;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
if ((suInstId && (sngisdn_info->glare.suInstId == suInstId)) ||
(spInstId && (sngisdn_info->glare.spInstId == spInstId))) {
/* This hangup is for a glared saved call */
ftdm_clear_flag(sngisdn_info, FLAG_DELAYED_REL);
clear_call_glare_data(sngisdn_info);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/* 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(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* do nothing, just drop the message */
break;
case FTDM_CHANNEL_STATE_DIALING:
/* Remote side rejected our SETUP message on outbound call */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN);
}
/* fall-through */
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
case FTDM_CHANNEL_STATE_RING:
/* If we previously had a glare on this channel,
this RELEASE could be for the previous call. Confirm whether call_data has
not changed while we were waiting for ftdmchan->mutex by comparing suInstId's */
if (((sngisdn_chan_data_t*)ftdmchan->call_data)->suInstId == suInstId ||
((sngisdn_chan_data_t*)ftdmchan->call_data)->spInstId == spInstId) {
if (relEvnt->causeDgn[0].eh.pres && relEvnt->causeDgn[0].causeVal.pres) {
ftdmchan->caller_data.hangup_cause = relEvnt->causeDgn[0].causeVal.val;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "cause:%d\n", ftdmchan->caller_data.hangup_cause);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "RELEASE COMPLETE did not have a cause code\n");
ftdmchan->caller_data.hangup_cause = 0;
}
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "RELEASE was for previous call (suInstId:%u spInstId:%u)\n", suInstId, spInstId);
}
break;
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_GET_CALLERID:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
break;
case FTDM_CHANNEL_STATE_TERMINATING:
if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE) &&
sngisdn_info->glare.suInstId != suInstId) {
/* This release if for the outbound call that we already started clearing */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Received RELEASE for local glared call\n");
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received release before we could clear local call\n");
/* FS core took too long to respond to the SIG STOP event */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
/* set abort flag so that we do not transmit another release complete on this channel once FS core is done */
}
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_dat_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
/* Function does not require any info from infoEvnt struct for now */
/* InfoEvnt *infoEvnt = &sngisdn_event->event.infoEvnt; */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing DATA IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_sshl_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
/* Function does not require any info from ssHlEvnt struct for now */
/* SsHlEvnt *ssHlEvnt = &sngisdn_event->event.ssHlEvnt; */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_sshl_cfm (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
/* Function does not require any info from ssHlEvnt struct for now */
/* SsHlEvnt *ssHlEvnt = &sngisdn_event->event.ssHlEvnt; */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_rmrt_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
/* Function does not require any info from ssHlEvnt struct for now */
/* RmRtEvnt *rmRtEvnt = &sngisdn_event->event.rmRtEvnt; */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RESUME/RETRIEVE IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_rmrt_cfm (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
/* Function does not require any info from ssHlEvnt struct for now */
/* RmRtEvnt *rmRtEvnt = &sngisdn_event->event.rmRtEvnt; */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
/* Function does not require any info from ssHlEvnt struct for now */
/* StaEvnt *staEvnt = &sngisdn_event->event.staEvnt; */
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
FacEvnt *facEvnt = &sngisdn_event->event.facEvnt;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_GET_CALLERID:
/* Update the caller ID Name */
#if 1
if (facEvnt->facElmt.facStr.pres) {
uint8_t facility_str[255];
memcpy(facility_str, (uint8_t*)&facEvnt->facElmt.facStr.val, facEvnt->facElmt.facStr.len);
char retrieved_str[255];
if (sng_isdn_retrieve_facility_caller_name(facility_str, facEvnt->facElmt.facStr.len, retrieved_str) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n");
}
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "DYDBG Name is:%s\n", retrieved_str);
}
#endif
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
break;
default:
/* We do not support other FACILITY types for now, so do nothing */
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
uint32_t suInstId = sngisdn_event->suInstId;
uint32_t spInstId = sngisdn_event->spInstId;
sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
StaEvnt *staEvnt = &sngisdn_event->event.staEvnt;
uint8_t call_state = 0;
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
call_state = staEvnt->callSte.callGlblSte.val;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Processing STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n");
if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) {
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
call_state = staEvnt->callSte.callGlblSte.val;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received STATUS without call state\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
switch (staEvnt->causeDgn[0].causeVal.val) {
case FTDM_CAUSE_RESPONSE_TO_STATUS_ENQUIRY:
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Status Check OK:%d", call_state);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
case FTDM_CAUSE_WRONG_CALL_STATE:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Message incompatible with call state (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
break;
case FTDM_CAUSE_RECOVERY_ON_TIMER_EXPIRE:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Recovery on timer expire (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "STATUS CONFIRM (call_state:%d channel-state:%s cause:%d) (suId:%u suInstId:%u spInstId:%u)\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val, suId, suInstId, spInstId);
break;
}
/* Section 4.3.30 from INT Interface - Service Definition */
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
switch(call_state) {
/* Sere ITU-T Q931 for definition of call states */
case 0: /* Remote switch thinks there are no calls on this channel */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_UP:
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_TERMINATING:
/* We are in the process of clearing local states,
just make sure we will not send any messages to remote switch */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
break;
case FTDM_CHANNEL_STATE_HANGUP:
/* This cannot happen, state_advance always sets
ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
and we called check_for_state_change earlier so something is very wrong here!!! */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We were waiting for remote switch to send RELEASE COMPLETE
but this will not happen, so just clear local state */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* If our local state is down as well, then there is nothing to do */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 1:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* Remote side is still waiting for our CONNECT message */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
break;
}
/* Fall-through */
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 2: /* overlap sending/receiving */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_COLLECT:
/* T302 Timeout reached */
/* Send the call to user, and see if they accept it */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T302 Timer expired, proceeding with call\n");
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING);
break;
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Remote switch expecting OVERLAP receive, but we are already PROCEEDING\n");
sngisdn_snd_disconnect(ftdmchan);
break;
case FTDM_CHANNEL_STATE_DOWN:
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We hung up locally, but remote switch doesn't know send disconnect again*/
sngisdn_snd_disconnect(ftdmchan);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 3:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* Remote side is still waiting for our CONNECT message */
if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_connect", 1, sngisdn_delayed_connect, (void*) sngisdn_info, NULL);
break;
}
/* Fall-through */
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 8: /* Remote switch is in "Connect Request state" */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* This is ok. We sent a Connect, and we are waiting for a connect ack */
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We hung up locally, but remote switch doesn't know send disconnect again*/
sngisdn_snd_disconnect(ftdmchan);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 10: /* Remote switch is in active state */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* This is ok, they are in active state and we are in active state */
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We sent a disconnect message, but remote side missed it ? */
ftdm_sched_timer(((sngisdn_span_data_t*)ftdmchan->span->signal_data)->sched, "delayed_disconnect", 1, sngisdn_delayed_disconnect, (void*) sngisdn_info, NULL);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 9:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 22:
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* Stack is in the process of clearing the call*/
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* Do nothing as we will get a RELEASE COMPLETE */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
//ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
//ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_srv_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
/* Function does not require any info from ssHlEvnt struct for now */
/*Srv *srvEvnt = &sngisdn_event->event.srvEvnt;*/
ftdm_log(FTDM_LOG_DEBUG, "Processing SERVICE IND (suId:%u dChan:%d ces:%d)\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_srv_cfm (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
/* Function does not require any info from ssHlEvnt struct for now */
/*Srv *srvEvnt = &sngisdn_event->event.srvEvnt;*/
ftdm_log(FTDM_LOG_DEBUG, "Processing SERVICE CFM (suId:%u dChan:%d ces:%d)\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
uint8_t evntType = sngisdn_event->evntType;
/* Function does not require any info from ssHlEvnt struct for now */
/*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d type:%d)\n", suId, dChan, ces, evntType);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
uint8_t evntType = sngisdn_event->evntType;
/* Function does not require any info from ssHlEvnt struct for now */
/*Rst *rstEvnt = &sngisdn_event->event.rstEvnt;*/
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART CFM (suId:%u dChan:%d ces:%d %s)\n", suId, dChan, ces,
(evntType == IN_LNK_DWN)?"LNK_DOWN":
(evntType == IN_LNK_UP)?"LNK_UP":
(evntType == IN_INDCHAN)?"b-channel":
(evntType == IN_LNK_DWN_DM_RLS)?"Nfas service procedures":
(evntType == IN_SWCHD_BU_DCHAN)?"NFAS switchover to backup":"Unknown");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}

View File

@ -1,935 +0,0 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* David Yat Sin <davidy@sangoma.com>
* 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 "ftmod_sangoma_isdn.h"
extern ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
extern ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
extern ftdm_status_t cpy_called_name_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
extern ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt);
extern void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
extern void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
extern void get_memory_info(void);
extern ftdm_sngisdn_data_t g_sngisdn_data;
#define MAX_DECODE_STR_LEN 2000
/* Remote side transmit a SETUP */
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
uint8_t bchan_no = 0;
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan;
/*sngisdn_span_data_t *span_info;*/
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
ftdm_assert(g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] == NULL, "Con Ind on busy spInstId");
if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
/* TODO: Implement me */
ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (conEvnt->chanId.chanNmbSlotMap.pres) {
bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0];
} else if (conEvnt->chanId.infoChanSel.pres) {
bchan_no = conEvnt->chanId.infoChanSel.val;
}
if (!bchan_no) {
ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (g_sngisdn_data.dchans[dChan].channels[bchan_no] == NULL) {
ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
ftdmchan = sngisdn_info->ftdmchan;
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) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP\n");
switch (ftdmchan->state){
case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
sngisdn_info->suInstId = get_unique_suInstId(suId);
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
/* try to open the channel */
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
} else {
/* Fill in call information */
cpy_calling_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
cpy_calling_name_from_sngisdn(&ftdmchan->caller_data, conEvnt);
/* Get ani2 */
#if 0
/* TODO: confirm that this works in the field */
if (conEvnt->niOperSysAcc.eh.pres) {
if (conEvnt->niOperSysAcc.typeAcc.pres) {
ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeAcc.val;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of access:%x", conEvnt->niOperSysAcc.typeAcc.val);
}
if (conEvnt->niOperSysAcc.typeServ.pres) {
ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeServ.val;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of service:%x", conEvnt->niOperSysAcc.typeServ.val);
}
}
#endif
/* 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);
}
break;
case FTDM_CHANNEL_STATE_DIALING: /* glare */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received SETUP in DIALING state, glare, queueing incoming call\n");
/* the flag the channel as having a collision */
sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
/* save the SETUP for processing once the channel has gone to DOWN */
memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
sngisdn_info->glare.suId = suId;
sngisdn_info->glare.suInstId = suInstId;
sngisdn_info->glare.spInstId = spInstId;
sngisdn_info->glare.dChan = dChan;
sngisdn_info->glare.ces = ces;
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
break;
}
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/* Remote side transmit a CONNECT or CONNECT ACK */
void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan;
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
if (!sngisdn_info->spInstId) {
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK\n");
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) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
if(sngisdn_info->ces == CES_MNGMNT) {
/* We assign the call to the first TE */
sngisdn_info->ces = ces;
} else {
/* We already assigned this call, do nothing */
ftdm_mutex_unlock(ftdmchan->mutex);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_DIALING:
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
} else {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* This is the only valid state we should get a CONNECT ACK on */
/* do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
}
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan;
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (!sngisdn_info->spInstId) {
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
}
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Received %s\n",
(evntType == MI_ALERTING)?"ALERT":
(evntType == MI_CALLPROC)?"PROCEED":
(evntType == MI_PROGRESS)?"PROGRESS":"UNKNOWN");
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) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_DIALING:
if (evntType == MI_PROGRESS) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
if (evntType == MI_PROGRESS) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received ALERT/PROCEED/PROGRESS in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan = NULL;
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
if (spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) {
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
} else if (suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS) {
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
} else {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
return;
}
if (!sngisdn_info->spInstId) {
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT\n");
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) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_UP:
if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n");
ftdmchan->caller_data.hangup_cause = 0;
}
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
/* start reset procedure */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
sngisdn_chan_data_t *sngisdn_info ;
ftdm_channel_t *ftdmchan = NULL;
/* get the ftdmchan and ss7_chan_data from the circuit */
if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdmchan = sngisdn_info->ftdmchan;
} else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdmchan = sngisdn_info->ftdmchan;
}
if (ftdmchan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE\n");
/* 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)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
};
/* 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;
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* Remote side sent a SETUP, then a RELEASE COMPLETE to abort call - this is an abort */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_DIALING:
/* Remote side rejected our SETUP message on outbound call */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_UP:
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
default:
/* Should just stop the call...but a reset is easier for now (since it does hangup the call) */
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
/* go to RESTART */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
/**************************************************************************/
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received DATA IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received SSHL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received SSHL CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE ind suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received FLOW CONTROL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received FACILITY IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
sngisdn_chan_data_t *sngisdn_info ;
ftdm_channel_t *ftdmchan = NULL;
uint8_t call_state = 0;
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
call_state = staEvnt->callSte.callGlblSte.val;
}
/* get the ftdmchan and ss7_chan_data from the circuit */
if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdmchan = sngisdn_info->ftdmchan;
} else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdmchan = sngisdn_info->ftdmchan;
}
if (ftdmchan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM\n");
/* 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)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
};
if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) {
if (staEvnt->causeDgn[0].causeVal.val != 30) {
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
call_state = staEvnt->callSte.callGlblSte.val;
/* Section 4.3.30 from INT Interface - Service Definition */
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
/* There is incompatibility between local and remote side call states some Q931 msgs probably got lost - initiate disconnect */
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Incompatible call states detected, remote side indicated state:%d our state:%s cause:%d\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val);
switch(call_state) {
/* Sere ITU-T Q931 for definition of call states */
case 0: /* Remote switch thinks there are no calls on this channel */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_DIALING:
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_TERMINATING:
/* We are in the process of clearing local states,
just make sure we will not send any messages to remote switch */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
break;
case FTDM_CHANNEL_STATE_HANGUP:
/* This cannot happen, state_advance always sets
ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
and we called check_for_state_change earlier so something is very wrong here!!! */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We were waiting for remote switch to send RELEASE COMPLETE
but this will not happen, so just clear local state */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* If our local state is down as well, then there is nothing to do */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 8: /* Remote switch is in "Connect Request state" */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* This is ok. We sent a Connect, and we are waiting for a connect ack */
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We hung up locally, but remote switch doesn't know send disconnect again*/
sngisdn_snd_disconnect(ftdmchan);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
} else {
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
/* We could not extract the call state */
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible call states detected, but could not determine call (cause:%d)\n", ftdmchan->caller_data.hangup_cause);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
}
/**************************************************************************/
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESTART IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_q921_ind(BdMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned j,k;
ftdm_span_t *ftdmspan = NULL;
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.lnkNmb) {
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
}
}
}
if (ftdmspan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Received q921 status on unconfigured span\n", status->t.usta.lnkNmb);
#ifdef DEBUG_MODE
FORCE_SEGFAULT
#endif
return;
}
switch (status->t.usta.alarm.category) {
case (LCM_CATEGORY_INTERFACE):
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
default:
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__)
return;
}
void sngisdn_rcv_q931_ind(InMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_span_t *ftdmspan = NULL;
if (status->t.usta.alarm.cause == 287) {
get_memory_info();
return;
}
switch (status->t.usta.alarm.category) {
case (LCM_CATEGORY_INTERFACE):
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
/* clean this up later */
switch (status->t.usta.alarm.event) {
case LCM_EVENT_UP:
case LCM_EVENT_DOWN:
{
unsigned j,k;
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.suId) {
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
}
}
}
if (ftdmspan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Received q931 LCM EVENT on unconfigured span (suId:%d)\n", status->t.usta.suId);
return;
}
sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP)?FTDM_SIG_STATE_UP:FTDM_SIG_STATE_DOWN);
}
break;
}
break;
default:
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_cc_ind(CcMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "RECEIVED %s\n", __FUNCTION__);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
(event == TL3PKTRX)?"RX":"UNKNOWN"
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
uint8_t data;
uint8_t tdata[1000];
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
i = 0;
for(j=0;j<mlen;j++) {
tdata[j]= data;
if (cptr == tmp->b_wptr) {
tmp = tmp->b_cont;
if (tmp) cptr = tmp->b_rptr;
}
data = *cptr++;
}
sngisdn_trace_q931(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] FRAME %s:%s\n", Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
}
ftdm_safe_free(data_str);
/* We do not need to free mBuf in this case because stack does it */
/* SPutMsg(mBuf); */
return;
}
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
(event == TL2FRMTX)?"TX": \
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
uint8_t data;
uint8_t tdata[16];
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
if (trc->t.trc.evnt == TL2TMR) {
goto end_of_trace;
}
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
i = 0;
while (i < mlen) {
j = 0;
for(j=0;j<16;j++) {
if (i<mlen) {
tdata[j]= data;
if (cptr == tmp->b_wptr) {
tmp = tmp->b_cont;
if (tmp) cptr = tmp->b_rptr;
}
i++;
if (i<mlen) data = *cptr++;
}
}
}
sngisdn_trace_q921(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] FRAME %s:%s\n", Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
}
end_of_trace:
ftdm_safe_free(data_str);
SPutMsg(mBuf);
return;
}
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
{
char *data;
int ret;
va_list ap;
va_start(ap, fmt);
ret = ftdm_vasprintf(&data, fmt, ap);
if (ret == -1) {
return;
}
switch (level) {
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_WARN:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
#ifdef DEBUG_MODE
FORCE_SEGFAULT
#endif
break;
case SNG_LOGLEVEL_CRIT:
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
#ifdef DEBUG_MODE
FORCE_SEGFAULT
#endif
break;
default:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
}
return;
}
/* 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:
*/
/******************************************************************************/

View File

@ -43,7 +43,7 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan);
void sngisdn_snd_progress(ftdm_channel_t *ftdmchan);
void sngisdn_snd_connect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan);
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare);
void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
@ -52,11 +52,15 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending SETUP\n");
ftdm_assert((!sngisdn_info->suInstId && !sngisdn_info->spInstId), "Trying to call out, but call data was not cleared\n");
sngisdn_info->suInstId = get_unique_suInstId(signal_data->cc_id);
sngisdn_info->spInstId = 0;
ftdm_mutex_lock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
g_sngisdn_data.ccs[signal_data->cc_id].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
ftdm_mutex_unlock(g_sngisdn_data.ccs[signal_data->cc_id].mutex);
memset(&conEvnt, 0, sizeof(conEvnt));
conEvnt.bearCap[0].eh.pres = PRSNT_NODEF;
@ -92,18 +96,21 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
conEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
/* PRI only params */
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
} else {
conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF;
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW;
conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ULAW;
}
conEvnt.bearCap[0].lyr1Ident.pres = PRSNT_NODEF;
conEvnt.bearCap[0].lyr1Ident.val = IN_L1_IDENT;
conEvnt.chanId.intType.pres = PRSNT_NODEF;
conEvnt.chanId.intType.val = IN_IT_OTHER;
conEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
conEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
conEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
conEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
conEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
@ -130,20 +137,81 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
signal_data->signalling == SNGISDN_SIGNALING_NET) {
sngisdn_info->ces = CES_MNGMNT;
}
cpy_calling_num_to_sngisdn(&conEvnt.cgPtyNmb, &ftdmchan->caller_data);
cpy_called_num_to_sngisdn(&conEvnt.cdPtyNmb, &ftdmchan->caller_data);
cpy_calling_num_to_sngisdn(&conEvnt.cgPtyNmb, &ftdmchan->caller_data);
cpy_calling_name_to_sngisdn(&conEvnt, ftdmchan);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP request\n");
}
return;
}
/* Used only for BRI PTMP */
/* Unsed only for overlap receive */
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending SETUP ACK , but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
/* BRI only params */
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
} else {
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_SETUPACK, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP ACK request\n");
}
return;
}
/* Used only for BRI PTMP - This function is used when the NT side makes a call out,
and one or multiple TE's reply, then NT assigns the call by sending a con_complete*/
void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
{
CnStEvnt cnStEvnt;
@ -151,9 +219,15 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT COMPL , but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT ACK\n");
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
@ -187,7 +261,7 @@ void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending connect ACK on suId:%d suInstId:%u spInstId:%u ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, sngisdn_info->ces);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT COMPL (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_comp(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused CONNECT ACK request\n");
@ -203,9 +277,15 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED\n");
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
@ -239,7 +319,7 @@ void sngisdn_snd_proceed(ftdm_channel_t *ftdmchan)
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROCEED (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_CALLPROC, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused PROCEED request\n");
@ -254,9 +334,20 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS\n");
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending PROGRESS, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
return;
}
if (signal_data->switchtype == SNGISDN_SWITCH_INSNET) {
/* Trillium Q931 layer complains of invalid event when receiving PROGRESS in
INSNET variant, so PROGRESS event is probably invalid */
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.pres = PRSNT_NODEF;
@ -264,9 +355,9 @@ void sngisdn_snd_progress(ftdm_channel_t *ftdmchan)
cnStEvnt.progInd.codeStand0.pres = PRSNT_NODEF;
cnStEvnt.progInd.codeStand0.val = IN_CSTD_CCITT;
cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
cnStEvnt.progInd.progDesc.val = IN_PD_IBAVAIL;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending PROGRESS (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_PROGRESS, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused PROGRESS request\n");
}
@ -280,7 +371,12 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending ALERT\n");
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending ALERT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
@ -292,7 +388,7 @@ void sngisdn_snd_alert(ftdm_channel_t *ftdmchan)
cnStEvnt.progInd.progDesc.pres = PRSNT_NODEF;
cnStEvnt.progInd.progDesc.val = IN_PD_NOTETEISDN;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con status on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending ALERT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId,&cnStEvnt, MI_ALERTING, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused ALERT request\n");
@ -307,8 +403,13 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT\n");
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending CONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
@ -344,21 +445,75 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending con response on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending CONNECT (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_response(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused CONNECT request\n");
}
return;
}
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
{
DiscEvnt discEvnt;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT\n");
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
{
CnStEvnt cnStEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (ftdmchan->span->trunk_type != FTDM_TRUNK_BRI &&
ftdmchan->span->trunk_type != FTDM_TRUNK_BRI_PTMP) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring INFO REQ on non-BRI channel\n");
return;
}
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
//ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ\n");
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending INFO REQ (suId:%d dchan:%d ces:%d)\n", signal_data->cc_id, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_con_status(signal_data->cc_id, 0, 0, &cnStEvnt, MI_INFO, signal_data->dchan_id, sngisdn_info->ces)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused INFO request\n");
}
return;
}
void sngisdn_snd_status_enq(ftdm_channel_t *ftdmchan)
{
StaEvnt staEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
//ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending STATUS ENQ\n");
memset(&staEvnt, 0, sizeof(StaEvnt));
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending Status ENQ on suId:%d suInstId:%u spInstId:%d dchan:%d ces:%d\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
if (sng_isdn_status_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &staEvnt, MI_STATENQ)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused Status ENQ request\n");
}
return;
}
void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
{
DiscEvnt discEvnt;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending DISCONNECT, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
return;
}
memset(&discEvnt, 0, sizeof(discEvnt));
/* Fill discEvnt here */
@ -372,20 +527,28 @@ void sngisdn_snd_disconnect(ftdm_channel_t *ftdmchan)
discEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
discEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending disc request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
if (sng_isdn_disc_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &discEvnt)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused DISCONNECT request\n");
}
return;
}
void sngisdn_snd_release(ftdm_channel_t *ftdmchan)
void sngisdn_snd_release(ftdm_channel_t *ftdmchan, uint8_t glare)
{
RelEvnt relEvnt;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE\n");
uint32_t suInstId, spInstId;
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
if (!sngisdn_info->suInstId) {
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending RELEASE, but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
return;
}
memset(&relEvnt, 0, sizeof(relEvnt));
/* Fill discEvnt here */
@ -400,24 +563,29 @@ void sngisdn_snd_release(ftdm_channel_t *ftdmchan)
relEvnt.causeDgn[0].recommend.pres = NOTPRSNT;
relEvnt.causeDgn[0].dgnVal.pres = NOTPRSNT;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending release request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
if (glare) {
suInstId = sngisdn_info->glare.suInstId;
spInstId = sngisdn_info->glare.spInstId;
} else {
suInstId = sngisdn_info->suInstId;
spInstId = sngisdn_info->spInstId;
}
if (sng_isdn_release_request(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &relEvnt)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n");
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending RELEASE/RELEASE COMPLETE (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, suInstId, spInstId);
if (glare) {
if (sng_isdn_release_request(signal_data->cc_id, suInstId, spInstId, &relEvnt)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n");
}
} else {
if (sng_isdn_release_request(signal_data->cc_id, suInstId, spInstId, &relEvnt)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused RELEASE/RELEASE COMPLETE request\n");
}
}
return;
}
void sngisdn_snd_reset(ftdm_channel_t *ftdmchan)
{
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending RESET\n");
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "%s not implemented\n", __FUNCTION__);
/* TODO: implement me */
return;
}
/* For Emacs:
* Local Variables:

View File

@ -0,0 +1,901 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* David Yat Sin <dyatsin@sangoma.com>
* 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 "ftmod_sangoma_isdn.h"
extern void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
extern void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
extern void get_memory_info(void);
#define MAX_DECODE_STR_LEN 2000
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
uint8_t bchan_no = 0;
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
/* TODO: Implement me */
ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (conEvnt->chanId.chanNmbSlotMap.pres) {
bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0];
} else if (conEvnt->chanId.infoChanSel.pres) {
bchan_no = conEvnt->chanId.infoChanSel.val;
}
if (!bchan_no) {
ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (g_sngisdn_data.dchans[dChan].channels[bchan_no] == NULL) {
ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_CON_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
sngisdn_event->dChan = dChan;
sngisdn_event->ces = ces;
memcpy(&sngisdn_event->event.conEvnt, conEvnt, sizeof(*conEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Cfm on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Cfm on unconfigured dchan\n");
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK (suId:%u suInstId:%u spInstId:%u ces:%d)\n", suId, suInstId, spInstId, ces);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_CON_CFM;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
sngisdn_event->dChan = dChan;
sngisdn_event->ces = ces;
memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Cnst Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Cnst Ind on unconfigured dchan\n");
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received %s (suId:%u suInstId:%u spInstId:%u ces:%d)\n",
(evntType == MI_ALERTING)?"ALERT":
(evntType == MI_CALLPROC)?"PROCEED":
(evntType == MI_PROGRESS)?"PROGRESS":
(evntType == MI_SETUPACK)?"SETUP ACK":
(evntType == MI_INFO)?"INFO":"UNKNOWN",
suId, suInstId, spInstId, ces);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_CNST_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
sngisdn_event->dChan = dChan;
sngisdn_event->ces = ces;
sngisdn_event->evntType = evntType;
memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_DISC_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
memcpy(&sngisdn_event->event.discEvnt, discEvnt, sizeof(*discEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_REL_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
memcpy(&sngisdn_event->event.relEvnt, relEvnt, sizeof(*relEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DATA IND suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_DAT_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
memcpy(&sngisdn_event->event.infoEvnt, infoEvnt, sizeof(*infoEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_SSHL_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
sngisdn_event->action = action;
memcpy(&sngisdn_event->event.ssHlEvnt, ssHlEvnt, sizeof(*ssHlEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_SSHL_CFM;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
sngisdn_event->action = action;
memcpy(&sngisdn_event->event.ssHlEvnt, ssHlEvnt, sizeof(*ssHlEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RMRT IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_RMRT_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
sngisdn_event->action = action;
memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_RMRT_CFM;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
sngisdn_event->action = action;
memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_FLC_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_FAC_IND;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
sngisdn_event->evntType = evntType;
memcpy(&sngisdn_event->event.facEvnt, facEvnt, sizeof(*facEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
sngisdn_event_data_t *sngisdn_event;
if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) &&
!(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId);
return;
}
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_STA_CFM;
sngisdn_event->sngisdn_info = sngisdn_info;
sngisdn_event->suId = suId;
sngisdn_event->suInstId = suInstId;
sngisdn_event->spInstId = spInstId;
memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt));
ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i;
sngisdn_span_data_t *signal_data;
sngisdn_event_data_t *sngisdn_event;
ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND (dChan:%d ces:%u)\n", dChan, ces);
/* Enqueue the event to each span within the dChan */
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND;
sngisdn_event->suId = suId;
sngisdn_event->dChan = dChan;
sngisdn_event->ces = ces;
sngisdn_event->signal_data = signal_data;
memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i;
sngisdn_span_data_t *signal_data;
sngisdn_event_data_t *sngisdn_event;
ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM (dChan:%d ces:%u)\n", dChan, ces);
/* Enqueue the event to each span within the dChan */
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_SRV_CFM;
sngisdn_event->suId = suId;
sngisdn_event->dChan = dChan;
sngisdn_event->ces = ces;
sngisdn_event->signal_data = signal_data;
memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt));
ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i;
sngisdn_span_data_t *signal_data;
sngisdn_event_data_t *sngisdn_event;
ftdm_log(FTDM_LOG_INFO, "Received RESTART IND (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
/* Enqueue the event to each span within the dChan */
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_RST_IND;
sngisdn_event->suId = suId;
sngisdn_event->dChan = dChan;
sngisdn_event->ces = ces;
sngisdn_event->evntType = evntType;
sngisdn_event->signal_data = signal_data;
memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt));
ftdm_queue_enqueue(signal_data->event_queue, sngisdn_event);
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evntType)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned i;
sngisdn_span_data_t *signal_data;
sngisdn_event_data_t *sngisdn_event;
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType);
/* Enqueue the event to each span within the dChan */
for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) {
signal_data = g_sngisdn_data.dchans[dChan].spans[i];
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM;
sngisdn_event->suId = suId;
sngisdn_event->dChan = dChan;
sngisdn_event->ces = ces;
sngisdn_event->evntType = evntType;
sngisdn_event->signal_data = signal_data;
memcpy(&sngisdn_event->event.rstEvnt, rstEvnt, sizeof(*rstEvnt));
ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event);
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
}
void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
if (reason != LL1_REASON_CON_REQ_FAIL) {
ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_q921_ind(BdMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned j,k;
ftdm_span_t *ftdmspan = NULL;
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.lnkNmb) {
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
}
}
}
ftdm_assert(ftdmspan != NULL, "Received q921 status on unconfigured span\n");
switch (status->t.usta.alarm.category) {
case (LCM_CATEGORY_INTERFACE):
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
default:
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
switch (status->t.usta.alarm.event) {
case ENTR_CONG: /* Entering Congestion */
ftdm_log(FTDM_LOG_WARNING, "s%d: Entering Congestion\n", ftdmspan->span_id);
ftdm_set_flag(ftdmspan, FTDM_SPAN_SUSPENDED);
break;
case EXIT_CONG: /* Exiting Congestion */
ftdm_log(FTDM_LOG_WARNING, "s%d: Exiting Congestion\n", ftdmspan->span_id);
ftdm_clear_flag(ftdmspan, FTDM_SPAN_SUSPENDED);
break;
}
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__)
return;
}
void sngisdn_rcv_q931_ind(InMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_span_t *ftdmspan = NULL;
if (status->t.usta.alarm.cause == 287) {
get_memory_info();
return;
}
switch (status->t.usta.alarm.category) {
case (LCM_CATEGORY_INTERFACE):
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
/* clean this up later */
switch (status->t.usta.alarm.event) {
case LCM_EVENT_UP:
case LCM_EVENT_DOWN:
{
unsigned j,k;
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.suId) {
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
}
}
}
if (ftdmspan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Received q931 LCM EVENT on unconfigured span (suId:%u)\n", status->t.usta.suId);
return;
}
if (status->t.usta.alarm.event == LCM_EVENT_UP) {
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
} else {
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
}
}
break;
}
break;
default:
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_cc_ind(CcMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "RECEIVED %s\n", __FUNCTION__);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
(event == TL3PKTRX)?"RX":"UNKNOWN"
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
uint8_t data;
uint8_t tdata[1000];
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
i = 0;
for(j=0;j<mlen;j++) {
tdata[j]= data;
if (cptr == tmp->b_wptr) {
tmp = tmp->b_cont;
if (tmp) cptr = tmp->b_rptr;
}
data = *cptr++;
}
sngisdn_trace_q931(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d FRAME %s:%s\n", trc->t.trc.suId, Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
}
ftdm_safe_free(data_str);
/* We do not need to free mBuf in this case because stack does it */
/* SPutMsg(mBuf); */
return;
}
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
(event == TL2FRMTX)?"TX": \
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
uint8_t data;
uint8_t tdata[16];
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
if (trc->t.trc.evnt == TL2TMR) {
goto end_of_trace;
}
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
i = 0;
while (i < mlen) {
j = 0;
for(j=0;j<16;j++) {
if (i<mlen) {
tdata[j]= data;
if (cptr == tmp->b_wptr) {
tmp = tmp->b_cont;
if (tmp) cptr = tmp->b_rptr;
}
i++;
if (i<mlen) data = *cptr++;
}
}
}
sngisdn_trace_q921(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", trc->t.trc.lnkNmb, Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
}
end_of_trace:
ftdm_safe_free(data_str);
SPutMsg(mBuf);
return;
}
void sngisdn_rcv_sng_assert(char *message)
{
ftdm_assert(0, message);
}
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
{
char *data;
int ret;
va_list ap;
va_start(ap, fmt);
ret = ftdm_vasprintf(&data, fmt, ap);
if (ret == -1) {
return;
}
switch (level) {
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_WARN:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
/*ftdm_assert(0, "Got an error from stack");*/
break;
case SNG_LOGLEVEL_CRIT:
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
/*ftdm_assert(0, "Got an error from stack");*/
break;
default:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
}
return;
}
/* 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:
*/
/******************************************************************************/

View File

@ -37,22 +37,27 @@
ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb);
ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt);
ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display);
ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm);
ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm);
ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm);
ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan);
ftdm_status_t sngisdn_check_free_ids(void);
extern ftdm_sngisdn_data_t g_sngisdn_data;
void get_memory_info(void);
void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
void __inline__ clear_call_data(sngisdn_chan_data_t *sngisdn_info)
{
uint32_t cc_id = ((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->cc_id;
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing call data (suId:%u suInstId:%u spInstId:%u)\n", cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].mutex);
g_sngisdn_data.ccs[cc_id].active_spInstIds[sngisdn_info->spInstId]=NULL;
g_sngisdn_data.ccs[cc_id].active_suInstIds[sngisdn_info->suInstId]=NULL;
ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
sngisdn_info->suInstId = 0;
sngisdn_info->spInstId = 0;
@ -61,10 +66,33 @@ void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
return;
}
uint32_t get_unique_suInstId(uint8_t cc_id)
void __inline__ clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info)
{
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_DEBUG, "Clearing glare data (suId:%d suInstId:%u spInstId:%u actv-suInstId:%u actv-spInstId:%u)\n",
sngisdn_info->glare.suId,
sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId,
sngisdn_info->suInstId, sngisdn_info->spInstId);
ftdm_mutex_lock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex);
g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_spInstIds[sngisdn_info->glare.spInstId]=NULL;
g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_suInstIds[sngisdn_info->glare.suInstId]=NULL;
ftdm_mutex_unlock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex);
ftdm_clear_flag(sngisdn_info, FLAG_GLARE);
memset(&sngisdn_info->glare.setup, 0, sizeof(ConEvnt));
sngisdn_info->glare.suId = 0;
sngisdn_info->glare.suInstId = 0;
sngisdn_info->glare.spInstId = 0;
sngisdn_info->glare.dChan = 0;
sngisdn_info->glare.ces = 0;
return;
}
uint32_t __inline__ get_unique_suInstId(uint8_t cc_id)
{
uint32_t suInstId;
ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].request_mutex);
ftdm_mutex_lock(g_sngisdn_data.ccs[cc_id].mutex);
suInstId = g_sngisdn_data.ccs[cc_id].last_suInstId;
while(1) {
@ -73,16 +101,16 @@ uint32_t get_unique_suInstId(uint8_t cc_id)
}
if (g_sngisdn_data.ccs[cc_id].active_suInstIds[suInstId] == NULL) {
g_sngisdn_data.ccs[cc_id].last_suInstId = suInstId;
ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].request_mutex);
ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
return suInstId;
}
}
/* Should never reach here */
ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].request_mutex);
ftdm_mutex_unlock(g_sngisdn_data.ccs[cc_id].mutex);
return 0;
}
ftdm_status_t get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
ftdm_status_t __inline__ get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn_chan_data_t **sngisdn_data)
{
ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
@ -93,7 +121,7 @@ ftdm_status_t get_ftdmchan_by_suInstId(uint8_t cc_id, uint32_t suInstId, sngisdn
return FTDM_SUCCESS;
}
ftdm_status_t get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
ftdm_status_t __inline__ get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn_chan_data_t **sngisdn_data)
{
ftdm_assert_return(g_sngisdn_data.ccs[cc_id].activation_done, FTDM_FAIL, "Trying to find call on unconfigured CC\n");
@ -104,6 +132,19 @@ ftdm_status_t get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInstId, sngisdn
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail)
{
unsigned i;
if (ftdmspan->trunk_type == FTDM_TRUNK_BRI ||
ftdmspan->trunk_type == FTDM_TRUNK_BRI_PTMP) {
for(i=1; i<=ftdmspan->chan_count; i++) {
ftdm_log_chan(ftdmspan->channels[i], FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
ftdmspan->channels[i]->availability_rate = avail;
}
}
return FTDM_SUCCESS;
}
ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb)
{
@ -147,7 +188,9 @@ ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cd
}
if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
ftdm_copy_string(ftdm->dnis.digits, (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
unsigned i = strlen(ftdm->dnis.digits);
ftdm_copy_string(&ftdm->dnis.digits[i], (const char*)cdPtyNmb->nmbDigits.val, cdPtyNmb->nmbDigits.len+1);
}
return FTDM_SUCCESS;
}
@ -172,13 +215,16 @@ ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *red
return FTDM_SUCCESS;
}
ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt)
ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, Display *display)
{
if (conEvnt->display.eh.pres && conEvnt->display.dispInfo.pres == PRSNT_NODEF) {
ftdm_copy_string(ftdm->cid_name, (const char*)conEvnt->display.dispInfo.val, conEvnt->display.dispInfo.len+1);
if (display->eh.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
/* TODO check if caller name is contained in a Facility IE */
if (display->dispInfo.pres != PRSNT_NODEF) {
return FTDM_FAIL;
}
ftdm_copy_string(ftdm->cid_name, (const char*)display->dispInfo.val, display->dispInfo.len+1);
return FTDM_SUCCESS;
}
@ -219,14 +265,23 @@ ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *
cdPtyNmb->eh.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.val = ftdm->dnis.plan;
if (ftdm->dnis.plan == FTDM_NPI_INVALID) {
cdPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
cdPtyNmb->nmbPlanId.val = ftdm->dnis.plan;
}
cdPtyNmb->typeNmb0.pres = PRSNT_NODEF;
cdPtyNmb->typeNmb0.val = ftdm->dnis.type;
if (ftdm->dnis.type == FTDM_TON_INVALID) {
cdPtyNmb->typeNmb0.val = FTDM_TON_UNKNOWN;
} else {
cdPtyNmb->typeNmb0.val = ftdm->dnis.type;
}
cdPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cdPtyNmb->nmbDigits.len = len;
memcpy(cdPtyNmb->nmbDigits.val, ftdm->dnis.digits, len);
return FTDM_SUCCESS;
}
@ -241,10 +296,18 @@ ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *f
redirNmb->eh.pres = PRSNT_NODEF;
redirNmb->nmbPlanId.pres = PRSNT_NODEF;
redirNmb->nmbPlanId.val = ftdm->rdnis.plan;
if (ftdm->rdnis.plan == FTDM_NPI_INVALID) {
redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
redirNmb->nmbPlanId.val = ftdm->rdnis.plan;
}
redirNmb->typeNmb.pres = PRSNT_NODEF;
redirNmb->typeNmb.val = ftdm->rdnis.type;
if (ftdm->rdnis.type == FTDM_TON_INVALID) {
redirNmb->typeNmb.val = FTDM_TON_UNKNOWN;
} else {
redirNmb->typeNmb.val = ftdm->rdnis.type;
}
redirNmb->nmbDigits.pres = PRSNT_NODEF;
redirNmb->nmbDigits.len = len;
@ -308,28 +371,99 @@ ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdm
return FTDM_SUCCESS;
}
ftdm_status_t check_for_state_change(ftdm_channel_t *ftdmchan)
void sngisdn_delayed_release(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
#if 0
ftdm_log_chan_msg(ftdmchan, "Checking for pending state change\n");
ftdm_mutex_lock(ftdmchan->mutex);
if (ftdm_test_flag(sngisdn_info, FLAG_DELAYED_REL)) {
ftdm_clear_flag(sngisdn_info, FLAG_DELAYED_REL);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed RELEASE (suId:%d suInstId:%u spInstId:%u)\n",
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
sngisdn_snd_release(ftdmchan, 1);
#if 1 /* TODO: Confirm this */
clear_call_glare_data(sngisdn_info);
#else
g_sngisdn_data.ccs[signal_data->cc_id].active_spInstIds[sngisdn_info->glare.spInstId] = NULL;
g_sngisdn_data.ccs[signal_data->cc_id].active_suInstIds[sngisdn_info->glare.suInstId] = NULL;
#endif
/* check to see if there are any pending state changes on the channel and give them a sec to happen*/
ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 5000);
/* check the flag to confirm it is clear now */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
/* the flag is still up...so we have a problem */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "FTDM_CHANNEL_STATE_CHANGE set for over 500ms\n");
} else {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Call was already released (suId:%d suInstId:%u spInstId:%u)\n",
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
}
ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
/* move the state of the channel to RESTART to force a reset */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
void sngisdn_delayed_connect(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
return FTDM_FAIL;
}
return FTDM_SUCCESS;
ftdm_mutex_lock(ftdmchan->mutex);
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed CONNECT (suId:%d suInstId:%u spInstId:%u)\n",
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
sngisdn_snd_connect(ftdmchan);
ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
void sngisdn_delayed_disconnect(void* p_sngisdn_info)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
ftdm_mutex_lock(ftdmchan->mutex);
if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n",
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
sngisdn_snd_disconnect(ftdmchan);
}
ftdm_mutex_unlock(ftdmchan->mutex);
return;
}
ftdm_status_t sngisdn_check_free_ids(void)
{
unsigned i;
unsigned j;
ftdm_log(FTDM_LOG_INFO, "Checking suInstId's\n");
for(j=1;j<=MAX_VARIANTS;j++) {
if (g_sngisdn_data.ccs[j].config_done) {
for(i=1;i<MAX_INSTID;i++) {
if (g_sngisdn_data.ccs[j].active_suInstIds[i] != NULL) {
ftdm_log(FTDM_LOG_INFO, "suId:%u suInstId:%u is not free\n", j, i);
}
}
}
}
ftdm_log(FTDM_LOG_INFO, "Checking spInstId's\n");
for(j=1;j<=MAX_VARIANTS;j++) {
if (g_sngisdn_data.ccs[j].config_done) {
for(i=1;i<MAX_INSTID;i++) {
if (g_sngisdn_data.ccs[j].active_spInstIds[i] != NULL) {
ftdm_log(FTDM_LOG_INFO, "suId:%u spInstId:%u is not free\n", j, i);
}
}
}
}
ftdm_log(FTDM_LOG_INFO, "Checking ID's done\n");
return FTDM_SUCCESS;
}
void get_memory_info(void)
@ -339,6 +473,7 @@ void get_memory_info(void)
return;
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -205,7 +205,7 @@ void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
i=i+1;
c=c+1;
}
str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Origination");
str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Originating");
/* Decode message type */
str_len+= sprintf(&str[str_len], " Type:%s (0x%x)\n", get_code_2_str((int)(data[2+lenCallRef] & 0xFF), dcodQ931MsgTypeTable), (int)(data[2+lenCallRef] & 0xFF));
@ -337,7 +337,7 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
}
if (numberMap) {
*str_len+= sprintf(&str[*str_len], " MAP\n");
*str_len+= sprintf(&str[*str_len], " MAP:%s ", get_code_2_str(infoChannelSelection, dcodQ931InfoChannelSelTable));
} else {
*str_len+= sprintf(&str[*str_len], "No:%d ", channelNo);
}
@ -608,6 +608,9 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
break;
case PROT_Q931_IE_SENDING_COMPLETE:
/* No need to decode sending complete IE, as no additional info is available except that sending is done */
/* This is a single octet IE */
*str_len+= sprintf(&str[*str_len], "\n");
return 0;
break;
case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
case PROT_Q931_IE_REDIRECTION_NUMBER:

View File

@ -373,6 +373,14 @@ struct code2str dcodQ931ScreeningTable[] = {
{-1, "invalid" },
};
struct code2str dcodQ931InfoChannelSelTable[] = {
{0, "No Chan"},
{1, "B1"},
{2, "B2"},
{3, "Any Chan"},
{-1, "invalid" },
};
struct code2str dcodQ931ReasonTable[] = {
{0x0, "Unknown"},
{0x1, "Call forwarding busy"},

File diff suppressed because it is too large Load Diff

View File

@ -42,681 +42,235 @@
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
void handle_sng_log(uint8_t level, char *fmt,...);
void handle_sng_alarm(sng_alrm_t t_alarm);
static void handle_entsi_alarm(sng_alrm_t t_alarm);
int ft_to_sngss7_cfg(void);
int ft_to_sngss7_activate_all(void);
static int ftmod_ss7_general_configuration(void);
static int ftmod_ss7_configure_mtp1_link(int id);
static int ftmod_ss7_configure_mtp2_link(int id);
static int ftmod_ss7_configure_mtp3_link(int id);
static int ftmod_ss7_configure_mtp3_linkset(int id);
static int ftmod_ss7_configure_mtp3_route(int id);
static int ftmod_ss7_configure_mtp3_isup(int id);
static int ftmod_ss7_configure_isup_mtp3(int id);
static int ftmod_ss7_configure_isup_interface(int id);
static int ftmod_ss7_configure_isup_circuit(int id);
static int ftmod_ss7_configure_isup_cc(int id);
static int ftmod_ss7_configure_cc_isup(int id);
static int ftmod_ss7_enable_isap(int suId);
static int ftmod_ss7_enable_nsap(int suId);
static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId);
int ftmod_ss7_inhibit_mtplink(uint32_t id);
int ftmod_ss7_uninhibit_mtplink(uint32_t id);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
/* LOGGIGING ******************************************************************/
void handle_sng_log(uint8_t level, char *fmt,...)
{
char *data;
int ret;
va_list ap;
va_start(ap, fmt);
ret = vasprintf(&data, fmt, ap);
if (ret == -1) {
return;
}
switch (level) {
/**************************************************************************/
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_WARN:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_CRIT:
printf("%s",data);
/*ftdm_log(FTDM_LOG_CRIT, "sng_ss7->%s", data);*/
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
}
return;
}
/******************************************************************************/
void handle_sng_alarm(sng_alrm_t t_alarm)
{
switch (t_alarm.entity) {
/**************************************************************************/
case (ENTL1):
ftdm_log(FTDM_LOG_WARNING,"[SNG-MTP1] %s : %s : %s \n",
DECODE_LL1_EVENT(t_alarm.event),
DECODE_LL1_CAUSE(t_alarm.cause),
DECODE_LL1_PARM(t_alarm.eventParm[0]));
break;
/**************************************************************************/
case (ENTSD):
ftdm_log(FTDM_LOG_WARNING,"[SNG-MTP2] %s : %s \n",
DECODE_LSD_EVENT(t_alarm.event),
DECODE_LSD_CAUSE(t_alarm.cause));
break;
/**************************************************************************/
case (ENTSN):
ftdm_log(FTDM_LOG_WARNING,"[SNG-MTP3] %s on %d: %s \n",
DECODE_LSN_EVENT(t_alarm.event),
t_alarm.id,
DECODE_LSN_CAUSE(t_alarm.cause));
break;
/**************************************************************************/
case (ENTSI):
handle_entsi_alarm(t_alarm);
break;
/**************************************************************************/
case (ENTCC):
ftdm_log(FTDM_LOG_DEBUG,"[SNG-CC] %s : %s \n",
DECODE_LCC_EVENT(t_alarm.event),
DECODE_LCC_CAUSE(t_alarm.cause));
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_WARNING,"Received alarm from unknown entity");
break;
/**************************************************************************/
} /* switch (t_alarm.entity) */
return;
}
/******************************************************************************/
static void handle_entsi_alarm(sng_alrm_t alarm)
{
switch (alarm.event) {
/**************************************************************************/
case (LCM_EVENT_TIMEOUT):
/* this event always has the circuit value embedded */
SS7_WARN("[ISUP] Timer %d expired on CIC %d\n",
alarm.eventParm[8],
g_ftdm_sngss7_data.cfg.isupCircuit[alarm.eventParm[0]].cic);
break;
/**************************************************************************/
case (LSI_EVENT_REMOTE):
SS7_WARN("[ISUP] %s received on CIC %d\n",
DECODE_LSI_CAUSE(alarm.cause),
g_ftdm_sngss7_data.cfg.isupCircuit[alarm.eventParm[0]].cic);
break;
/**************************************************************************/
case (LSI_EVENT_LOCAL):
SS7_WARN("[ISUP] %s transmitted on CIC %d\n",
DECODE_LSI_CAUSE(alarm.cause),
g_ftdm_sngss7_data.cfg.isupCircuit[alarm.eventParm[0]].cic);
break;
/**************************************************************************/
case (LSI_EVENT_MTP):
SS7_WARN("[ISUP] Received %s on %d\n",
DECODE_LSI_CAUSE(alarm.cause),
g_ftdm_sngss7_data.cfg.mtp3_isup[alarm.eventParm[2]].id);
break;
/**************************************************************************/
case (LCM_EVENT_UI_INV_EVT):
switch (alarm.cause) {
/**********************************************************************/
case (LSI_CAUSE_INV_CIRCUIT):
SS7_WARN("[ISUP] Invalid circuit = %d (CIC = %d)\n",
alarm.eventParm[0],
g_ftdm_sngss7_data.cfg.isupCircuit[alarm.eventParm[0]].cic);
break;
/**********************************************************************/
}
break;
/**************************************************************************/
case (LCM_EVENT_LI_INV_EVT):
switch (alarm.cause) {
/**********************************************************************/
case (LCM_CAUSE_INV_SAP):
SS7_WARN("[ISUP] Invalid spId = %d\n",
alarm.eventParm[3]);
break;
/**********************************************************************/
}
break;
/**************************************************************************/
default:
SS7_WARN("[ISUP] %s : %s \n", DECODE_LSI_EVENT(alarm.event), DECODE_LSI_CAUSE(alarm.cause));
break;
/**************************************************************************/
} /* switch (alarm.event) */
return;
}
/* ACTIVATION *****************************************************************/
int ft_to_sngss7_activate_all(void)
{
sng_isup_cc_t *cc_isup = NULL;
sng_mtp3_isup_t *isup_mtp3 = NULL;
sng_mtp3LinkSet_t *mtp3_linkset = NULL;
int x;
int x;
/* CC to ISUP *************************************************************/
x = 1;
cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
while (cc_isup->id != 0) {
if (sngss7_test_flag(cc_isup, SNGSS7_FLAG_ACTIVE)) {
SS7_DEBUG("CC-ISUP interface already active = %d\n", cc_isup->id);
} else {
if (sng_activate_cc_isup_inf(cc_isup->ccId)) {
SS7_ERROR("Failed to activate CC-ISUP = %d\n",cc_isup->id);
return FTDM_FAIL;
} else {
SS7_INFO("Started CC-ISUP interface = %d\n", cc_isup->id);
sngss7_set_flag(cc_isup, SNGSS7_FLAG_ACTIVE);
}
} /* if (sngss7_test_flag(cc_isup, SNGSS7_FLAG_ACTIVE) */
x = 1;
while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) {
/* check if this link has already been actived */
if (!(g_ftdm_sngss7_data.cfg.isap[x].flags & ACTIVE)) {
x++;
cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
} /* while (cc_isup->id != 0) */
if (ftmod_ss7_enable_isap(x)) {
SS7_CRITICAL("ISAP %d Enable: NOT OK\n", x);
SS7_ASSERT;
} else {
SS7_INFO("ISAP %d Enable: OK\n", x);
}
/* ISUP - MTP3 ************************************************************/
x = 1;
isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
while (isup_mtp3->id != 0) {
if (sngss7_test_flag(isup_mtp3, SNGSS7_FLAG_ACTIVE)) {
SS7_DEBUG("ISUP-MTP3 interface already active = %d\n", isup_mtp3->id);
} else {
if (sng_activate_isup_mtp3_inf(isup_mtp3->id)) {
SS7_ERROR("Failed to activate ISUP-MTP3 = %d\n",isup_mtp3->id);
return FTDM_FAIL;
} else {
SS7_INFO("Started ISUP-MTP3interface = %d\n", isup_mtp3->id);
sngss7_set_flag(isup_mtp3, SNGSS7_FLAG_ACTIVE);
}
} /* if (sngss7_test_flag(isup_mtp3, SNGSS7_FLAG_ACTIVE) */
/* set the ACTIVE flag */
g_ftdm_sngss7_data.cfg.isap[x].flags |= ACTIVE;
} /* if !ACTIVE */
x++;
} /* while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) */
x++;
isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
} /* while (isup_mtp3->id != 0) */
x = 1;
while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) {
/* check if this link has already been actived */
if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & ACTIVE)) {
/* MTP3 Linkset (MTP3 - MTP2 - MTP1) **************************************/
x = 1;
mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
while (mtp3_linkset->id != 0) {
if (sngss7_test_flag(mtp3_linkset, SNGSS7_FLAG_ACTIVE)) {
SS7_DEBUG("MTP3 Linkset already active = %s\n", mtp3_linkset->name);
} else {
if (sng_activate_mtp3_linkset(mtp3_linkset->id)) {
SS7_ERROR("Failed to activate MTP3 Linkset = %s\n",mtp3_linkset->name);
return FTDM_FAIL;
} else {
SS7_INFO("Started MTP3 Linkset = %s\n", mtp3_linkset->name);
sngss7_set_flag(mtp3_linkset, SNGSS7_FLAG_ACTIVE);
}
} /* if (sngss7_test_flag(mtp3_linkset, SNGSS7_FLAG_ACTIVE) */
if (ftmod_ss7_enable_nsap(x)) {
SS7_CRITICAL("NSAP %d Enable: NOT OK\n", x);
SS7_ASSERT;
} else {
SS7_INFO("NSAP %d Enable: OK\n", x);
}
x++;
mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
} /* while (mtp3_linkset->id != 0) */
/* set the ACTIVE flag */
g_ftdm_sngss7_data.cfg.nsap[x].flags |= ACTIVE;
} /* if !ACTIVE */
x++;
} /* while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) */
return FTDM_SUCCESS;
}
x = 1;
while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
/* check if this link has already been actived */
if (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & ACTIVE)) {
/* CONFIGURATION **************************************************************/
int ft_to_sngss7_cfg(void)
{
sng_mtp1Link_t *mtp1_link = NULL;
sng_mtp2Link_t *mtp2_link = NULL;
sng_mtp3Link_t *mtp3_link = NULL;
sng_mtp3LinkSet_t *mtp3_linkset = NULL;
sng_mtp3Route_t *mtp3_route = NULL;
sng_mtp3_isup_t *mtp3_isup = NULL;
sng_mtp3_isup_t *isup_mtp3 = NULL;
sng_isupInterface_t *isup_interface = NULL;
sng_isupCircuit_t *isup_circuit = NULL;
sng_isup_cc_t *isup_cc = NULL;
sng_isup_cc_t *cc_isup = NULL;
int x;
if (ftmod_ss7_enable_mtpLinkSet(x)) {
SS7_CRITICAL("LinkSet \"%s\" Enable: NOT OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
SS7_ASSERT;
} else {
SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
}
SS7_DEBUG("Starting LibSngSS7 configuration...\n");
/* set the ACTIVE flag */
g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= ACTIVE;
} /* if !ACTIVE */
x++;
} /* while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) */
if (g_ftdm_sngss7_data.gen_config_done == 0) {
/* perform general configuration */
if(ftmod_ss7_general_configuration()) {
SS7_ERROR("Failed to run general configuration!\n");
return FTDM_FAIL;
} else {
SS7_INFO("General Configuration was successful\n");
g_ftdm_sngss7_data.gen_config_done = 1;
}
} else {
SS7_DEBUG("General configuration already done.\n");
}
/* MTP1 *******************************************************************/
x=1;
mtp1_link = &g_ftdm_sngss7_data.cfg.mtp1Link[x];
while (mtp1_link->id != 0) {
if (sngss7_test_flag(mtp1_link, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("MTP1 Link already configured = %s\n",mtp1_link->name);
} else {
if (ftmod_ss7_configure_mtp1_link(x)) {
SS7_ERROR("Failed to configure MTP1 link = %s\n!", mtp1_link->name);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured MTP1 link = %s\n", mtp1_link->name);
sngss7_set_flag(mtp1_link, SNGSS7_FLAG_CONFIGURED);
}
}
/* next link */
x++;
mtp1_link = &g_ftdm_sngss7_data.cfg.mtp1Link[x];
} /* while (g_ftdm_sngss7_data.cfg.mtp1Link[x]->id != 0) */
/* MTP2 *******************************************************************/
x=1;
mtp2_link = &g_ftdm_sngss7_data.cfg.mtp2Link[x];
while (mtp2_link->id != 0) {
if (sngss7_test_flag(mtp2_link, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("MTP2 Link already configured = %s\n",mtp2_link->name);
} else {
if (ftmod_ss7_configure_mtp2_link(x)) {
SS7_ERROR("Failed to configure MTP2 link = %s\n!", mtp2_link->name);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured MTP2 link = %s\n", mtp2_link->name);
sngss7_set_flag(mtp2_link, SNGSS7_FLAG_CONFIGURED);
}
}
/* next link */
x++;
mtp2_link = &g_ftdm_sngss7_data.cfg.mtp2Link[x];
} /* while (g_ftdm_sngss7_data.cfg.mtp2Link[x]->id != 0) */
/* MTP3 *******************************************************************/
x=1;
mtp3_link = &g_ftdm_sngss7_data.cfg.mtp3Link[x];
while (mtp3_link->id != 0) {
if (sngss7_test_flag(mtp3_link, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("MTP3 Link already configured = %s\n", mtp3_link->name);
} else {
if (ftmod_ss7_configure_mtp3_link(x)) {
SS7_ERROR("Failed to configure MTP3 link = %s\n!", mtp3_link->name);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured MTP3 link = %s\n", mtp3_link->name);
sngss7_set_flag(mtp3_link, SNGSS7_FLAG_CONFIGURED);
}
}
/* next link */
x++;
mtp3_link = &g_ftdm_sngss7_data.cfg.mtp3Link[x];
} /* while (g_ftdm_sngss7_data.cfg.mtp3Link[x]->id != 0) */
x=1;
mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
while (mtp3_linkset->id != 0) {
if (sngss7_test_flag(mtp3_linkset, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("MTP3 LinkSet already configured = %s\n", mtp3_linkset->name);
} else {
if (ftmod_ss7_configure_mtp3_linkset(x)) {
SS7_ERROR("Failed to configure MTP3 link = %s\n!", mtp3_linkset->name);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured MTP3 link = %s\n", mtp3_linkset->name);
sngss7_set_flag(mtp3_linkset, SNGSS7_FLAG_CONFIGURED);
}
}
/* next link */
x++;
mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
} /* while (g_ftdm_sngss7_data.cfg.mtp1Link[x]->id != 0) */
x=1;
mtp3_route = &g_ftdm_sngss7_data.cfg.mtp3Route[x];
while (mtp3_route->id != 0) {
if (sngss7_test_flag(mtp3_route, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("MTP3 Route already configured = %s\n", mtp3_route->name);
} else {
if (ftmod_ss7_configure_mtp3_route(x)) {
SS7_ERROR("Failed to configure MTP3 route = %s\n!", mtp3_route->name);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured MTP3 route = %s\n", mtp3_route->name);
sngss7_set_flag(mtp3_route, SNGSS7_FLAG_CONFIGURED);
}
}
/* next link */
x++;
mtp3_route = &g_ftdm_sngss7_data.cfg.mtp3Route[x];
} /* while (g_ftdm_sngss7_data.cfg.mtp3Route[x]->id != 0) */
mtp3_route = &g_ftdm_sngss7_data.cfg.mtp3Route[0];
if (sngss7_test_flag(mtp3_route, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("MTP3 Self Route already configured\n");
} else {
if (ftmod_ss7_configure_mtp3_route(0)) {
SS7_ERROR("Failed to configure MTP3 Route = SelfRoute\n!");
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured MTP3 Route = SelfRoute\n");
sngss7_set_flag(mtp3_route, SNGSS7_FLAG_CONFIGURED);
}
}
x=1;
mtp3_isup = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
while (mtp3_isup->id != 0) {
if (sngss7_test_flag(mtp3_isup, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("MTP3-ISUP interface already configured = %d\n", mtp3_isup->id);
} else {
if (ftmod_ss7_configure_mtp3_isup(x)) {
SS7_ERROR("Failed to configure MTP3-ISUP interface = %d\n!", mtp3_isup->id);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured MTP3-ISUP interface = %d\n", mtp3_isup->id);
}
}
/* next link */
x++;
mtp3_isup = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
} /* while (g_ftdm_sngss7_data.cfg.mtp3_isup[x]->id != 0) */
/* ISUP *******************************************************************/
x=1;
isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
while (isup_mtp3->id != 0) {
if (sngss7_test_flag(isup_mtp3, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("ISUP-MTP3 interface already configured = %d\n", isup_mtp3->id);
} else {
if (ftmod_ss7_configure_isup_mtp3(x)) {
SS7_ERROR("Failed to configure ISUP-MTP3 interface = %d\n!", isup_mtp3->id);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured ISUP-MTP3 interface = %d\n", isup_mtp3->id);
sngss7_set_flag(isup_mtp3, SNGSS7_FLAG_CONFIGURED);
}
}
/* next link */
x++;
isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
} /* while (g_ftdm_sngss7_data.cfg.isup_mtp3[x]->id != 0) */
x=1;
isup_cc = &g_ftdm_sngss7_data.cfg.isup_cc[x];
while (isup_cc->id != 0) {
if (sngss7_test_flag(isup_cc, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("ISUP-CC interface already configured = %d\n", isup_cc->id);
} else {
if (ftmod_ss7_configure_isup_cc(x)) {
SS7_ERROR("Failed to configure ISUP-CC interface = %d\n!", isup_cc->id);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured ISUP-CC interface = %d\n", isup_cc->id);
}
}
/* next link */
x++;
isup_cc = &g_ftdm_sngss7_data.cfg.isup_cc[x];
} /* while (g_ftdm_sngss7_data.cfg.isup_cc[x]->id != 0) */
x=1;
isup_interface = &g_ftdm_sngss7_data.cfg.isupInterface[x];
while (isup_interface->id != 0) {
if (sngss7_test_flag(isup_interface, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("ISUP interface already configured = %s\n", isup_interface->name);
} else {
if (ftmod_ss7_configure_isup_interface(x)) {
SS7_ERROR("Failed to configure ISUP interface = %s\n", isup_interface->name);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured ISUP interface = %s\n", isup_interface->name);
sngss7_set_flag(isup_interface, SNGSS7_FLAG_CONFIGURED);
}
}
/* next link */
x++;
isup_interface = &g_ftdm_sngss7_data.cfg.isupInterface[x];
} /* while (g_ftdm_sngss7_data.cfg.isup_interface[x]->id != 0) */
x=1;
isup_circuit = &g_ftdm_sngss7_data.cfg.isupCircuit[x];
while (isup_circuit->id != 0) {
if (isup_circuit->cic != 0) {
if (sngss7_test_flag(isup_circuit, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("ISUP Circuit already configured = %d\n", isup_circuit->id);
} else {
if (ftmod_ss7_configure_isup_circuit(x)) {
SS7_ERROR("Failed to configure ISUP circuit = %d\n!", isup_circuit->id);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured ISUP circuit = %d\n", isup_circuit->id);
sngss7_set_flag(isup_circuit, SNGSS7_FLAG_CONFIGURED);
}
}
}
/* next link */
x++;
isup_circuit = &g_ftdm_sngss7_data.cfg.isupCircuit[x];
} /* while (g_ftdm_sngss7_data.cfg.isup_circuit[x]->id != 0) */
/* CC *********************************************************************/
x=1;
cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
while (cc_isup->id != 0) {
if (sngss7_test_flag(cc_isup, SNGSS7_FLAG_CONFIGURED)) {
SS7_DEBUG("CC-ISUP interface already configured = %d\n", cc_isup->id);
} else {
if (ftmod_ss7_configure_cc_isup(x)) {
SS7_ERROR("Failed to configure CC-ISUP interface = %d\n!", cc_isup->id);
return FTDM_FAIL;
} else {
SS7_INFO("Successfully configured CC-ISUP interface = %d\n", cc_isup->id);
sngss7_set_flag(cc_isup, SNGSS7_FLAG_CONFIGURED);
}
}
/* next link */
x++;
cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
} /* while (g_ftdm_sngss7_data.cfg.cc_isup[x]->id != 0) */
SS7_DEBUG("Finished LibSngSS7 configuration...\n");
return FTDM_SUCCESS;
return 0;
}
/******************************************************************************/
static int ftmod_ss7_general_configuration(void)
static int ftmod_ss7_enable_isap(int suId)
{
CcMngmt cntrl;
Pst pst;
if(sng_cfg_mtp1_gen(&g_ftdm_sngss7_data.cfg)) {
SS7_ERROR("General configuration for MTP1 failed!\n");
return FTDM_FAIL;
} else {
SS7_INFO("General configuration for MTP1 was successful\n");
}
/* initalize the post structure */
smPstInit(&pst);
if(sng_cfg_mtp2_gen(&g_ftdm_sngss7_data.cfg)) {
SS7_ERROR("General configuration for MTP2 failed!\n");
return FTDM_FAIL;
} else {
SS7_INFO("General configuration for MTP2 was successful\n");
}
/* insert the destination Entity */
pst.dstEnt = ENTCC;
if(sng_cfg_mtp3_gen(&g_ftdm_sngss7_data.cfg)) {
SS7_ERROR("General configuration for MTP3 failed!\n");
return FTDM_FAIL;
} else {
SS7_INFO("General configuration for MTP3 was successful\n");
}
/* initalize the control structure */
memset(&cntrl, 0x0, sizeof(CcMngmt));
if(sng_cfg_isup_gen(&g_ftdm_sngss7_data.cfg)) {
SS7_ERROR("General configuration for ISUP failed!\n");
return FTDM_FAIL;
} else {
SS7_INFO("General configuration for ISUP was successful\n");
}
/* initalize the control header */
smHdrInit(&cntrl.hdr);
if(sng_cfg_cc_gen(&g_ftdm_sngss7_data.cfg)) {
SS7_ERROR("General configuration for Call-Control failed!\n");
return FTDM_FAIL;
} else {
SS7_INFO("General configuration for Call-Control was successful\n");
}
cntrl.hdr.msgType = TCNTRL; /* this is a control request */
cntrl.hdr.entId.ent = ENTCC;
cntrl.hdr.entId.inst = S_INST;
cntrl.hdr.elmId.elmnt = STISAP;
return FTDM_SUCCESS;
cntrl.hdr.elmId.elmntInst1 = suId; /* this is the SAP to bind */
cntrl.t.cntrl.action = ABND_ENA; /* bind and activate */
cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */
return (sng_cntrl_cc(&pst, &cntrl));
}
/******************************************************************************/
static int ftmod_ss7_configure_mtp1_link(int id)
static int ftmod_ss7_enable_nsap(int suId)
{
if(sng_cfg_mtp1_link(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
SiMngmt cntrl;
Pst pst;
/* initalize the post structure */
smPstInit(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTSI;
/* initalize the control structure */
memset(&cntrl, 0x0, sizeof(SiMngmt));
/* initalize the control header */
smHdrInit(&cntrl.hdr);
cntrl.hdr.msgType = TCNTRL; /* this is a control request */
cntrl.hdr.entId.ent = ENTSI;
cntrl.hdr.entId.inst = S_INST;
cntrl.hdr.elmId.elmnt = STNSAP;
cntrl.t.cntrl.s.siElmnt.elmntId.sapId = suId;
cntrl.t.cntrl.s.siElmnt.elmntParam.nsap.nsapType = SAP_MTP;
cntrl.t.cntrl.action = ABND_ENA; /* bind and activate */
cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */
return (sng_cntrl_isup(&pst, &cntrl));
}
/******************************************************************************/
static int ftmod_ss7_configure_mtp2_link(int id)
static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId)
{
if(sng_cfg_mtp2_link(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
SnMngmt cntrl;
Pst pst;
/* initalize the post structure */
smPstInit(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTSN;
/* initalize the control structure */
memset(&cntrl, 0x0, sizeof(SnMngmt));
/* initalize the control header */
smHdrInit(&cntrl.hdr);
cntrl.hdr.msgType = TCNTRL; /* this is a control request */
cntrl.hdr.entId.ent = ENTSN;
cntrl.hdr.entId.inst = S_INST;
cntrl.hdr.elmId.elmnt = STLNKSET;
cntrl.hdr.elmId.elmntInst1 = lnkSetId; /* this is the linkset to bind */
cntrl.t.cntrl.action = ABND_ENA; /* bind and activate */
cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */
return (sng_cntrl_mtp3(&pst, &cntrl));
}
/******************************************************************************/
static int ftmod_ss7_configure_mtp3_link(int id)
int ftmod_ss7_inhibit_mtplink(uint32_t id)
{
if(sng_cfg_mtp3_link(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
SnMngmt cntrl;
Pst pst;
/* initalize the post structure */
smPstInit(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTSN;
/* initalize the control structure */
memset(&cntrl, 0x0, sizeof(SnMngmt));
/* initalize the control header */
smHdrInit(&cntrl.hdr);
cntrl.hdr.msgType = TCNTRL; /* this is a control request */
cntrl.hdr.entId.ent = ENTSN;
cntrl.hdr.entId.inst = S_INST;
cntrl.hdr.elmId.elmnt = STDLSAP;
cntrl.hdr.elmId.elmntInst1 = id; /* the DSLAP to inhibit */
cntrl.t.cntrl.action = AINH; /* Inhibit */
cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */
return (sng_cntrl_mtp3(&pst, &cntrl));
}
/******************************************************************************/
static int ftmod_ss7_configure_mtp3_linkset(int id)
int ftmod_ss7_uninhibit_mtplink(uint32_t id)
{
if(sng_cfg_mtp3_linkset(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
}
SnMngmt cntrl;
Pst pst;
/******************************************************************************/
static int ftmod_ss7_configure_mtp3_route(int id)
{
if(sng_cfg_mtp3_route(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
}
/* initalize the post structure */
smPstInit(&pst);
/******************************************************************************/
static int ftmod_ss7_configure_mtp3_isup(int id)
{
if(sng_cfg_mtp3_isup_interface(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
}
/* insert the destination Entity */
pst.dstEnt = ENTSN;
/******************************************************************************/
static int ftmod_ss7_configure_isup_mtp3(int id)
{
if(sng_cfg_isup_mtp3_interface(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
}
/* initalize the control structure */
memset(&cntrl, 0x0, sizeof(SnMngmt));
/******************************************************************************/
static int ftmod_ss7_configure_isup_interface(int id)
{
if(sng_cfg_isup_interface(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
}
/* initalize the control header */
smHdrInit(&cntrl.hdr);
/******************************************************************************/
static int ftmod_ss7_configure_isup_circuit(int id)
{
if(sng_cfg_isup_circuit(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
}
cntrl.hdr.msgType = TCNTRL; /* this is a control request */
cntrl.hdr.entId.ent = ENTSN;
cntrl.hdr.entId.inst = S_INST;
cntrl.hdr.elmId.elmnt = STDLSAP;
cntrl.hdr.elmId.elmntInst1 = id; /* the DSLAP to inhibit */
/******************************************************************************/
static int ftmod_ss7_configure_isup_cc(int id)
{
if(sng_cfg_isup_cc_interface(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
}
cntrl.t.cntrl.action = AUNINH; /* Inhibit */
cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */
/******************************************************************************/
static int ftmod_ss7_configure_cc_isup(int id)
{
if(sng_cfg_cc_isup_interface(&g_ftdm_sngss7_data.cfg, id)){
return FTDM_FAIL;
} else {
return FTDM_SUCCESS;
}
return (sng_cntrl_mtp3(&pst, &cntrl));
}
/******************************************************************************/
/* For Emacs:
* Local Variables:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,592 @@
/*
* Copyright (c) 2009|Konrad Hammel <konrad@sangoma.com>
* 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 *****************************************************************/
void handle_sng_log(uint8_t level, char *fmt,...);
void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta);
void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
void handle_sng_log(uint8_t level, char *fmt,...)
{
char *data;
int ret;
va_list ap;
va_start(ap, fmt);
ret = vasprintf(&data, fmt, ap);
if (ret == -1) {
return;
}
switch (level) {
/**************************************************************************/
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_WARN:
ftdm_log(FTDM_LOG_WARNING, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_CRIT:
/*printf("%s",data);*/
ftdm_log(FTDM_LOG_CRIT, "sng_ss7->%s", data);
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
}
return;
}
/******************************************************************************/
void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta)
{
} /* handle_mtp1_alarm */
/******************************************************************************/
void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
{
switch (sta->t.usta.alarm.category) {
/**************************************************************************/
case (LCM_CATEGORY_PROTOCOL):
case (LCM_CATEGORY_INTERFACE):
switch (sta->t.usta.alarm.event) {
/**********************************************************************/
case (LSD_EVENT_ENTR_CONG):
case (LSD_EVENT_EXIT_CONG):
case (LSD_EVENT_PROT_ST_UP):
case (LSD_EVENT_PROT_ST_DN):
case (LSD_EVENT_LINK_ALIGNED):
case (LSD_EVENT_REMOTE_CONG_START):
case (LSD_EVENT_REMOTE_CONG_END):
case (LSD_EVENT_RX_REMOTE_SIPO):
switch (sta->t.usta.alarm.cause) {
/******************************************************************/
case (LCM_CAUSE_UNKNOWN):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
break;
/******************************************************************/
case (LCM_CAUSE_MGMT_INITIATED):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d][MGMT] %s\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
break;
/******************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s (***unknown cause***)\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
break;
/******************************************************************/
} /* switch (sta->t.usta.alarm.cause) */
break;
/**********************************************************************/
case (LSD_EVENT_PROT_ERR):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause));
break;
/**********************************************************************/
case (LSD_EVENT_ALIGN_LOST):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
break;
/**********************************************************************/
case (LSD_EVENT_RTB_FULL):
case (LSD_EVENT_RTB_FULL_OVER):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.evntParm[1],
sta->t.usta.evntParm[2],
sta->t.usta.evntParm[3],
sta->t.usta.evntParm[4]);
break;
/**********************************************************************/
case (LSD_EVENT_NEG_ACK):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.evntParm[1]);
break;
/**********************************************************************/
case (LSD_EVENT_DAT_CFM_SDT):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %d\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
break;
/**********************************************************************/
case (LCM_EVENT_UI_INV_EVT):
case (LCM_EVENT_LI_INV_EVT):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0]);
break;
/**********************************************************************/
case (LCM_EVENT_INV_EVT):
switch (sta->t.usta.alarm.cause) {
/******************************************************************/
case (LCM_CAUSE_UNKNOWN):
case (LCM_CAUSE_SWVER_NAVAIL):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Event (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0]);
break;
/******************************************************************/
case (LCM_CAUSE_DECODE_ERR):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)|Version (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0],
sta->t.usta.evntParm[1]);
break;
/******************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.alarm.cause);
break;
/******************************************************************/
} /* switch (sta->t.usta.alarm.cause) */
break;
/**********************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.alarm.cause);
break;
/**********************************************************************/
} /* switch (sta->t.usta.alarm.event) */
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2] Unknown alarm category %d\n",
sta->t.usta.alarm.category);
break;
/**************************************************************************/
} /* switch(sta->t.usta.alarm.category) */
return;
} /* handle_mtp2_alarm */
/******************************************************************************/
void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
{
switch (sta->hdr.elmId.elmnt) {
/**************************************************************************/
case (STDLSAP):
switch (sta->t.usta.alarm.event) {
/**********************************************************************/
case (LSN_EVENT_INV_OPC_OTHER_END):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : OPC(0x%X%X%X%X)\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[3],
sta->t.usta.evntParm[2],
sta->t.usta.evntParm[1],
sta->t.usta.evntParm[0]);
break;
/**********************************************************************/
case (LSN_EVENT_INV_SLC_OTHER_END):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : SLC(%d)\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0]);
break;
/**********************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s(%d) : %s(%d)\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.alarm.cause);
break;
/**********************************************************************/
} /* sta->t.usta.alarm.event */
break;
/**************************************************************************/
case (STNSAP):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
break;
/**************************************************************************/
case (STLNKSET):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][LNKSET:%d] %s : %s\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
break;
/**************************************************************************/
case (STROUT):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%d%d%d%d] %s : %s\n",
sta->t.usta.evntParm[0],
sta->t.usta.evntParm[1],
sta->t.usta.evntParm[2],
sta->t.usta.evntParm[3],
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP3] %s(%d) : %s(%d)\n",
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.alarm.cause);
break;
/**************************************************************************/
} /* switch (sta->hdr.elmId.elmnt) */
return;
} /* handle_mtp3_alarm */
/******************************************************************************/
void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
{
char msg[250];
char tmp[25];
char *p = NULL;
int x = 0;
/* initalize the msg variable to NULLs */
memset(&msg[0], '\0', sizeof(&msg));
/* point p to the first spot in msg */
p = &msg[0];
p = strcat(p, "[ISUP]");
/* go through the dgnVals */
for (x = 0; x < 5; x++) {
switch (sta->t.usta.dgn.dgnVal[x].type) {
/**********************************************************************/
case (LSI_USTA_DGNVAL_NONE):
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_EVENT):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[EVENT:%d]",sta->t.usta.dgn.dgnVal[x].t.event);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SPID):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SPID:%d]",sta->t.usta.dgn.dgnVal[x].t.spId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SUID):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SUID:%d]",sta->t.usta.dgn.dgnVal[x].t.suId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SPINSTID):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SPINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.spInstId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SUINSTID):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SUINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.suInstId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_CIRCUIT):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[CKT:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cirId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_CIC):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[CIC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cic);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_INTF):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[INTF:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.intfId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_DPC):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[DPC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.dpc);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_ADDRS):
#if 0
/*
*typedef struct addrs
*{
*U8 length;
*U8 strg[ADRLEN];
*} Addrs;
*/
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[ADDRS:%d]",sta->t.usta.dgn.dgnVal[x].t.);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
#endif
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SWTCH):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SWTCH:%d]",sta->t.usta.dgn.dgnVal[x].t.swtch);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_RANGE):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[RANGE:0x%X]",sta->t.usta.dgn.dgnVal[x].t.range);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_STATUS_OCTS):
#if 0
/*
*typedef struct addrs
*{
*U8 length;
*U8 strg[ADRLEN];
*} Addrs;
*/
/* init tmp with NULLs */
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[STATUS_OCT:0x%X]",sta->t.usta.dgn.dgnVal[x].t.);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
#endif
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_VER):
#ifdef SI_RUG
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[VER:%d]",sta->t.usta.dgn.dgnVal[x].t.intfVer);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
#endif
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_TIMER):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[TIMER:0x%X]",sta->t.usta.dgn.dgnVal[x].t.tmrInfo);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_MSGTYPE):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[MSGTYPE:%d]",sta->t.usta.dgn.dgnVal[x].t.msgType);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_STATE):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[STATE:%d]",sta->t.usta.dgn.dgnVal[x].t.state);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
default:
break;
/**********************************************************************/
} /* switch (sta->t.usta.dgn.dgnVal[x].t.type) */
} /* for (x = 0; x < 5; x++) */
ftdm_log(FTDM_LOG_ERROR,"%s %s : %s\n",
msg,
DECODE_LSI_EVENT(sta->t.usta.alarm.event),
DECODE_LSI_CAUSE(sta->t.usta.alarm.cause));
} /* handle_isup_alarm */
/******************************************************************************/
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
{
return;
} /* handle_cc_alarm */
/******************************************************************************/
/******************************************************************************/
/* 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:
*/
/******************************************************************************/

View File

@ -44,58 +44,273 @@
#include <ctype.h>
#include "private/ftdm_core.h"
/*
#include "sng_sit.h"
#include "sng_ss7_error.h"
*/
#include "sng_ss7.h"
/******************************************************************************/
/* DEFINES ********************************************************************/
#define MAX_CIC_LENGTH 5
#define MAX_CIC_MAP_LENGTH 256
#define MAX_MTP_LINKS MAX_SN_LINKSETS
#define MAX_NAME_LEN 10
#define MAX_PATH 255
#define MAX_CIC_LENGTH 5
#define MAX_CIC_MAP_LENGTH 1000
#if 0
#define SS7_HARDCODED
#endif
#define SNG_BASE 1
typedef enum {
SNG_IAM = 1,
SNG_ACM,
SNG_CPG,
SNG_ANM,
SNG_REL,
SNG_RLC
}sng_msg_type_t;
VOICE = 0,
SIG,
HOLE
} sng_ckt_type_t;
typedef enum {
CONFIGURED = (1 << 0),
ACTIVE = (1 << 1)
} sng_flag_t;
typedef struct sng_mtp_link {
char name[MAX_NAME_LEN];
uint32_t id;
uint32_t flags;
struct {
uint32_t span;
uint32_t chan;
} mtp1;
struct {
uint32_t lssuLength;
uint32_t errorType;
uint32_t linkType;
uint32_t mtp1Id;
uint32_t t1;
uint32_t t2;
uint32_t t3;
uint32_t t4n;
uint32_t t4e;
uint32_t t5;
uint32_t t6;
uint32_t t7;
} mtp2;
struct {
uint32_t priority;
uint32_t linkType;
uint32_t switchType;
uint32_t apc;
uint32_t spc;
uint32_t ssf;
uint32_t slc;
uint32_t linkSetId;
uint32_t mtp2Id;
uint32_t t1;
uint32_t t2;
uint32_t t3;
uint32_t t4;
uint32_t t5;
uint32_t t6;
uint32_t t7;
uint32_t t8;
uint32_t t9;
uint32_t t10;
uint32_t t11;
uint32_t t12;
uint32_t t13;
uint32_t t14;
uint32_t t15;
uint32_t t16;
uint32_t t17;
uint32_t t18;
uint32_t t19;
uint32_t t20;
uint32_t t21;
uint32_t t22;
uint32_t t23;
uint32_t t24;
uint32_t t25;
uint32_t t26;
uint32_t t27;
uint32_t t28;
uint32_t t29;
uint32_t t30;
uint32_t t31;
uint32_t t32;
uint32_t t33;
uint32_t t34;
uint32_t t35;
uint32_t t36;
uint32_t t37;
uint32_t tcraft;
uint32_t tflc;
uint32_t tbnd;
} mtp3;
} sng_mtp_link_t;
typedef struct sng_link_set {
uint32_t id;
char name[MAX_NAME_LEN];
uint32_t flags;
uint32_t apc;
uint32_t linkType;
uint32_t minActive;
uint32_t numLinks;
uint32_t links[16];
} sng_link_set_t;
typedef struct sng_route {
uint32_t id;
char name[MAX_NAME_LEN];
uint32_t flags;
uint32_t dpc;
uint32_t cmbLinkSetId;
uint32_t linkType;
uint32_t switchType;
uint32_t ssf;
uint32_t isSTP;
uint32_t t6;
uint32_t t8;
uint32_t t10;
uint32_t t11;
uint32_t t15;
uint32_t t16;
uint32_t t18;
uint32_t t19;
uint32_t t21;
uint32_t t25;
} sng_route_t;
typedef struct sng_isup_intf {
uint32_t id;
char name[MAX_NAME_LEN];
uint32_t flags;
uint32_t spc;
uint32_t dpc;
uint32_t switchType;
uint32_t nwId;
uint32_t mtpRouteId;
uint32_t ssf;
uint32_t isap;
uint16_t t4;
uint32_t t10;
uint32_t t11;
uint32_t t18;
uint32_t t19;
uint32_t t20;
uint32_t t21;
uint32_t t22;
uint32_t t23;
uint32_t t24;
uint32_t t25;
uint32_t t26;
uint32_t t28;
uint32_t t29;
uint32_t t30;
uint32_t t32;
uint32_t t35;
uint32_t t37;
uint32_t t38;
uint32_t t39;
uint32_t tfgr;
uint32_t tpause;
uint32_t tstaenq;
} sng_isup_inf_t;
typedef struct sng_isup_ckt {
uint32_t id;
uint32_t flags;
uint32_t span;
uint32_t chan;
uint32_t type; /* VOICE/SIG/HOLE */
uint32_t cic;
uint32_t infId;
uint32_t ssf;
uint32_t typeCntrl;
void *obj;
uint16_t t3;
uint16_t t12;
uint16_t t13;
uint16_t t14;
uint16_t t15;
uint16_t t16;
uint16_t t17;
uint16_t tval;
} sng_isup_ckt_t;
typedef struct sng_nsap {
uint32_t id;
uint32_t flags;
uint32_t suId;
uint32_t spId;
uint32_t nwId;
uint32_t linkType;
uint32_t switchType;
uint32_t ssf;
} sng_nsap_t;
typedef struct sng_isap {
uint32_t id;
uint32_t suId;
uint32_t spId;
uint32_t switchType;
uint32_t ssf;
uint32_t flags;
uint32_t t1;
uint32_t t2;
uint32_t t5;
uint32_t t6;
uint32_t t7;
uint32_t t8;
uint32_t t9;
uint32_t t27;
uint32_t t31;
uint32_t t33;
uint32_t t34;
uint32_t t36;
uint32_t tccr;
uint32_t tccrt;
uint32_t tex;
uint32_t tcrm;
uint32_t tcra;
uint32_t tect;
uint32_t trelrsp;
uint32_t tfnlrelrsp;
} sng_isap_t;
typedef struct sng_ss7_cfg {
uint32_t spc;
char license[MAX_PATH];
char signature[MAX_PATH];
sng_mtp_link_t mtpLink[MAX_MTP_LINKS+1];
sng_link_set_t mtpLinkSet[MAX_MTP_LINKSETS+1];
sng_route_t mtpRoute[MAX_MTP_ROUTES+1];
sng_isup_inf_t isupIntf[MAX_ISUP_INFS+1];
sng_isup_ckt_t isupCkt[MAX_ISUP_CKTS+1];
sng_nsap_t nsap[MAX_NSAPS+1];
sng_isap_t isap[MAX_ISAPS+1];
}sng_ss7_cfg_t;
typedef struct ftdm_sngss7_data {
sng_config_t cfg;
int gen_config_done;
int min_digits;
int function_trace;
int function_trace_level;
int message_trace;
int message_trace_level;
fio_signal_cb_t sig_cb;
sng_ss7_cfg_t cfg;
int gen_config;
int min_digits;
int function_trace;
int function_trace_level;
int message_trace;
int message_trace_level;
fio_signal_cb_t sig_cb;
}ftdm_sngss7_data_t;
typedef struct sngss7_timer_data {
ftdm_timer_t *heartbeat_timer;
int beat;
int counter;
ftdm_sched_callback_t callback;
ftdm_sched_t *sched;
void *sngss7_info;
ftdm_timer_t *heartbeat_timer;
int beat;
int counter;
ftdm_sched_callback_t callback;
ftdm_sched_t *sched;
void *sngss7_info;
}sngss7_timer_data_t;
typedef struct sngss7_glare_data {
uint32_t suInstId;
uint32_t spInstId;
uint32_t circuit;
SiConEvnt iam;
uint32_t suInstId;
uint32_t spInstId;
uint32_t circuit;
SiConEvnt iam;
}sngss7_glare_data_t;
typedef struct sngss7_group_data {
@ -104,56 +319,99 @@ typedef struct sngss7_group_data {
}sngss7_group_data_t;
typedef struct sngss7_chan_data {
ftdm_channel_t *ftdmchan;
sng_isupCircuit_t *circuit;
uint32_t suInstId;
uint32_t spInstId;
uint32_t spId;
uint8_t globalFlg;
uint32_t flags;
sngss7_glare_data_t glare;
sngss7_timer_data_t t35;
sngss7_group_data_t grs;
ftdm_channel_t *ftdmchan;
sng_isup_ckt_t *circuit;
uint32_t base_chan;
uint32_t suInstId;
uint32_t spInstId;
uint32_t spId;
uint8_t globalFlg;
uint32_t flags;
sngss7_glare_data_t glare;
sngss7_timer_data_t t35;
}sngss7_chan_data_t;
typedef struct sngss7_span_data {
ftdm_sched_t *sched;
sngss7_group_data_t grs;
}sngss7_span_data_t;
typedef enum {
FLAG_RESET_RX = (1 << 0),
FLAG_RESET_TX = (1 << 1),
FLAG_GRP_RESET_RX = (1 << 2),
FLAG_GRP_RESET_TX = (1 << 3),
FLAG_REMOTE_REL = (1 << 4),
FLAG_LOCAL_REL = (1 << 5),
FLAG_GLARE = (1 << 6),
FLAG_INFID_RESUME = (1 << 17),
FLAG_INFID_PAUSED = (1 << 18),
FLAG_CKT_MN_BLOCK_RX = (1 << 19),
FLAG_CKT_MN_BLOCK_TX = (1 << 20),
FLAG_CKT_MN_UNBLK_RX = (1 << 21),
FLAG_CKT_MN_UNBLK_TX = (1 << 22),
FLAG_GRP_HW_BLOCK_RX = (1 << 23),
FLAG_GRP_HW_BLOCK_TX = (1 << 24),
FLAG_GRP_MN_BLOCK_RX = (1 << 25),
FLAG_GRP_MN_BLOCK_TX = (1 << 28),
FLAG_GRP_HW_UNBLK_RX = (1 << 27),
FLAG_GRP_HW_UNBLK_TX = (1 << 28),
FLAG_GRP_MN_UNBLK_RX = (1 << 29),
FLAG_GRP_MN_UNBLK_TX = (1 << 30)
FLAG_RESET_RX = (1 << 0),
FLAG_RESET_TX = (1 << 1),
FLAG_RESET_SENT = (1 << 2),
FLAG_RESET_TX_RSP = (1 << 3),
FLAG_GRP_RESET_RX = (1 << 4),
FLAG_GRP_RESET_RX_DN = (1 << 5),
FLAG_GRP_RESET_RX_CMPLT = (1 << 6),
FLAG_GRP_RESET_BASE = (1 << 7),
FLAG_GRP_RESET_TX = (1 << 8),
FLAG_GRP_RESET_SENT = (1 << 9),
FLAG_GRP_RESET_TX_RSP = (1 << 10),
FLAG_REMOTE_REL = (1 << 11),
FLAG_LOCAL_REL = (1 << 12),
FLAG_GLARE = (1 << 13),
FLAG_INFID_RESUME = (1 << 14),
FLAG_INFID_PAUSED = (1 << 15),
FLAG_CKT_UCIC_BLOCK = (1 << 16),
FLAG_CKT_UCIC_UNBLK = (1 << 17),
FLAG_CKT_LC_BLOCK_RX = (1 << 18),
FLAG_CKT_LC_UNBLK_RX = (1 << 19),
FLAG_CKT_MN_BLOCK_RX = (1 << 20),
FLAG_CKT_MN_BLOCK_TX = (1 << 21),
FLAG_CKT_MN_UNBLK_RX = (1 << 22),
FLAG_CKT_MN_UNBLK_TX = (1 << 23),
FLAG_GRP_HW_BLOCK_RX = (1 << 24),
FLAG_GRP_HW_BLOCK_TX = (1 << 25),
FLAG_GRP_MN_BLOCK_RX = (1 << 26),
FLAG_GRP_MN_BLOCK_TX = (1 << 27),
FLAG_GRP_HW_UNBLK_RX = (1 << 28),
FLAG_GRP_HW_UNBLK_TX = (1 << 29),
FLAG_GRP_MN_UNBLK_RX = (1 << 30),
FLAG_GRP_MN_UNBLK_TX = (1 << 31)
} flag_t;
/******************************************************************************/
/* GLOBALS ********************************************************************/
extern ftdm_sngss7_data_t g_ftdm_sngss7_data;
extern uint32_t sngss7_id;
extern ftdm_sched_t *sngss7_sched;
extern uint32_t sngss7_id;
extern ftdm_sched_t *sngss7_sched;
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
void handle_sng_log(uint8_t level, char *fmt,...);
void handle_sng_alarm(sng_alrm_t t_alarm);
void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta);
void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
int ft_to_sngss7_cfg_all(void);
int ftmod_ss7_mtp1_gen_config(void);
int ftmod_ss7_mtp2_gen_config(void);
int ftmod_ss7_mtp3_gen_config(void);
int ftmod_ss7_isup_gen_config(void);
int ftmod_ss7_cc_gen_config(void);
int ftmod_ss7_mtp1_psap_config(int id);
int ftmod_ss7_mtp2_dlsap_config(int id);
int ftmod_ss7_mtp3_dlsap_config(int id);
int ftmod_ss7_mtp3_nsap_config(int id);
int ftmod_ss7_mtp3_linkset_config(int id);
int ftmod_ss7_mtp3_route_config(int id);
int ftmod_ss7_isup_nsap_config(int id);
int ftmod_ss7_isup_intf_config(int id);
int ftmod_ss7_isup_ckt_config(int id);
int ftmod_ss7_isup_isap_config(int id);
int ftmod_ss7_cc_isap_config(int id);
int ftmod_ss7_inhibit_mtplink(uint32_t id);
int ftmod_ss7_uninhibit_mtplink(uint32_t id);
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm);
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
int ft_to_sngss7_cfg(void);
int ft_to_sngss7_activate_all(void);
void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan);
@ -169,6 +427,7 @@ void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_grs(ftdm_channel_t *ftdmchan);
void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt);
@ -188,6 +447,8 @@ uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum
uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
int check_for_state_change(ftdm_channel_t *ftdmchan);
int check_cics_in_range(sngss7_chan_data_t *sngss7_info);
int check_for_reset(sngss7_chan_data_t *sngss7_info);
ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
unsigned long get_unique_id(void);
@ -199,11 +460,17 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
/******************************************************************************/
/* MACROS *********************************************************************/
#define SS7_DEBUG(a,...) ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ );
#define SS7_INFO(a,...) ftdm_log(FTDM_LOG_INFO,a,##__VA_ARGS__ );
#define SS7_WARN(a,...) ftdm_log(FTDM_LOG_WARNING,a,##__VA_ARGS__ );
#define SS7_ERROR(a,...) ftdm_log(FTDM_LOG_ERROR,a,##__VA_ARGS__ );
#define SS7_CRITICAL(a,...) ftdm_log(FTDM_LOG_CRIT,a,##__VA_ARGS__ );
#define SS7_DEBUG(a,...) ftdm_log(FTDM_LOG_DEBUG,a , ##__VA_ARGS__ );
#define SS7_INFO(a,...) ftdm_log(FTDM_LOG_INFO,a , ##__VA_ARGS__ );
#define SS7_WARN(a,...) ftdm_log(FTDM_LOG_WARNING,a , ##__VA_ARGS__ );
#define SS7_ERROR(a,...) ftdm_log(FTDM_LOG_ERROR,a , ##__VA_ARGS__ );
#define SS7_CRITICAL(a,...) ftdm_log(FTDM_LOG_CRIT,a , ##__VA_ARGS__ );
#define SS7_DEBUG_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_DEBUG, msg , ##args)
#define SS7_INFO_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_INFO, msg , ##args)
#define SS7_WARN_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_WARNING, msg , ##args)
#define SS7_ERROR_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_ERROR, msg , ##args)
#define SS7_CTRIT_CHAN(fchan, msg, args...) ftdm_log_chan(fchan, FTDM_LOG_CRIT, msg , ##args)
#ifdef KONRAD_DEVEL
#define SS7_DEVEL_DEBUG(a,...) ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ );
@ -212,107 +479,121 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
#endif
#define SS7_FUNC_TRACE_ENTER(a) if (g_ftdm_sngss7_data.function_trace) { \
switch (g_ftdm_sngss7_data.function_trace_level) { \
case 0: \
ftdm_log(FTDM_LOG_EMERG,"Entering %s\n", a); \
break; \
case 1: \
ftdm_log(FTDM_LOG_ALERT,"Entering %s\n", a); \
break; \
case 2: \
ftdm_log(FTDM_LOG_CRIT,"Entering %s\n", a); \
break; \
case 3: \
ftdm_log(FTDM_LOG_ERROR,"Entering %s\n", a); \
break; \
case 4: \
ftdm_log(FTDM_LOG_WARNING,"Entering %s\n", a); \
break; \
case 5: \
ftdm_log(FTDM_LOG_NOTICE,"Entering %s\n", a); \
break; \
case 6: \
ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \
break; \
case 7: \
ftdm_log(FTDM_LOG_DEBUG,"Entering %s\n", a); \
break; \
default: \
ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \
break; \
} /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
} /* if(g_ftdm_sngss7_data.function_trace) */
switch (g_ftdm_sngss7_data.function_trace_level) { \
case 0: \
ftdm_log(FTDM_LOG_EMERG,"Entering %s\n", a); \
break; \
case 1: \
ftdm_log(FTDM_LOG_ALERT,"Entering %s\n", a); \
break; \
case 2: \
ftdm_log(FTDM_LOG_CRIT,"Entering %s\n", a); \
break; \
case 3: \
ftdm_log(FTDM_LOG_ERROR,"Entering %s\n", a); \
break; \
case 4: \
ftdm_log(FTDM_LOG_WARNING,"Entering %s\n", a); \
break; \
case 5: \
ftdm_log(FTDM_LOG_NOTICE,"Entering %s\n", a); \
break; \
case 6: \
ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \
break; \
case 7: \
ftdm_log(FTDM_LOG_DEBUG,"Entering %s\n", a); \
break; \
default: \
ftdm_log(FTDM_LOG_INFO,"Entering %s\n", a); \
break; \
} /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
} /* if(g_ftdm_sngss7_data.function_trace) */
#define SS7_FUNC_TRACE_EXIT(a) if (g_ftdm_sngss7_data.function_trace) { \
switch (g_ftdm_sngss7_data.function_trace_level) { \
case 0: \
ftdm_log(FTDM_LOG_EMERG,"Exitting %s\n", a); \
break; \
case 1: \
ftdm_log(FTDM_LOG_ALERT,"Exitting %s\n", a); \
break; \
case 2: \
ftdm_log(FTDM_LOG_CRIT,"Exitting %s\n", a); \
break; \
case 3: \
ftdm_log(FTDM_LOG_ERROR,"Exitting %s\n", a); \
break; \
case 4: \
ftdm_log(FTDM_LOG_WARNING,"Exitting %s\n", a); \
break; \
case 5: \
ftdm_log(FTDM_LOG_NOTICE,"Exitting %s\n", a); \
break; \
case 6: \
ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
break; \
case 7: \
ftdm_log(FTDM_LOG_DEBUG,"Exitting %s\n", a); \
break; \
default: \
ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
break; \
} /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
} /* if(g_ftdm_sngss7_data.function_trace) */
switch (g_ftdm_sngss7_data.function_trace_level) { \
case 0: \
ftdm_log(FTDM_LOG_EMERG,"Exitting %s\n", a); \
break; \
case 1: \
ftdm_log(FTDM_LOG_ALERT,"Exitting %s\n", a); \
break; \
case 2: \
ftdm_log(FTDM_LOG_CRIT,"Exitting %s\n", a); \
break; \
case 3: \
ftdm_log(FTDM_LOG_ERROR,"Exitting %s\n", a); \
break; \
case 4: \
ftdm_log(FTDM_LOG_WARNING,"Exitting %s\n", a); \
break; \
case 5: \
ftdm_log(FTDM_LOG_NOTICE,"Exitting %s\n", a); \
break; \
case 6: \
ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
break; \
case 7: \
ftdm_log(FTDM_LOG_DEBUG,"Exitting %s\n", a); \
break; \
default: \
ftdm_log(FTDM_LOG_INFO,"Exitting %s\n", a); \
break; \
} /* switch (g_ftdm_sngss7_data.function_trace_level) */ \
} /* if(g_ftdm_sngss7_data.function_trace) */
#define SS7_MSG_TRACE(a,...) if (g_ftdm_sngss7_data.message_trace) { \
switch (g_ftdm_sngss7_data.message_trace_level) { \
case 0: \
ftdm_log(FTDM_LOG_EMERG,a,##__VA_ARGS__ ); \
break; \
case 1: \
ftdm_log(FTDM_LOG_ALERT,a,##__VA_ARGS__ ); \
break; \
case 2: \
ftdm_log(FTDM_LOG_CRIT,a,##__VA_ARGS__ ); \
break; \
case 3: \
ftdm_log(FTDM_LOG_ERROR,a,##__VA_ARGS__ ); \
break; \
case 4: \
ftdm_log(FTDM_LOG_WARNING,a,##__VA_ARGS__ ); \
break; \
case 5: \
ftdm_log(FTDM_LOG_NOTICE,a,##__VA_ARGS__ ); \
break; \
case 6: \
ftdm_log(FTDM_LOG_INFO,a,##__VA_ARGS__ ); \
break; \
case 7: \
ftdm_log(FTDM_LOG_DEBUG,a,##__VA_ARGS__ ); \
break; \
default: \
ftdm_log(FTDM_LOG_INFO,a,##__VA_ARGS__ ); \
break; \
} /* switch (g_ftdm_sngss7_data.message_trace_level) */ \
} /* if(g_ftdm_sngss7_data.message_trace) */
#define SS7_MSG_TRACE(fchan, sngss7info ,msg) if (g_ftdm_sngss7_data.message_trace) { \
switch (g_ftdm_sngss7_data.message_trace_level) { \
case 0: \
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
case 1: \
ftdm_log_chan(fchan, FTDM_LOG_ALERT, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
case 2: \
ftdm_log_chan(fchan, FTDM_LOG_CRIT, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
case 3: \
ftdm_log_chan(fchan, FTDM_LOG_ERROR, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
case 4: \
ftdm_log_chan(fchan, FTDM_LOG_WARNING, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
case 5: \
ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
case 6: \
ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
case 7: \
ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
default: \
ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d]%s",sngss7info->circuit->cic, msg); \
break; \
} /* switch (g_ftdm_sngss7_data.message_trace_level) */ \
} /* if(g_ftdm_sngss7_data.message_trace) */
#define sngss7_test_flag(obj, flag) ((obj)->flags & flag)
#define sngss7_clear_flag(obj, flag) ((obj)->flags &= ~(flag))
#define sngss7_set_flag(obj, flag) ((obj)->flags |= (flag))
# define SS7_ASSERT *(int*)0=0;
/******************************************************************************/
/******************************************************************************/
#endif /* __FTMOD_SNG_SS7_H__ */
/******************************************************************************/
/******************************************************************************/
/* 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:
*/
/******************************************************************************/

View File

@ -42,393 +42,444 @@
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_rsc(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rsca(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_blo(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_bla(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan);
void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan);
/* FUNCTIONS ******************************************************************/
void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan)
void
ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
SiConEvnt iam;
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;
sngss7_info->suInstId = get_unique_id ();
sngss7_info->spInstId = 0;
sngss7_info->spId = 1;
memset(&iam, 0x0, sizeof(iam));
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 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 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 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 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 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);
/* 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);
sng_cc_con_request (sngss7_info->spId,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id, &iam, 0);
SS7_MSG_TRACE("Transmitted IAM on CIC # %d\n", sngss7_info->circuit->cic);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx IAM\n");
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiCnStEvnt acm;
memset(&acm, 0x0, sizeof(acm));
/* fill in the needed information for the ACM */
acm.bckCallInd.eh.pres = PRSNT_NODEF;
acm.bckCallInd.chrgInd.pres = PRSNT_NODEF;
acm.bckCallInd.chrgInd.val = 0x00;
acm.bckCallInd.cadPtyStatInd.pres = PRSNT_NODEF;
acm.bckCallInd.cadPtyStatInd.val = 0x01;
acm.bckCallInd.cadPtyCatInd.pres = PRSNT_NODEF;
acm.bckCallInd.cadPtyCatInd.val = 0x00;
acm.bckCallInd.end2EndMethInd.pres = PRSNT_NODEF;
acm.bckCallInd.end2EndMethInd.val = 0x00;
acm.bckCallInd.intInd.pres = PRSNT_NODEF;
acm.bckCallInd.intInd.val = 0x00;
acm.bckCallInd.end2EndInfoInd.pres = PRSNT_NODEF;
acm.bckCallInd.end2EndInfoInd.val = 0x00;
acm.bckCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF;
acm.bckCallInd.isdnUsrPrtInd.val = 0x0;
acm.bckCallInd.holdInd.pres = PRSNT_NODEF;
acm.bckCallInd.holdInd.val = 0x00;
acm.bckCallInd.isdnAccInd.pres = PRSNT_NODEF;
acm.bckCallInd.isdnAccInd.val = 0x0;
acm.bckCallInd.echoCtrlDevInd.pres = PRSNT_NODEF;
acm.bckCallInd.echoCtrlDevInd.val = 0x0;
acm.bckCallInd.sccpMethInd.pres = PRSNT_NODEF;
acm.bckCallInd.sccpMethInd.val = 0x00;
/* send the ACM request to LibSngSS7 */
sng_cc_con_status(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&acm,
ADDRCMPLT);
SS7_MSG_TRACE("Transmitted ACM on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiConEvnt anm;
memset(&anm, 0x0, sizeof(anm));
/* send the ANM request to LibSngSS7 */
sng_cc_con_response(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&anm,
5);
SS7_MSG_TRACE("Transmitted ANM on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiRelEvnt rel;
memset(&rel, 0x0, sizeof(rel));
rel.causeDgn.eh.pres = PRSNT_NODEF;
rel.causeDgn.location.pres = PRSNT_NODEF;
rel.causeDgn.location.val = 0x01;
rel.causeDgn.cdeStand.pres = PRSNT_NODEF;
rel.causeDgn.cdeStand.val = 0x00;
rel.causeDgn.recommend.pres = NOTPRSNT;
rel.causeDgn.causeVal.pres = PRSNT_NODEF;
rel.causeDgn.causeVal.val = (uint8_t)ftdmchan->caller_data.hangup_cause;
rel.causeDgn.dgnVal.pres = NOTPRSNT;
/* send the REL request to LibSngSS7 */
sng_cc_rel_request(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&rel);
SS7_MSG_TRACE("Transmitted REL on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiCnStEvnt acm;
memset (&acm, 0x0, sizeof (acm));
/* fill in the needed information for the ACM */
acm.bckCallInd.eh.pres = PRSNT_NODEF;
acm.bckCallInd.chrgInd.pres = PRSNT_NODEF;
acm.bckCallInd.chrgInd.val = 0x00;
acm.bckCallInd.cadPtyStatInd.pres = PRSNT_NODEF;
acm.bckCallInd.cadPtyStatInd.val = 0x01;
acm.bckCallInd.cadPtyCatInd.pres = PRSNT_NODEF;
acm.bckCallInd.cadPtyCatInd.val = 0x00;
acm.bckCallInd.end2EndMethInd.pres = PRSNT_NODEF;
acm.bckCallInd.end2EndMethInd.val = 0x00;
acm.bckCallInd.intInd.pres = PRSNT_NODEF;
acm.bckCallInd.intInd.val = 0x00;
acm.bckCallInd.end2EndInfoInd.pres = PRSNT_NODEF;
acm.bckCallInd.end2EndInfoInd.val = 0x00;
acm.bckCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF;
acm.bckCallInd.isdnUsrPrtInd.val = 0x0;
acm.bckCallInd.holdInd.pres = PRSNT_NODEF;
acm.bckCallInd.holdInd.val = 0x00;
acm.bckCallInd.isdnAccInd.pres = PRSNT_NODEF;
acm.bckCallInd.isdnAccInd.val = 0x0;
acm.bckCallInd.echoCtrlDevInd.pres = PRSNT_NODEF;
acm.bckCallInd.echoCtrlDevInd.val = 0x0;
acm.bckCallInd.sccpMethInd.pres = PRSNT_NODEF;
acm.bckCallInd.sccpMethInd.val = 0x00;
/* send the ACM request to LibSngSS7 */
sng_cc_con_status (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&acm,
ADDRCMPLT);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ACM\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiConEvnt anm;
memset (&anm, 0x0, sizeof (anm));
/* send the ANM request to LibSngSS7 */
sng_cc_con_response(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&anm,
5);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiRelEvnt rlc;
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ANM\n");
memset(&rlc, 0x0, sizeof(rlc));
/* send the RLC request to LibSngSS7 */
sng_cc_rel_response(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&rlc);
SS7_MSG_TRACE("Transmitted RLC on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_rsc(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRRESREQ,
NULL);
SS7_MSG_TRACE("Transmitted RSC on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiRelEvnt rel;
memset (&rel, 0x0, sizeof (rel));
rel.causeDgn.eh.pres = PRSNT_NODEF;
rel.causeDgn.location.pres = PRSNT_NODEF;
rel.causeDgn.location.val = 0x01;
rel.causeDgn.cdeStand.pres = PRSNT_NODEF;
rel.causeDgn.cdeStand.val = 0x00;
rel.causeDgn.recommend.pres = NOTPRSNT;
rel.causeDgn.causeVal.pres = PRSNT_NODEF;
rel.causeDgn.causeVal.val = (uint8_t) ftdmchan->caller_data.hangup_cause;
rel.causeDgn.dgnVal.pres = NOTPRSNT;
/* send the REL request to LibSngSS7 */
sng_cc_rel_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&rel);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx REL\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_rsca(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRRESRSP,
NULL);
SS7_MSG_TRACE("Transmitted RSC-RLC on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiRelEvnt rlc;
memset (&rlc, 0x0, sizeof (rlc));
/* send the RLC request to LibSngSS7 */
sng_cc_rel_response (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&rlc);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RLC\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_blo(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request(1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRBLOREQ,
NULL);
SS7_MSG_TRACE("Transmitted BLO on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRRESREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_bla(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request(1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRBLORSP,
NULL);
SS7_MSG_TRACE("Transmitted BLA on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRRESRSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC-RLC\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request(1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRUBLREQ,
NULL);
SS7_MSG_TRACE("Transmitted UBL on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request (1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRBLOREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLO\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request(1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRUBLRSP,
NULL);
SS7_MSG_TRACE("Transmitted UBA on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request (1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRBLORSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLA\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan)
void
ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request(1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_LOOPBACKACK,
NULL);
SS7_MSG_TRACE("Transmitted LPA on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request (1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRUBLREQ,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBL\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan)
void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
/* get the original channel the message came in on */
sngss7_info = g_ftdm_sngss7_data.cfg.isupCircuit[sngss7_info->grs.circuit].obj;
sng_cc_sta_request(1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_GRSRSP,
NULL);
SS7_MSG_TRACE("Transmitted GRA on CIC # %d\n", sngss7_info->circuit->cic);
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request (1,
0,
0,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_CIRUBLRSP,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBA\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
sng_cc_sta_request (1,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
sngss7_info->globalFlg,
SIT_STA_LOOPBACKACK,
NULL);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx LPA\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_span_data_t *span = ftdmchan->span->mod_data;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiStaEvnt gra;
/* clean out the gra struct */
memset (&gra, 0x0, sizeof (gra));
gra.rangStat.eh.pres = PRSNT_NODEF;
/* fill in the range */
gra.rangStat.range.pres = PRSNT_NODEF;
gra.rangStat.range.val = span->grs.range;
/* fill in the status */
gra.rangStat.status.pres = PRSNT_NODEF;
gra.rangStat.status.len = ((span->grs.range + 1) >> 3) + (((span->grs.range + 1) & 0x07) ? 1 : 0);
/* the status field should be 1 if blocked for maintenace reasons
* and 0 is not blocked....since we memset the struct nothing to do
*/
/* send the GRA to LibSng-SS7 */
sng_cc_sta_request (1,
0,
0,
span->grs.circuit,
0,
SIT_STA_GRSRSP,
&gra);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRA\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
ftdm_span_t *span = ftdmchan->span;
SiStaEvnt grs;
memset (&grs, 0x0, sizeof (grs));
grs.rangStat.eh.pres = PRSNT_NODEF;
grs.rangStat.range.pres = PRSNT_NODEF;
grs.rangStat.range.val = span->chan_count-1;
sng_cc_sta_request (1,
0,
0,
sngss7_info->circuit->id,
0,
SIT_STA_GRSREQ,
&grs);
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx GRS\n");
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
/* For Emacs:
* Local Variables:
@ -441,4 +492,3 @@ void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan)
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/
/******************************************************************************/

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2009 Konrad Hammel <konrad@sangoma.com>
* 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 *****************************************************************/
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm);
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm)
{
SnMngmt sta;
memset(&sta, 0x0, sizeof(sta));
sta.hdr.elmId.elmnt = STDLSAP;
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id;
return(sng_sta_mtp3(&sta, cfm));
}
/******************************************************************************/
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm)
{
SnMngmt sta;
memset(&sta, 0x0, sizeof(sta));
sta.hdr.elmId.elmnt = STLNKSET;
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id;
sta.hdr.elmId.elmntInst2 = 1;
return(sng_sta_mtp3(&sta, cfm));
}
/******************************************************************************/
/******************************************************************************/
/* 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:
*/
/******************************************************************************/

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2009 Konrad Hammel <konrad@sangoma.com>
* 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 *****************************************************************/
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
/******************************************************************************/
/******************************************************************************/
/* 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:
*/
/******************************************************************************/

View File

@ -50,6 +50,9 @@ uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum
uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
int check_for_state_change(ftdm_channel_t *ftdmchan);
int check_cics_in_range(sngss7_chan_data_t *sngss7_info);
int check_for_reset(sngss7_chan_data_t *sngss7_info);
unsigned long get_unique_id(void);
ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
@ -60,309 +63,391 @@ ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_in
uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
{
return 0;
return 0;
}
/******************************************************************************/
uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
{
int k;
int j;
int flag;
char tmp;
unsigned char lower;
unsigned char upper;
int k;
int j;
int flag;
char tmp[2];
unsigned char lower;
unsigned char upper;
/**************************************************************************/
cgPtyNum->eh.pres = PRSNT_NODEF;
/**************************************************************************/
cgPtyNum->natAddrInd.pres = PRSNT_NODEF;
cgPtyNum->natAddrInd.val = 0x03;
/**************************************************************************/
cgPtyNum->scrnInd.pres = PRSNT_NODEF;
cgPtyNum->scrnInd.val = ftdm->screen;
/**************************************************************************/
cgPtyNum->presRest.pres = PRSNT_NODEF;
cgPtyNum->presRest.val = ftdm->pres;
/**************************************************************************/
cgPtyNum->numPlan.pres = PRSNT_NODEF;
cgPtyNum->numPlan.val = 0x01;
/**************************************************************************/
cgPtyNum->niInd.pres = PRSNT_NODEF;
cgPtyNum->niInd.val = 0x00;
/**************************************************************************/
cgPtyNum->addrSig.pres = PRSNT_NODEF;
/**************************************************************************/
cgPtyNum->eh.pres = PRSNT_NODEF;
/**************************************************************************/
cgPtyNum->natAddrInd.pres = PRSNT_NODEF;
cgPtyNum->natAddrInd.val = 0x03;
/**************************************************************************/
cgPtyNum->scrnInd.pres = PRSNT_NODEF;
cgPtyNum->scrnInd.val = ftdm->screen;
/**************************************************************************/
cgPtyNum->presRest.pres = PRSNT_NODEF;
cgPtyNum->presRest.val = ftdm->pres;
/**************************************************************************/
cgPtyNum->numPlan.pres = PRSNT_NODEF;
cgPtyNum->numPlan.val = 0x01;
/**************************************************************************/
cgPtyNum->niInd.pres = PRSNT_NODEF;
cgPtyNum->niInd.val = 0x00;
/**************************************************************************/
cgPtyNum->addrSig.pres = PRSNT_NODEF;
k = 0;
j = 0;
flag = 0;
while (1) {
tmp = ftdm->cid_num.digits[k];
if (tmp != '\0') {
if (isdigit(tmp)) {
lower = atoi(&tmp);
k++;
tmp = ftdm->cid_num.digits[k];
} else {
while (!(isdigit(tmp)) && (tmp != '\0')) {
k++;
tmp = ftdm->cid_num.digits[k];
} /* while(!(isdigit(tmp))) */
/* atoi will search through memory starting from the pointer it is given until
* it finds the \0...since tmp is on the stack it will start going through the
* possibly causing corruption. Hard code a \0 to prevent this
*/
tmp[1] = '\0';
k = 0;
j = 0;
flag = 0;
if (tmp != '\0') {
lower = atoi(&tmp);
k++;
tmp = ftdm->cid_num.digits[k];
} else {
flag = 1;
lower = 0xf;
} /* if (tmp != '\0') */
} /* (isdigit(tmp)) */
} else {
flag = 1;
lower = 0xf;
} /* if (tmp != '\0') */
while (1) {
tmp[0] = ftdm->cid_num.digits[k];
tmp = ftdm->cid_num.digits[k];
if (tmp != '\0') {
if (isdigit(tmp)) {
upper = (atoi(&tmp)) << 4;
} else {
while (!(isdigit(tmp)) && (tmp != '\0')) {
k++;
tmp = ftdm->cid_num.digits[k];
} /* while(!(isdigit(tmp))) */
if (tmp[0] != '\0') {
if (isdigit(tmp[0])) {
lower = atoi(&tmp[0]);
k++;
tmp[0] = ftdm->cid_num.digits[k];
} else {
while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
k++;
tmp[0] = ftdm->cid_num.digits[k];
} /* while(!(isdigit(tmp))) */
if (tmp != '\0') {
upper = (atoi(&tmp)) << 4;
k++;
} else {
flag = 1;
upper = 0xf;
} /* if (tmp != '\0') */
} /* if (isdigit(tmp)) */
} else {
if (flag == 1){
upper = 0x0;
} else {
flag = 1;
upper = 0xf;
} /* if (flag == 1) */
} /* if (tmp != '\0') */
if (tmp[0] != '\0') {
lower = atoi(&tmp[0]);
k++;
tmp[0] = ftdm->cid_num.digits[k];
} else {
flag = 1;
lower = 0xf;
} /* if (tmp != '\0') */
} /* (isdigit(tmp)) */
} else {
flag = 1;
lower = 0xf;
} /* if (tmp != '\0') */
cgPtyNum->addrSig.val[j] = upper | lower;
j++;
tmp[0] = ftdm->cid_num.digits[k];
if (flag) {
break;
} else {
k++;
}
} /* while(1) */
if (tmp[0] != '\0') {
if (isdigit(tmp[0])) {
upper = (atoi(&tmp[0])) << 4;
} else {
while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
k++;
tmp[0] = ftdm->cid_num.digits[k];
} /* while(!(isdigit(tmp))) */
cgPtyNum->addrSig.len = j;
/**************************************************************************/
cgPtyNum->oddEven.pres = PRSNT_NODEF;
cgPtyNum->oddEven.val = ((cgPtyNum->addrSig.val[j] >>4) == 0x0 ) ? 0x01 : 0x00;
/**************************************************************************/
return 0;
if (tmp[0] != '\0') {
upper = (atoi(&tmp[0])) << 4;
k++;
} else {
flag = 1;
upper = 0xf;
} /* if (tmp != '\0') */
} /* if (isdigit(tmp)) */
} else {
if (flag == 1) {
upper = 0x0;
} else {
flag = 1;
upper = 0xf;
} /* if (flag == 1) */
} /* if (tmp != '\0') */
cgPtyNum->addrSig.val[j] = upper | lower;
j++;
if (flag) {
break;
} else {
k++;
}
} /* while(1) */
cgPtyNum->addrSig.len = j;
/**************************************************************************/
cgPtyNum->oddEven.pres = PRSNT_NODEF;
cgPtyNum->oddEven.val = ((cgPtyNum->addrSig.val[j] >> 4) == 0x0 ) ? 0x01 : 0x00;
/**************************************************************************/
return 0;
}
/******************************************************************************/
uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
{
return 0;
return 0;
}
/******************************************************************************/
uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
{
int k;
int j;
int flag;
char tmp;
unsigned char lower;
unsigned char upper;
int k;
int j;
int flag;
char tmp[2];
unsigned char lower;
unsigned char upper;
/**************************************************************************/
cdPtyNum->eh.pres = PRSNT_NODEF;
/**************************************************************************/
cdPtyNum->natAddrInd.pres = PRSNT_NODEF;
cdPtyNum->natAddrInd.val = 0x03;
/**************************************************************************/
cdPtyNum->numPlan.pres = PRSNT_NODEF;
cdPtyNum->numPlan.val = 0x01;
/**************************************************************************/
cdPtyNum->innInd.pres = PRSNT_NODEF;
cdPtyNum->innInd.val = 0x01;
/**************************************************************************/
cdPtyNum->addrSig.pres = PRSNT_NODEF;
/**************************************************************************/
cdPtyNum->eh.pres = PRSNT_NODEF;
/**************************************************************************/
cdPtyNum->natAddrInd.pres = PRSNT_NODEF;
cdPtyNum->natAddrInd.val = 0x03;
/**************************************************************************/
cdPtyNum->numPlan.pres = PRSNT_NODEF;
cdPtyNum->numPlan.val = 0x01;
/**************************************************************************/
cdPtyNum->innInd.pres = PRSNT_NODEF;
cdPtyNum->innInd.val = 0x01;
/**************************************************************************/
cdPtyNum->addrSig.pres = PRSNT_NODEF;
k = 0;
j = 0;
flag = 0;
while (1) {
tmp = ftdm->dnis.digits[k];
if (tmp != '\0') {
if (isdigit(tmp)) {
lower = atoi(&tmp);
k++;
tmp = ftdm->dnis.digits[k];
} else {
while (!(isdigit(tmp)) && (tmp != '\0')) {
k++;
tmp = ftdm->dnis.digits[k];
} /* while(!(isdigit(tmp))) */
/* atoi will search through memory starting from the pointer it is given until
* it finds the \0...since tmp is on the stack it will start going through the
* possibly causing corruption. Hard code a \0 to prevent this
*/
tmp[1] = '\0';
k = 0;
j = 0;
flag = 0;
if (tmp != '\0') {
lower = atoi(&tmp);
k++;
tmp = ftdm->dnis.digits[k];
} else {
flag = 1;
lower = 0xf;
} /* if (tmp != '\0') */
} /* (isdigit(tmp)) */
} else {
flag = 1;
lower = 0xf;
} /* if (tmp != '\0') */
while (1) {
tmp[0] = ftdm->dnis.digits[k];
tmp = ftdm->dnis.digits[k];
if (tmp != '\0') {
if (isdigit(tmp)) {
upper = (atoi(&tmp)) << 4;
} else {
while (!(isdigit(tmp)) && (tmp != '\0')) {
k++;
tmp = ftdm->dnis.digits[k];
} /* while(!(isdigit(tmp))) */
if (tmp[0] != '\0') {
if (isdigit(tmp[0])) {
lower = atoi(&tmp[0]);
k++;
tmp[0] = ftdm->dnis.digits[k];
} else {
while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
k++;
tmp[0] = ftdm->dnis.digits[k];
} /* while(!(isdigit(tmp))) */
if (tmp != '\0') {
upper = (atoi(&tmp)) << 4;
k++;
} else {
flag = 1;
upper = 0xf;
} /* if (tmp != '\0') */
} /* if (isdigit(tmp)) */
} else {
if (flag == 1){
upper = 0x0;
} else {
flag = 1;
upper = 0xf;
} /* if (flag == 1) */
} /* if (tmp != '\0') */
if (tmp[0] != '\0') {
lower = atoi(&tmp[0]);
k++;
tmp[0] = ftdm->dnis.digits[k];
} else {
flag = 1;
lower = 0xf;
} /* if (tmp != '\0') */
} /* (isdigit(tmp)) */
} else {
flag = 1;
lower = 0xf;
} /* if (tmp != '\0') */
cdPtyNum->addrSig.val[j] = upper | lower;
j++;
tmp[0] = ftdm->dnis.digits[k];
if (flag) {
break;
} else {
k++;
}
} /* while(1) */
if (tmp[0] != '\0') {
if (isdigit(tmp[0])) {
upper = (atoi(&tmp[0])) << 4;
} else {
while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
k++;
tmp[0] = ftdm->dnis.digits[k];
} /* while(!(isdigit(tmp))) */
cdPtyNum->addrSig.len = j;
/**************************************************************************/
cdPtyNum->oddEven.pres = PRSNT_NODEF;
cdPtyNum->oddEven.val = ((cdPtyNum->addrSig.val[j] >>4) == 0x0 ) ? 0x01 : 0x00;
/**************************************************************************/
return 0;
if (tmp[0] != '\0') {
upper = (atoi(&tmp[0])) << 4;
k++;
} else {
flag = 1;
upper = 0xf;
} /* if (tmp != '\0') */
} /* if (isdigit(tmp)) */
} else {
if (flag == 1) {
upper = 0x0;
} else {
flag = 1;
upper = 0xf;
} /* if (flag == 1) */
} /* if (tmp != '\0') */
cdPtyNum->addrSig.val[j] = upper | lower;
j++;
if (flag) {
break;
} else {
k++;
}
} /* while(1) */
cdPtyNum->addrSig.len = j;
/**************************************************************************/
cdPtyNum->oddEven.pres = PRSNT_NODEF;
cdPtyNum->oddEven.val = ((cdPtyNum->addrSig.val[j] >> 4) == 0x0 ) ? 0x01 : 0x00;
/**************************************************************************/
return 0;
}
/******************************************************************************/
uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven)
{
uint8_t i;
uint8_t j;
uint8_t i;
uint8_t j;
/* check if the token string is present */
if (str.pres == 1) {
j=0;
/* check if the token string is present */
for (i=0; i < str.len; i++) {
sprintf(&ftdm[j], "%d", (str.val[i] & 0x0F));
j++;
sprintf(&ftdm[j], "%d", ((str.val[i] & 0xF0) >> 4));
j++;
}
if (str.pres == 1) {
j = 0;
/* if the odd flag is up the last digit is a fake "0" */
if ((oddEven.pres == 1) && (oddEven.val == 1)) {
ftdm[j-1] = '\0';
} else {
ftdm[j] = '\0';
}
} else {
SS7_ERROR("Asked to copy tknStr that is not present!\n");
return 1;
}
for (i = 0; i < str.len; i++) {
sprintf(&ftdm[j], "%d", (str.val[i] & 0x0F));
j++;
sprintf(&ftdm[j], "%d", ((str.val[i] & 0xF0) >> 4));
j++;
}
return 0;
/* if the odd flag is up the last digit is a fake "0" */
if ((oddEven.pres == 1) && (oddEven.val == 1)) {
ftdm[j-1] = '\0';
} else {
ftdm[j] = '\0';
}
} else {
SS7_ERROR("Asked to copy tknStr that is not present!\n");
return 1;
}
return 0;
}
/******************************************************************************/
int check_for_state_change(ftdm_channel_t *ftdmchan)
{
/* check to see if there are any pending state changes on the channel and give them a sec to happen*/
ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 500);
/* check the flag to confirm it is clear now */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
/* the flag is still up...so we have a problem */
SS7_DEBUG_CHAN(ftdmchan, "FTDM_CHANNEL_STATE_CHANGE flag set for over 500ms, channel state = %s\n",
ftdm_channel_state2str (ftdmchan->state));
return 1;
}
return 0;
}
/******************************************************************************/
int check_cics_in_range(sngss7_chan_data_t *sngss7_info)
{
#if 0
SS7_DEBUG("Checking for pending state change on span: %d, chan: %d\n!",
ftdmchan->physical_span_id,
ftdmchan->physical_chan_id);
ftdm_channel_t *tmp_ftdmchan;
sngss7_chan_data_t *tmp_sngss7_info;
int i = 0;
/* check all the circuits in the range to see if we are the last ckt to reset */
for ( i = sngss7_info->grs.circuit; i < ( sngss7_info->grs.range + 1 ); i++ ) {
if ( g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0 ) {
/* get the ftdmchan and ss7_chan_data from the circuit */
if (extract_chan_data(g_ftdm_sngss7_data.cfg.isupCircuit[i].id, &tmp_sngss7_info, &tmp_ftdmchan)) {
SS7_ERROR("Failed to extract channel data for circuit = %d!\n", g_ftdm_sngss7_data.cfg.isupCircuit[i].id);
return 0;
}
/* check if the channel still has the reset flag done is up */
if (!sngss7_test_flag(tmp_sngss7_info, FLAG_GRP_RESET_RX_DN)) {
SS7_DEBUG_CHAN(tmp_ftdmchan, "[CIC:%d] Still processing reset...\n", tmp_sngss7_info->circuit->cic);
return 0;
}
} /* if not siglink */
} /* for */
SS7_DEBUG("All circuits out of reset: circuit=%d, range=%d\n",
sngss7_info->grs.circuit,
sngss7_info->grs.range);
return 1;
#endif
/* check to see if there are any pending state changes on the channel and give them a sec to happen*/
ftdm_wait_for_flag_cleared(ftdmchan, FTDM_CHANNEL_STATE_CHANGE, 500);
/* check the flag to confirm it is clear now */
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) {
/* the flag is still up...so we have a problem */
SS7_ERROR("FTDM_CHANNEL_STATE_CHANGE set for over 500ms on span: %d, chan: %d\n",
ftdmchan->physical_span_id,
ftdmchan->physical_chan_id);
return 0;
/* move the state of the channel to RESTART to force a reset */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
return 1;
}
return 0;
}
/******************************************************************************/
ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
/*SS7_FUNC_TRACE_ENTER(__FUNCTION__);*/
if (g_ftdm_sngss7_data.cfg.isupCircuit[circuit].obj == NULL) {
SS7_ERROR("sngss7_info is Null for circuit #%d\n", circuit);
return FTDM_FAIL;
}
if (g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj == NULL) {
SS7_ERROR("sngss7_info is Null for circuit #%d\n", circuit);
return FTDM_FAIL;
}
ftdm_assert_return(g_ftdm_sngss7_data.cfg.isupCircuit[circuit].obj,FTDM_FAIL,"received message on signalling link or non-configured cic\n");
*sngss7_info = g_ftdm_sngss7_data.cfg.isupCircuit[circuit].obj;
ftdm_assert_return(g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj, FTDM_FAIL, "received message on signalling link or non-configured cic\n");
ftdm_assert_return((*sngss7_info)->ftdmchan,FTDM_FAIL,"received message on signalling link or non-configured cic\n");
*ftdmchan = (*sngss7_info)->ftdmchan;
*sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj;
SS7_FUNC_TRACE_EXIT(__FUNCTION__);
return FTDM_SUCCESS;
ftdm_assert_return((*sngss7_info)->ftdmchan, FTDM_FAIL, "received message on signalling link or non-configured cic\n");
*ftdmchan = (*sngss7_info)->ftdmchan;
/*SS7_FUNC_TRACE_EXIT(__FUNCTION__);*/
return FTDM_SUCCESS;
}
/******************************************************************************/
int check_for_reset(sngss7_chan_data_t *sngss7_info)
{
if (sngss7_test_flag(sngss7_info,FLAG_RESET_RX)) {
return 1;
}
if (sngss7_test_flag(sngss7_info,FLAG_RESET_TX)) {
return 1;
}
if (sngss7_test_flag(sngss7_info,FLAG_GRP_RESET_RX)) {
return 1;
}
if (sngss7_test_flag(sngss7_info,FLAG_GRP_RESET_TX)) {
return 1;
}
return 0;
}
/******************************************************************************/
unsigned long get_unique_id(void)
{
if (sngss7_id < 420000000) {
sngss7_id++;
} else {
sngss7_id = 1;
}
if (sngss7_id < 420000000) {
sngss7_id++;
} else {
sngss7_id = 1;
}
return(sngss7_id);
return(sngss7_id);
}
/******************************************************************************/