diff --git a/libs/freetdm/Makefile.am b/libs/freetdm/Makefile.am index ff5e23beb1..33a8b96936 100644 --- a/libs/freetdm/Makefile.am +++ b/libs/freetdm/Makefile.am @@ -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 \ @@ -264,14 +268,19 @@ ftmod_pritap_la_LIBADD = $(MYLIB) endif if SNGSS7 -ftmod_sangoma_ss7_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c \ - $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c +ftmod_sangoma_ss7_la_SOURCES = $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_timers.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c \ + $(SRC)/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c ftmod_sangoma_ss7_la_CFLAGS = $(AM_CFLAGS) $(MY_CFLAGS) -D_GNU_SOURCE ftmod_sangoma_ss7_la_LDFLAGS = -module -avoid-version -lsng_ss7 ftmod_sangoma_ss7_la_LIBADD = $(MYLIB) @@ -285,17 +294,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) diff --git a/libs/freetdm/configure.ac b/libs/freetdm/configure.ac index 9ad8c4f678..a8ed67f228 100644 --- a/libs/freetdm/configure.ac +++ b/libs/freetdm/configure.ac @@ -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 diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index c98117c807..56eebd7dd5 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -40,7 +40,7 @@ #define FREETDM_LIMIT_REALM "__freetdm" #define FREETDM_VAR_PREFIX "freetdm_" -#define FREETDM_VAR_PREFIX_LEN 8 +#define FREETDM_VAR_PREFIX_LEN (sizeof(FREETDM_VAR_PREFIX)-1) SWITCH_MODULE_LOAD_FUNCTION(mod_freetdm_load); SWITCH_MODULE_SHUTDOWN_FUNCTION(mod_freetdm_shutdown); @@ -87,6 +87,7 @@ static struct { analog_option_t analog_options; switch_hash_t *ss7_configs; int sip_headers; + uint8_t crash_on_assert; } globals; /* private data attached to each fs session */ @@ -1301,11 +1302,14 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi } } - ftdm_channel_clear_vars(ftdmchan); + span_id = ftdm_channel_get_span_id(ftdmchan); + chan_id = ftdm_channel_get_id(ftdmchan); + for (h = var_event->headers; h; h = h->next) { if (!strncasecmp(h->name, FREETDM_VAR_PREFIX, FREETDM_VAR_PREFIX_LEN)) { char *v = h->name + FREETDM_VAR_PREFIX_LEN; if (!zstr(v)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Adding outbound freetdm variable %s=%s to channel %d:%d\n", v, h->value, span_id, chan_id); ftdm_channel_add_var(ftdmchan, v, h->value); } } @@ -1316,9 +1320,6 @@ static switch_call_cause_t channel_outgoing_channel(switch_core_session_t *sessi switch_caller_profile_t *caller_profile; switch_channel_t *channel = switch_core_session_get_channel(*new_session); - span_id = ftdm_channel_get_span_id(ftdmchan); - chan_id = ftdm_channel_get_id(ftdmchan); - switch_core_session_add_stream(*new_session, NULL); if ((tech_pvt = (private_t *) switch_core_session_alloc(*new_session, sizeof(private_t))) != 0) { tech_init(tech_pvt, *new_session, ftdmchan); @@ -1402,6 +1403,9 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_core_session_t *session = NULL; private_t *tech_pvt = NULL; switch_channel_t *channel = NULL; + ftdm_iterator_t *iter = NULL; + const char *var_name = NULL; + const char *var_value = NULL; uint32_t spanid, chanid; char name[128]; ftdm_caller_data_t *channel_caller_data = ftdm_channel_get_caller_data(sigmsg->channel); @@ -1510,6 +1514,13 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session if (channel_caller_data->raw_data_len) { switch_channel_set_variable_printf(channel, "freetdm_custom_call_data", "%s", channel_caller_data->raw_data); } + /* Add any channel variable to the dial plan */ + iter = ftdm_channel_get_var_iterator(sigmsg->channel); + for ( ; iter; iter = ftdm_iterator_next(iter)) { + ftdm_channel_get_current_var(iter, &var_name, &var_value); + snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name); + switch_channel_set_variable_printf(channel, name, "%s", var_value); + } switch_channel_set_state(channel, CS_INIT); if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { @@ -2106,10 +2117,10 @@ static FIO_SIGNAL_CB_FUNCTION(on_clear_channel_signal) } break; case FTDM_SIGEVENT_SIGSTATUS_CHANGED: - { - ftdm_signaling_status_t *sigstatus = (ftdm_signaling_status_t*)(sigmsg->raw_data); + { + ftdm_signaling_status_t sigstatus = sigmsg->raw_data ? *((ftdm_signaling_status_t*)(sigmsg->raw_data)) : sigmsg->sigstatus; switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "%d:%d signalling changed to :%s\n", - spanid, chanid, ftdm_signaling_status2str(*sigstatus)); + spanid, chanid, ftdm_signaling_status2str(sigstatus)); } break; default: @@ -2389,6 +2400,8 @@ static switch_status_t load_config(void) globals.debug = atoi(val); } else if (!strcasecmp(var, "hold-music")) { switch_set_string(globals.hold_music, val); + } else if (!strcasecmp(var, "crash-on-assert")) { + globals.crash_on_assert = switch_true(val); } else if (!strcasecmp(var, "sip-headers")) { globals.sip_headers = switch_true(val); } else if (!strcasecmp(var, "enable-analog-option")) { @@ -2619,6 +2632,32 @@ static switch_status_t load_config(void) uint32_t span_id = 0, to = 0, max = 0; ftdm_span_t *span = NULL; analog_option_t analog_options = ANALOG_OPTION_NONE; + + if (name) { + zstatus = ftdm_span_find_by_name(name, &span); + } else { + if (switch_is_number(id)) { + span_id = atoi(id); + zstatus = ftdm_span_find(span_id, &span); + } + + if (zstatus != FTDM_SUCCESS) { + zstatus = ftdm_span_find_by_name(id, &span); + } + } + + if (zstatus != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); + continue; + } + + if (!span_id) { + span_id = ftdm_span_get_id(span); + } + + /* some defaults first */ + SPAN_CONFIG[span_id].limit_backend = "hash"; + SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT; for (param = switch_xml_child(myspan, "param"); param; param = param->next) { char *var = (char *) switch_xml_attr_soft(param, "name"); @@ -2633,6 +2672,28 @@ static switch_status_t load_config(void) context = val; } else if (!strcasecmp(var, "dialplan")) { dialplan = val; + } else if (!strcasecmp(var, "call_limit_backend")) { + SPAN_CONFIG[span_id].limit_backend = val; + ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id); + } else if (!strcasecmp(var, "call_limit_rate")) { + int calls; + int seconds; + if (sscanf(val, "%d/%d", &calls, &seconds) != 2) { + ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var); + } else { + if (calls < 1 || seconds < 1) { + ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, minimum call limit must be 1 per second\n", var); + } else { + SPAN_CONFIG[span_id].limit_calls = calls; + SPAN_CONFIG[span_id].limit_seconds = seconds; + } + } + } else if (!strcasecmp(var, "call_limit_reset_event")) { + if (!strcasecmp(val, "answer")) { + SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER; + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, only accepted event is 'answer'\n", var); + } } else if (!strcasecmp(var, "dial-regex")) { dial_regex = val; } else if (!strcasecmp(var, "enable-callerid")) { @@ -3352,12 +3413,16 @@ static switch_status_t load_config(void) boost_span = boost_spans[i]; ftdm_log(FTDM_LOG_DEBUG, "Starting boost span %d\n", ftdm_span_get_id(boost_span)); if (ftdm_span_start(boost_span) == FTDM_FAIL) { - ftdm_log(FTDM_LOG_ERROR, "Error starting boost FreeTDM span %d, error: %s\n", - ftdm_span_get_id(boost_span), ftdm_span_get_last_error(boost_span)); - continue; + ftdm_log(FTDM_LOG_ERROR, "Error starting boost FreeTDM span %d, error: %s\n", + ftdm_span_get_id(boost_span), ftdm_span_get_last_error(boost_span)); + continue; } } + if (globals.crash_on_assert) { + ftdm_log(FTDM_LOG_WARNING, "Crash on assert enabled\n"); + ftdm_global_set_crash_policy(FTDM_CRASH_ON_ASSERT); + } switch_xml_free(xml); diff --git a/libs/freetdm/src/ftdm_call_utils.c b/libs/freetdm/src/ftdm_call_utils.c new file mode 100644 index 0000000000..d91b3bc9e2 --- /dev/null +++ b/libs/freetdm/src/ftdm_call_utils.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * David Yat Sin + * 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 + + +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_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target) +{ + if (!strcasecmp(bc_string, "speech")) { + *target = FTDM_BEARER_CAP_SPEECH; + } else if (!strcasecmp(bc_string, "unrestricted-digital")) { + *target = FTDM_BEARER_CAP_64K_UNRESTRICTED; + } else if (!strcasecmp(bc_string, "3.1Khz")) { + *target = FTDM_BEARER_CAP_3_1KHZ_AUDIO; + } else { + ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Capability value (%s)\n", bc_string); + return FTDM_FAIL; + } + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target) +{ + if (!strcasecmp(bc_string, "v110")) { + *target = FTDM_USER_LAYER1_PROT_V110; + } else if (!strcasecmp(bc_string, "ulaw")) { + *target = FTDM_USER_LAYER1_PROT_ULAW; + } else if (!strcasecmp(bc_string, "alaw")) { + *target =FTDM_USER_LAYER1_PROT_ALAW ; + } else { + ftdm_log(FTDM_LOG_WARNING, "Unsupported Bearer Layer1 Prot value (%s)\n", bc_string); + 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; +} + diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index 871d3451ae..fc32a0ff0f 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -51,6 +51,7 @@ #include "ftdm_cpu_monitor.h" #define SPAN_PENDING_CHANS_QUEUE_SIZE 1000 +#define SPAN_PENDING_SIGNALS_QUEUE_SIZE 1000 #define FTDM_READ_TRACE_INDEX 0 #define FTDM_WRITE_TRACE_INDEX 1 @@ -260,6 +261,14 @@ static ftdm_status_t ftdm_set_caller_data(ftdm_span_t *span, ftdm_caller_data_t return FTDM_FAIL; } + if (caller_data->dnis.plan == FTDM_NPI_INVALID) { + caller_data->dnis.plan = span->default_caller_data.dnis.plan; + } + + if (caller_data->dnis.type == FTDM_TON_INVALID) { + caller_data->dnis.type = span->default_caller_data.dnis.type; + } + if (caller_data->cid_num.plan == FTDM_NPI_INVALID) { caller_data->cid_num.plan = span->default_caller_data.cid_num.plan; } @@ -283,6 +292,20 @@ static ftdm_status_t ftdm_set_caller_data(ftdm_span_t *span, ftdm_caller_data_t if (caller_data->rdnis.type == FTDM_NPI_INVALID) { caller_data->rdnis.type = span->default_caller_data.rdnis.type; } + + if (caller_data->bearer_capability == FTDM_INVALID_INT_PARM) { + caller_data->bearer_capability = span->default_caller_data.bearer_capability; + } + + if (caller_data->bearer_layer1 == FTDM_INVALID_INT_PARM) { + caller_data->bearer_layer1 = span->default_caller_data.bearer_layer1; + } + + if (FTDM_FAIL == ftdm_is_number(caller_data->cid_num.digits)) { + ftdm_log(FTDM_LOG_DEBUG, "dropping caller id number %s since we only accept digits\n", caller_data->cid_num.digits); + caller_data->cid_num.digits[0] = '\0'; + } + return FTDM_SUCCESS; } @@ -386,8 +409,6 @@ static ftdm_status_t ftdm_channel_destroy(ftdm_channel_t *ftdmchan) ftdm_buffer_destroy(&ftdmchan->fsk_buffer); ftdmchan->pre_buffer_size = 0; - hashtable_destroy(ftdmchan->variable_hash); - ftdm_safe_free(ftdmchan->dtmf_hangup_buf); if (ftdmchan->tone_session.buffer) { @@ -449,6 +470,9 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span) if (span->pendingchans) { ftdm_queue_destroy(&span->pendingchans); } + if (span->pendingsignals) { + ftdm_queue_destroy(&span->pendingsignals); + } ftdm_mutex_unlock(span->mutex); ftdm_mutex_destroy(&span->mutex); ftdm_safe_free(span->signal_data); @@ -798,7 +822,6 @@ FT_DECLARE(ftdm_status_t) ftdm_span_add_channel(ftdm_span_t *span, ftdm_socket_t ftdm_buffer_create(&new_chan->digit_buffer, 128, 128, 0); ftdm_buffer_create(&new_chan->gen_dtmf_buffer, 128, 128, 0); - new_chan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); new_chan->dtmf_hangup_buf = ftdm_calloc (span->dtmf_hangup_len + 1, sizeof (char)); @@ -1168,14 +1191,6 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_set_state(const char *file, const char *f return FTDM_FAIL; } - if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_SUSPENDED)) { - if (state != FTDM_CHANNEL_STATE_RESTART && state != FTDM_CHANNEL_STATE_DOWN) { - ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_ERROR, "Ignored state change request from %s to %s, span %s is suspended\n", - ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state), ftdmchan->span->name); - return FTDM_FAIL; - } - } - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { ftdm_log_chan_ex(ftdmchan, file, func, line, FTDM_LOG_LEVEL_ERROR, "Ignored state change request from %s to %s, the previous state change has not been processed yet\n", ftdm_channel_state2str(ftdmchan->state), ftdm_channel_state2str(state)); @@ -1472,7 +1487,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_group(uint32_t group_id, ftdm_dir ftdm_group_channel_use_count(group, &count); if (count >= group->chan_count) { - ftdm_log(FTDM_LOG_ERROR, "All circuits are busy (%d channels used out of %d available).\n", count, group->chan_count); + ftdm_log(FTDM_LOG_WARNING, "All circuits are busy (%d channels used out of %d available).\n", count, group->chan_count); *ftdmchan = NULL; return FTDM_FAIL; } @@ -1569,7 +1584,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_open_by_span(uint32_t span_id, ftdm_direc ftdm_span_channel_use_count(span, &count); if (count >= span->chan_count) { - ftdm_log(FTDM_LOG_ERROR, "All circuits are busy: active=%i max=%i.\n", count, span->chan_count); + ftdm_log(FTDM_LOG_WARNING, "All circuits are busy: active=%i max=%i.\n", count, span->chan_count); return FTDM_FAIL; } @@ -1935,7 +1950,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char ftdm_channel_lock(ftdmchan); if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call is already terminating\n"); + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call is already TERMINATING\n"); goto done; } @@ -1947,14 +1962,27 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_answer(const char *file, const char goto done; } + if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } + /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */ + if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n"); + goto done; + } + if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS_MEDIA) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); } + /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */ + if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to UP\n"); + goto done; + } + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_UP, 1); done: @@ -1966,24 +1994,12 @@ done: /* lock must be acquired by the caller! */ static ftdm_status_t call_hangup(ftdm_channel_t *chan, const char *file, const char *func, int line) { + ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP); if (chan->state != FTDM_CHANNEL_STATE_DOWN) { if (chan->state == FTDM_CHANNEL_STATE_HANGUP) { /* make user's life easier, and just ignore double hangup requests */ return FTDM_SUCCESS; } - if (chan->state == FTDM_CHANNEL_STATE_TERMINATING && ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { - /* the signaling stack is already terminating the call but has not yet notified the user about it - * with SIGEVENT_STOP, we must flag this channel as hangup and wait for the SIGEVENT_STOP before - * proceeding, at that point we will move the channel to hangup, but the SIGEVENT_STOP will not - * be sent to the user since they already made clear they want to hangup! - * */ - ftdm_set_flag(chan, FTDM_CHANNEL_USER_HANGUP); - ftdm_wait_for_flag_cleared(chan, FTDM_CHANNEL_STATE_CHANGE, 5000); - if (ftdm_test_flag(chan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_log_chan(chan, FTDM_LOG_CRIT, "Failed to hangup, state change for %d/%s is still pending!\n", chan->state, ftdm_channel_state2str(chan->state)); - return FTDM_FAIL; - } - } ftdm_channel_set_state(file, func, line, chan, FTDM_CHANNEL_STATE_HANGUP, 1); } else { /* the signaling stack did not touch the state, @@ -2008,6 +2024,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup_with_cause(const char *file, FT_DECLARE(ftdm_status_t) _ftdm_channel_call_hangup(const char *file, const char *func, int line, ftdm_channel_t *ftdmchan) { ftdm_channel_lock(ftdmchan); + ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_CLEARING; call_hangup(ftdmchan, file, func, line); ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; @@ -2081,8 +2098,13 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch { ftdm_status_t status = FTDM_SUCCESS; ftdm_channel_lock(ftdmchan); - switch (indication) { + if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n"); + goto done; + } + + switch (indication) { /* FIXME: ring and busy cannot be used with all signaling stacks * (particularly isdn stacks I think, we should emulate or just move to hangup with busy cause) */ case FTDM_CHANNEL_INDICATE_RING: @@ -2109,6 +2131,13 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch if (ftdmchan->state < FTDM_CHANNEL_STATE_PROGRESS) { ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS, 1); } + + /* set state unlocks the channel so we need to re-confirm that the channel hasn't gone to hell */ + if (ftdmchan->state == FTDM_CHANNEL_STATE_TERMINATING) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Ignoring answer because the call has moved to TERMINATING while we're moving to PROGRESS\n"); + goto done; + } + ftdm_channel_set_state(file, func, line, ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, 1); } break; @@ -2119,6 +2148,7 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_indicate(const char *file, const ch break; } +done: ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; @@ -2128,7 +2158,8 @@ FT_DECLARE(ftdm_status_t) _ftdm_channel_call_place(const char *file, const char { ftdm_status_t status = FTDM_FAIL; - ftdm_assert(ftdmchan != NULL, "null channel"); + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel"); + ftdm_assert_return(ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND), FTDM_FAIL, "Call place, but outbound flag not set\n"); ftdm_channel_lock(ftdmchan); @@ -2218,9 +2249,10 @@ static void close_dtmf_debug(ftdm_channel_t *ftdmchan) } #endif +static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) { - assert(ftdmchan != NULL); + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "Null channel can't be done!\n"); ftdm_mutex_lock(ftdmchan->mutex); @@ -2248,6 +2280,7 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_done(ftdm_channel_t *ftdmchan) #ifdef FTDM_DEBUG_DTMF close_dtmf_debug(ftdmchan); #endif + ftdm_channel_clear_vars(ftdmchan); ftdmchan->init_state = FTDM_CHANNEL_STATE_DOWN; ftdmchan->state = FTDM_CHANNEL_STATE_DOWN; @@ -2274,14 +2307,12 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_close(ftdm_channel_t **ftdmchan) ftdm_channel_t *check; ftdm_status_t status = FTDM_FAIL; - assert(ftdmchan != NULL); + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel double pointer provided!\n"); + ftdm_assert_return(*ftdmchan != NULL, FTDM_FAIL, "null channel pointer provided!\n"); + check = *ftdmchan; *ftdmchan = NULL; - if (!check) { - return FTDM_FAIL; - } - if (ftdm_test_flag(check, FTDM_CHANNEL_CONFIGURED)) { ftdm_mutex_lock(check->mutex); if (ftdm_test_flag(check, FTDM_CHANNEL_OPEN)) { @@ -3375,8 +3406,8 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat ftdm_size_t max = datasize; unsigned int i = 0; - assert(ftdmchan != NULL); - assert(ftdmchan->fio != NULL); + ftdm_assert_return(ftdmchan != NULL, FTDM_FAIL, "null channel on write!\n"); + ftdm_assert_return(ftdmchan->fio != NULL, FTDM_FAIL, "null I/O on write!\n"); if (!ftdmchan->buffer_delay && ((ftdmchan->dtmf_buffer && ftdm_buffer_inuse(ftdmchan->dtmf_buffer)) || @@ -3428,16 +3459,16 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *dat return status; } -FT_DECLARE(ftdm_status_t) ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan) +static ftdm_status_t ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan) { - if(ftdmchan->variable_hash) { + ftdm_channel_lock(ftdmchan); + + if (ftdmchan->variable_hash) { hashtable_destroy(ftdmchan->variable_hash); } - ftdmchan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + ftdmchan->variable_hash = NULL; - if(!ftdmchan->variable_hash) - return FTDM_FAIL; - + ftdm_channel_unlock(ftdmchan); return FTDM_SUCCESS; } @@ -3445,34 +3476,98 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_var(ftdm_channel_t *ftdmchan, const c { char *t_name = 0, *t_val = 0; - if(!ftdmchan->variable_hash || !var_name || !value) - { + ftdm_status_t status = FTDM_FAIL; + + if (!var_name || !value) { return FTDM_FAIL; } + ftdm_channel_lock(ftdmchan); + + if (!ftdmchan->variable_hash) { + /* initialize on first use */ + ftdmchan->variable_hash = create_hashtable(16, ftdm_hash_hashfromstring, ftdm_hash_equalkeys); + if (!ftdmchan->variable_hash) { + goto done; + } + } + t_name = ftdm_strdup(var_name); t_val = ftdm_strdup(value); - if(hashtable_insert(ftdmchan->variable_hash, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE)) { - return FTDM_SUCCESS; - } - return FTDM_FAIL; + hashtable_insert(ftdmchan->variable_hash, t_name, t_val, HASHTABLE_FLAG_FREE_KEY | HASHTABLE_FLAG_FREE_VALUE); + + status = FTDM_SUCCESS; + +done: + ftdm_channel_unlock(ftdmchan); + + return status; } FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name) { - if(!ftdmchan->variable_hash || !var_name) - { + const char *var = NULL; + + ftdm_channel_lock(ftdmchan); + + if (!ftdmchan->variable_hash || !var_name) { + goto done; + } + + var = (const char *)hashtable_search(ftdmchan->variable_hash, (void *)var_name); + +done: + ftdm_channel_unlock(ftdmchan); + + return var; +} + +FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan) +{ + ftdm_hash_iterator_t *iter = NULL; + + ftdm_channel_lock(ftdmchan); + + iter = ftdmchan->variable_hash == NULL ? NULL : hashtable_first(ftdmchan->variable_hash); + + ftdm_channel_unlock(ftdmchan); + + return iter; +} + +FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val) +{ + const void *key = NULL; + void *val = NULL; + + *var_name = NULL; + *var_val = NULL; + + if (!iter) { + return FTDM_FAIL; + } + + hashtable_this(iter, &key, NULL, &val); + + *var_name = key; + *var_val = val; + + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter) +{ + if (!iter) { return NULL; } - return (const char *) hashtable_search(ftdmchan->variable_hash, (void *)var_name); + return hashtable_next(iter); } static struct { ftdm_io_interface_t *pika_interface; } interfaces; - FT_DECLARE(char *) ftdm_api_execute(const char *cmd) { ftdm_io_interface_t *fio = NULL; @@ -4104,6 +4199,9 @@ static ftdm_status_t post_configure_span_channels(ftdm_span_t *span) if (ftdm_test_flag(span, FTDM_SPAN_USE_CHAN_QUEUE)) { status = ftdm_queue_create(&span->pendingchans, SPAN_PENDING_CHANS_QUEUE_SIZE); } + if (status == FTDM_SUCCESS && ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) { + status = ftdm_queue_create(&span->pendingsignals, SPAN_PENDING_SIGNALS_QUEUE_SIZE); + } return status; } @@ -4369,10 +4467,39 @@ FT_DECLARE(ftdm_status_t) ftdm_group_create(ftdm_group_t **group, const char *na return status; } +static ftdm_status_t ftdm_span_trigger_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) +{ + return span->signal_cb(sigmsg); +} + +static ftdm_status_t ftdm_span_queue_signal(const ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) +{ + ftdm_sigmsg_t *new_sigmsg = NULL; + + ftdm_assert_return((sigmsg->raw_data == NULL), FTDM_FAIL, "No raw data should be used with asynchronous notification\n"); + + new_sigmsg = ftdm_calloc(1, sizeof(*sigmsg)); + if (!new_sigmsg) { + return FTDM_FAIL; + } + memcpy(new_sigmsg, sigmsg, sizeof(*sigmsg)); + + ftdm_queue_enqueue(span->pendingsignals, new_sigmsg); + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span) +{ + ftdm_sigmsg_t *sigmsg = NULL; + while ((sigmsg = ftdm_queue_dequeue(span->pendingsignals))) { + ftdm_span_trigger_signal(span, sigmsg); + ftdm_safe_free(sigmsg); + } + return FTDM_SUCCESS; +} + FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t *sigmsg) { - ftdm_status_t status = FTDM_FAIL; - if (sigmsg->channel) { ftdm_mutex_lock(sigmsg->channel->mutex); } @@ -4381,10 +4508,13 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t switch (sigmsg->event_id) { case FTDM_SIGEVENT_SIGSTATUS_CHANGED: - if (*((ftdm_signaling_status_t*)(sigmsg->raw_data)) == FTDM_SIG_STATE_UP) { - ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); - } else { - ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + { + ftdm_signaling_status_t sigstatus = ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE) ? sigmsg->sigstatus : *((ftdm_signaling_status_t*)(sigmsg->raw_data)); + if (sigstatus == FTDM_SIG_STATE_UP) { + ftdm_set_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + } else { + ftdm_clear_flag(sigmsg->channel, FTDM_CHANNEL_SIG_UP); + } } break; @@ -4407,10 +4537,12 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t break; } - - /* call the user callback only if set */ - if (span->signal_cb) { - status = span->signal_cb(sigmsg); + + /* if the signaling module uses a queue for signaling notifications, then enqueue it */ + if (ftdm_test_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE)) { + ftdm_span_queue_signal(span, sigmsg); + } else { + ftdm_span_trigger_signal(span, sigmsg); } done: @@ -4418,7 +4550,7 @@ done: ftdm_mutex_unlock(sigmsg->channel->mutex); } - return status; + return FTDM_SUCCESS; } static void *ftdm_cpu_monitor_run(ftdm_thread_t *me, void *obj) diff --git a/libs/freetdm/src/ftdm_threadmutex.c b/libs/freetdm/src/ftdm_threadmutex.c index 61051df4ef..1271d80f4a 100644 --- a/libs/freetdm/src/ftdm_threadmutex.c +++ b/libs/freetdm/src/ftdm_threadmutex.c @@ -329,6 +329,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *interrupt, int m return FTDM_SUCCESS; } #else +pollagain: ints[0].fd = interrupt->readfd; ints[0].events = POLLIN; ints[0].revents = 0; @@ -343,6 +344,9 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_wait(ftdm_interrupt_t *interrupt, int m res = poll(ints, num, ms); if (res == -1) { + if (errno == EINTR) { + goto pollagain; + } ftdm_log(FTDM_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno)); return FTDM_FAIL; } @@ -369,12 +373,23 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_signal(ftdm_interrupt_t *interrupt) if (!SetEvent(interrupt->event)) { ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt\n"); return FTDM_FAIL; + } #else int err; - if ((err = write(interrupt->writefd, "w", 1)) != 1) { - ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt: %s\n", errno, strerror(errno)); - return FTDM_FAIL; + struct pollfd testpoll; + testpoll.revents = 0; + testpoll.events = POLLIN; + testpoll.fd = interrupt->readfd; + err = poll(&testpoll, 1, 0); + if (err == 0 && !(testpoll.revents & POLLIN)) { + /* we just try to notify if there is nothing on the read fd already, + * otherwise users that never call interrupt wait eventually will + * eventually have the pipe buffer filled */ + if ((err = write(interrupt->writefd, "w", 1)) != 1) { + ftdm_log(FTDM_LOG_ERROR, "Failed to signal interrupt: %s\n", errno, strerror(errno)); + return FTDM_FAIL; + } } #endif return FTDM_SUCCESS; @@ -390,6 +405,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_destroy(ftdm_interrupt_t **ininterrupt) #else close(interrupt->readfd); close(interrupt->writefd); + interrupt->readfd = -1; interrupt->writefd = -1; #endif @@ -402,6 +418,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru { int numdevices = 0; unsigned i; + #if defined(__WINDOWS__) DWORD res = 0; HANDLE ints[20]; @@ -414,6 +431,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru for (i = 0; i < size; i++) { ints[i] = interrupts[i]->event; if (interrupts[i]->device != FTDM_INVALID_SOCKET) { + ints[size+numdevices] = interrupts[i]->device; numdevices++; } @@ -440,7 +458,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru struct pollfd ints[size*2]; memset(&ints, 0, sizeof(ints)); - +pollagain: for (i = 0; i < size; i++) { ints[i].events = POLLIN; ints[i].revents = 0; @@ -449,6 +467,7 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru ints[size+numdevices].events = POLLIN; ints[size+numdevices].revents = 0; ints[size+numdevices].fd = interrupts[i]->device; + numdevices++; } } @@ -456,6 +475,9 @@ FT_DECLARE(ftdm_status_t) ftdm_interrupt_multiple_wait(ftdm_interrupt_t *interru res = poll(ints, size + numdevices, ms); if (res == -1) { + if (errno == EINTR) { + goto pollagain; + } ftdm_log(FTDM_LOG_CRIT, "interrupt poll failed (%s)\n", strerror(errno)); return FTDM_FAIL; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c index b35596cbb2..7234e67183 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_boost/ftmod_sangoma_boost.c @@ -2534,46 +2534,6 @@ static FIO_SPAN_GET_SIG_STATUS_FUNCTION(sangoma_boost_get_span_sig_status) return sangoma_boost_data->sigmod->get_span_sig_status(span, status); } -/* TODO: move these ones to a common private header so other ISDN mods can use them */ -static void 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; - } -} - -static void 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; - } -} - - /** * \brief Initialises an sangoma boost span from configuration variables * \param span Span to configure diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 1872d4adab..9ffd7097a3 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -33,20 +33,31 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + #include "ftmod_sangoma_isdn.h" +#ifdef FTDM_DEBUG_CHAN_MEMORY +#include +#endif + static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj); -static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span); static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span); +ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); +static void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan); + +static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan); +static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event); + static ftdm_io_interface_t g_sngisdn_io_interface; static sng_isdn_event_interface_t g_sngisdn_event_interface; ftdm_sngisdn_data_t g_sngisdn_data; extern ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt); +extern ftdm_status_t sngisdn_check_free_ids(void); ftdm_state_map_t sangoma_isdn_state_map = { { @@ -66,7 +77,7 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_CANCEL, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_END} + {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} }, { ZSD_INBOUND, @@ -80,7 +91,13 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_INBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} + {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_GET_CALLERID, FTDM_END}, + {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} }, { ZSD_INBOUND, @@ -135,8 +152,7 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}, {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - }, - /**************************************************************************/ + }, { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, @@ -167,7 +183,7 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - {FTDM_CHANNEL_STATE_DIALING, FTDM_END} + {FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} }, { ZSD_OUTBOUND, @@ -214,11 +230,22 @@ ftdm_state_map_t sangoma_isdn_state_map = { } }; +static __inline__ void ftdm_sangoma_isdn_advance_chan_states(ftdm_channel_t *ftdmchan) +{ + while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_isdn_process_state_change(ftdmchan); + } +} + static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) { - ftdm_interrupt_t *ftdm_sangoma_isdn_int = NULL; + ftdm_interrupt_t *ftdm_sangoma_isdn_int[2]; + ftdm_status_t ret_status; ftdm_span_t *span = (ftdm_span_t *) obj; ftdm_channel_t *ftdmchan = NULL; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data; + sngisdn_event_data_t *sngisdn_event = NULL; + int32_t sleep = SNGISDN_EVENT_POLL_RATE; ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_isdn monitor thread for span=%u started.\n", span->span_id); @@ -226,44 +253,55 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj) ftdm_set_flag(span, FTDM_SPAN_IN_THREAD); /* get an interrupt queue for this span */ - if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int) != FTDM_SUCCESS) { + if (ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_isdn_int[0]) != FTDM_SUCCESS) { ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a ftdm_interrupt for span = %s!\n", span->name); goto ftdm_sangoma_isdn_run_exit; } - while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { - - /* find out why we returned from the interrupt queue */ - switch ((ftdm_interrupt_wait(ftdm_sangoma_isdn_int, 100))) { - case FTDM_SUCCESS: /* there was a state change on the span */ - /* process all pending state changes */ - while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) { - /* double check that this channel has a state change pending */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_isdn_process_state_change(ftdmchan); - } else { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_ERROR, "reported state change but state change flag not set\n"); - } - } - - break; - - case FTDM_TIMEOUT: - /* twiddle */ - break; - - case FTDM_FAIL: - ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned error!\non span = %s\n", span->name); - break; - - default: - ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned with unknown code on span = %s\n", span->name); - break; - - } - + if (ftdm_queue_get_interrupt(signal_data->event_queue, &ftdm_sangoma_isdn_int[1]) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_CRIT, "%s:Failed to get a event interrupt for span = %s!\n", span->name); + goto ftdm_sangoma_isdn_run_exit; } + while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { + /* find out why we returned from the interrupt queue */ + ret_status = ftdm_interrupt_multiple_wait(ftdm_sangoma_isdn_int, 2, sleep); + /* Check if there are any timers to process */ + ftdm_sched_run(signal_data->sched); + switch (ret_status) { + case FTDM_SUCCESS: /* there was a state change on the span */ + /* process all pending state changes */ + while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) { + /* double check that this channel has a state change pending */ + ftdm_channel_lock(ftdmchan); + ftdm_sangoma_isdn_advance_chan_states(ftdmchan); + ftdm_channel_unlock(ftdmchan); + } + + while ((sngisdn_event = ftdm_queue_dequeue(signal_data->event_queue))) { + ftdm_sangoma_isdn_process_stack_event(span, sngisdn_event); + ftdm_safe_free(sngisdn_event); + } + ftdm_span_trigger_signals(span); + break; + case FTDM_TIMEOUT: + /* twiddle */ + break; + case FTDM_FAIL: + ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned error!\non span = %s\n", span->name); + break; + + default: + ftdm_log(FTDM_LOG_ERROR,"ftdm_interrupt_wait returned with unknown code on span = %s\n", span->name); + break; + } + if (ftdm_sched_get_time_to_next_timer(signal_data->sched, &sleep) == FTDM_SUCCESS) { + if (sleep < 0 || sleep > SNGISDN_EVENT_POLL_RATE) { + sleep = SNGISDN_EVENT_POLL_RATE; + } + } + } + /* clear the IN_THREAD flag so that we know the thread is done */ ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); @@ -281,11 +319,117 @@ ftdm_sangoma_isdn_run_exit: return NULL; } -/******************************************************************************/ + +/** + * \brief Checks if span has state changes pending and processes + * \param span Span where event was fired + * \param sngisdn_event Event to handle + * \return The locked FTDM channel associated to the event if any, NULL otherwise + */ + +ftdm_channel_t* ftdm_sangoma_isdn_process_event_states(ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event) +{ + ftdm_channel_t *ftdmchan = NULL; + switch (sngisdn_event->event_id) { + /* Events that do not have a channel associated to them */ + case SNGISDN_EVENT_SRV_IND: + case SNGISDN_EVENT_SRV_CFM: + case SNGISDN_EVENT_RST_CFM: + case SNGISDN_EVENT_RST_IND: + return NULL; + break; + case SNGISDN_EVENT_CON_IND: + case SNGISDN_EVENT_CON_CFM: + case SNGISDN_EVENT_CNST_IND: + case SNGISDN_EVENT_DISC_IND: + case SNGISDN_EVENT_REL_IND: + case SNGISDN_EVENT_DAT_IND: + case SNGISDN_EVENT_SSHL_IND: + case SNGISDN_EVENT_SSHL_CFM: + case SNGISDN_EVENT_RMRT_IND: + case SNGISDN_EVENT_RMRT_CFM: + case SNGISDN_EVENT_FLC_IND: + case SNGISDN_EVENT_FAC_IND: + case SNGISDN_EVENT_STA_CFM: + ftdmchan = sngisdn_event->sngisdn_info->ftdmchan; + ftdm_assert_return(ftdmchan, NULL,"Event should have a channel associated\n"); + break; + } + ftdm_channel_lock(ftdmchan); + ftdm_sangoma_isdn_advance_chan_states(ftdmchan); + return ftdmchan; +} + + + +static void ftdm_sangoma_isdn_process_stack_event (ftdm_span_t *span, sngisdn_event_data_t *sngisdn_event) +{ + ftdm_channel_t *ftdmchan = NULL; + + ftdmchan = ftdm_sangoma_isdn_process_event_states(span, sngisdn_event); + switch(sngisdn_event->event_id) { + case SNGISDN_EVENT_CON_IND: + sngisdn_process_con_ind(sngisdn_event); + break; + case SNGISDN_EVENT_CON_CFM: + sngisdn_process_con_cfm(sngisdn_event); + break; + case SNGISDN_EVENT_CNST_IND: + sngisdn_process_cnst_ind(sngisdn_event); + break; + case SNGISDN_EVENT_DISC_IND: + sngisdn_process_disc_ind(sngisdn_event); + break; + case SNGISDN_EVENT_REL_IND: + sngisdn_process_rel_ind(sngisdn_event); + break; + case SNGISDN_EVENT_DAT_IND: + sngisdn_process_dat_ind(sngisdn_event); + break; + case SNGISDN_EVENT_SSHL_IND: + sngisdn_process_sshl_ind(sngisdn_event); + break; + case SNGISDN_EVENT_SSHL_CFM: + sngisdn_process_sshl_cfm(sngisdn_event); + break; + case SNGISDN_EVENT_RMRT_IND: + sngisdn_process_rmrt_ind(sngisdn_event); + break; + case SNGISDN_EVENT_RMRT_CFM: + sngisdn_process_rmrt_cfm(sngisdn_event); + break; + case SNGISDN_EVENT_FLC_IND: + sngisdn_process_flc_ind(sngisdn_event); + break; + case SNGISDN_EVENT_FAC_IND: + sngisdn_process_fac_ind(sngisdn_event); + break; + case SNGISDN_EVENT_STA_CFM: + sngisdn_process_sta_cfm(sngisdn_event); + break; + case SNGISDN_EVENT_SRV_IND: + sngisdn_process_srv_ind(sngisdn_event); + break; + case SNGISDN_EVENT_SRV_CFM: + sngisdn_process_srv_cfm(sngisdn_event); + break; + case SNGISDN_EVENT_RST_CFM: + sngisdn_process_rst_cfm(sngisdn_event); + break; + case SNGISDN_EVENT_RST_IND: + sngisdn_process_rst_ind(sngisdn_event); + break; + } + if(ftdmchan != NULL) { + ftdm_sangoma_isdn_advance_chan_states(ftdmchan); + ftdm_channel_unlock(ftdmchan); + } +} + static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) { ftdm_sigmsg_t sigev; - ftdm_signaling_status_t status; + ftdm_channel_state_t initial_state; sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; memset(&sigev, 0, sizeof(sigev)); @@ -295,68 +439,65 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) sigev.channel = ftdmchan; /*first lock the channel*/ - ftdm_mutex_lock(ftdmchan->mutex); - + ftdm_channel_lock(ftdmchan); /*clear the state change flag...since we might be setting a new state*/ ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); +#ifdef FTDM_DEBUG_CHAN_MEMORY + if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { + ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ)==0, "Failed to mprotect"); + } +#endif + + /* Only needed for debugging */ + initial_state = ftdmchan->state; ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "processing state change to %s\n", ftdm_channel_state2str(ftdmchan->state)); switch (ftdmchan->state) { - - case FTDM_CHANNEL_STATE_COLLECT: /* SETUP received but wating on digits */ + case FTDM_CHANNEL_STATE_COLLECT: /* SETUP received but waiting on digits */ { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request - do nothing\n"); - break; - } - - /* TODO: Overlap receive not implemented yet - cannot do it the same way as PRI requires sending complete bit */ - - /* Go straight to ring state for now */ - - /*now go to the RING state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); + /* TODO: Re-implement this. There is a way to re-evaluate new incoming digits from dialplan as they come */ + sngisdn_snd_setup_ack(ftdmchan); + /* Just wait in this state until we get enough digits or T302 timeout */ + } + break; + case FTDM_CHANNEL_STATE_GET_CALLERID: + { + sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); + sngisdn_snd_proceed(ftdmchan); + /* Wait in this state until we get FACILITY msg */ } break; case FTDM_CHANNEL_STATE_RING: /* incoming call request */ { ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending incoming call from %s to %s to FTDM core\n", ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.dnis.digits); - + ftdm_channel_add_var(ftdmchan, "isdn_specific_var", "1"); + ftdm_channel_add_var(ftdmchan, "isdn_crap", "morecrap"); + ftdm_channel_add_var(ftdmchan, "isdn_stuff", "s"); + ftdm_channel_add_var(ftdmchan, "isdn_d", "asdsadasdasdsad"); /* we have enough information to inform FTDM of the call*/ sigev.event_id = FTDM_SIGEVENT_START; ftdm_span_send_signal(ftdmchan->span, &sigev); } break; - case FTDM_CHANNEL_STATE_DIALING: /* outgoing call request */ { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n"); - break; - } sngisdn_snd_setup(ftdmchan); } break; case FTDM_CHANNEL_STATE_PROGRESS: { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n"); - break; - } - /*check if the channel is inbound or outbound*/ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /*OUTBOUND...so we were told by the line of this so noifiy the user*/ sigev.event_id = FTDM_SIGEVENT_PROGRESS; ftdm_span_send_signal(ftdmchan->span, &sigev); - } else { + } else if (!sngisdn_test_flag(sngisdn_info, FLAG_SENT_PROCEED)) { + sngisdn_set_flag(sngisdn_info, FLAG_SENT_PROCEED); sngisdn_snd_proceed(ftdmchan); } } break; - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: { if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { @@ -367,86 +508,72 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) } } break; - case FTDM_CHANNEL_STATE_UP: /* call is answered */ { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n"); - break; - } - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP && - ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) { - /* Assign the call to a specific equipment */ - sngisdn_snd_con_complete(ftdmchan); - } - } - /* check if the channel is inbound or outbound */ if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { /* OUTBOUND ... so we were told by the line that the other side answered */ sigev.event_id = FTDM_SIGEVENT_UP; ftdm_span_send_signal(ftdmchan->span, &sigev); + + if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP && + ((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) { + /* Assign the call to a specific equipment */ + sngisdn_snd_con_complete(ftdmchan); + } } else { /* INBOUND ... so FS told us it just answered ... tell the stack */ sngisdn_snd_connect(ftdmchan); } } break; - case FTDM_CHANNEL_STATE_CANCEL: { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n"); - break; - } - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call before informing user!\n"); /* Send a release complete */ - sngisdn_snd_release(ftdmchan); + sngisdn_snd_release(ftdmchan, 0); /*now go to the HANGUP complete state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); } break; - case FTDM_CHANNEL_STATE_TERMINATING: /* call is hung up by the remote end */ { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n"); - break; - } - /* this state is set when the line is hanging up */ sigev.event_id = FTDM_SIGEVENT_STOP; ftdm_span_send_signal(ftdmchan->span, &sigev); } break; - case FTDM_CHANNEL_STATE_HANGUP: /* call is hung up locally */ { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n"); - break; - } - - if (ftdm_test_flag(sngisdn_info, FLAG_REMOTE_REL)) { + if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT)) { + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote abort\n"); + } else if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_REL)) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Acknowledging remote hangup\n"); - sngisdn_snd_release(ftdmchan); - } else if (ftdm_test_flag(sngisdn_info, FLAG_REMOTE_ABORT)) { - /* Do not send any messages to remote switch as they aborted */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Clearing local states from remote abort\n"); + sngisdn_snd_release(ftdmchan, 0); + } else if (sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) { + /* We aborted this call before sending anything to the stack, so nothing to do anymore */ + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Clearing local states from local abort\n"); + } else if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) { + /* We are hangup local call because there was a glare, we are waiting for a + RELEASE on this call, before we can process the saved call */ + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n"); } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n"); /* set the flag to indicate this hangup is started from the local side */ - ftdm_set_flag(sngisdn_info, FLAG_LOCAL_REL); + sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL); /* If we never sent ack to incoming call, we need to send release instead of disconnect */ - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING) { - ftdm_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - sngisdn_snd_release(ftdmchan); + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || + ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALING) { + + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { + sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); + } + + sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); + sngisdn_snd_release(ftdmchan, 0); } else { sngisdn_snd_disconnect(ftdmchan); } @@ -454,361 +581,114 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) } /* now go to the HANGUP complete state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); } break; - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n"); - break; - } - - if (ftdm_test_flag(sngisdn_info, FLAG_REMOTE_REL)) { - if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_TX)) { - /* go to RESTART State until RSCa is received */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - /* Do nothing as we will receive a RELEASE COMPLETE from remote switch */ - } else if (ftdm_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) || - ftdm_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) { + if (sngisdn_test_flag(sngisdn_info, FLAG_REMOTE_ABORT) || + sngisdn_test_flag(sngisdn_info, FLAG_LOCAL_ABORT)) { /* If the remote side aborted, we will not get anymore message for this call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN); } else { - /* twiddle, waiting on remote confirmation before moving to down */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Completing locally requested hangup\n"); + /* waiting on remote confirmation before moving to down */ + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for release from stack\n"); } } break; - case FTDM_CHANNEL_STATE_DOWN: /* the call is finished and removed */ { - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "re-entering state from processing block/unblock request ... do nothing \n"); - break; - } + uint8_t glare = 0; - /* check if there is a reset response that needs to be sent */ - if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_RX)) { - /* send a RLC */ - sngisdn_snd_release(ftdmchan); - - /* inform Ftdm that the "sig" is up now for this channel */ - status = FTDM_SIG_STATE_UP; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - - /* check if we got the reset response */ - if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_TX)) { - /* inform Ftdm that the "sig" is up now for this channel */ - status = FTDM_SIG_STATE_UP; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } - - /* check if the circuit has the glare flag up */ - if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare flag is up....spoofing incoming call\n"); - /* clear all the call specific data */ - clear_call_data(sngisdn_info); + glare = sngisdn_test_flag(sngisdn_info, FLAG_GLARE); + /* clear all of the call specific data store in the channel structure */ + clear_call_data(sngisdn_info); + /* Close the channel even if we had a glare, we will re-open it when processing state COLLECT for the + "glared call" */ + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { + ftdm_channel_t *close_chan = ftdmchan; /* close the channel */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_t *close_chan = ftdmchan; - /* close the channel */ - ftdm_channel_close(&close_chan); - } + ftdm_channel_close(&close_chan); + } + if (glare) { - /* spoof an incoming call */ - sngisdn_rcv_con_ind(sngisdn_info->glare.suId, - sngisdn_info->glare.suInstId, - sngisdn_info->glare.spInstId, - &sngisdn_info->glare.setup, - sngisdn_info->glare.dChan, - sngisdn_info->glare.ces); - - } else { - /* clear all of the call specific data store in the channel structure */ - clear_call_data(sngisdn_info); - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_t *close_chan = ftdmchan; - /* close the channel */ - ftdm_channel_close(&close_chan); - } + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Glare detected, processing saved call\n"); + /* We are calling sngisdn_rcv_con_ind with ftdmchan->mutex being locked, + so no other threads will be able to touch this channel. The next time we will + process this channel is in this function, and it should be in state COLLECT (set inside + sngisdn_rcv_con_ind)*/ + sngisdn_rcv_con_ind(sngisdn_info->glare.suId, sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId, &sngisdn_info->glare.setup, sngisdn_info->glare.dChan, sngisdn_info->glare.ces); } } break; case FTDM_CHANNEL_STATE_RESTART: { -#if 0 - /* TODO: Go through channel restart call states. They do not make sense when running ISDN */ - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { - /* bring the call down first...then process the rest of the reset */ - switch (ftdmchan->last_state) { - /******************************************************************/ - case(FTDM_CHANNEL_STATE_TERMINATING): - case(FTDM_CHANNEL_STATE_HANGUP): - case(FTDM_CHANNEL_STATE_HANGUP_COMPLETE): - /* go back to the last state after taking care of the rest of the restart state */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - break; - /******************************************************************/ - default: - /* KONRAD: find out what the cause code should be */ - ftdmchan->caller_data.hangup_cause = 41; - - /* change the state to terminatting, it will throw us back here - * once the call is done - */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /******************************************************************/ - } - } else { - - /* check if this an incoming RSC */ - if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_RX)) { - /* go to a down state to clear the channel and send RSCa */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } /* if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_RX)) */ - } /* if (inuse) */ - - /* check if this is an outgoing RSC */ - if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_TX)) { - - /* make sure we aren't coming from hanging up a call */ - if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) { - /* send a reset request */ - sngisdn_snd_reset(ftdmchan); - } - - /* don't change to the DOWN state as we need to wait for the RSCa */ - } /* if (sngisdn_test_flag(sngisdn_info, FLAG_RESET_TX)) */ - - /* send a sig event to the core to disable the channel */ - status = FTDM_SIG_STATE_DOWN; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); -#endif + /* IMPLEMENT ME */ } break; case FTDM_CHANNEL_STATE_SUSPENDED: { - if (sngisdn_test_flag(sngisdn_info, FLAG_INFID_PAUSED)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "processing PAUSE\n"); - /* bring the channel signaling status to down */ - status = FTDM_SIG_STATE_DOWN; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - if (sngisdn_test_flag(sngisdn_info, FLAG_INFID_RESUME)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "processing RESUME\n"); - - /* we just resumed...throw the channel into reset */ - sngisdn_set_flag(sngisdn_info, FLAG_RESET_TX); - - /* clear the resume flag */ - sngisdn_clear_flag(sngisdn_info, FLAG_INFID_RESUME); - - /* go to restart state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - -#if 0 - /* CHECK the equivalent for ISDN */ - if (sngisdn_test_flag(sngisdn_info, FLAG_CKT_MN_BLOCK_RX)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "processing MN_BLOCK_RX\n"); - - /* bring the channel signaling status to down */ - status = FTDM_SIG_STATE_DOWN; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - - /* send a BLA */ - - ft_to_sngss7_bla(ftdmchan); - - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - if (sngisdn_test_flag(sngisdn_info, FLAG_CKT_MN_UNBLK_RX)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "processing MN_UNBLK_RX\n"); - /* bring the channel signaling status to up */ - status = FTDM_SIG_STATE_UP; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - - /* clear the unblock flag */ - sngisdn_clear_flag(sngisdn_info, FLAG_CKT_MN_UNBLK_RX); - - /* send a uba */ - ft_to_sngss7_uba(ftdmchan); - - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - /**********************************************************************/ - if (sngisdn_test_flag(sngisdn_info, FLAG_CKT_MN_BLOCK_TX)) { - ftdm_log_chan_msg(ftdm_chan, FTDM_LOG_DEBUG, "processing MN_BLOCK_TX\n"); - /* bring the channel signaling status to down */ - status = FTDM_SIG_STATE_DOWN; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - - /* send a blo */ - ft_to_sngss7_blo(ftdmchan); - - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - if (sngisdn_test_flag(sngisdn_info, FLAG_CKT_MN_UNBLK_TX)) { - ftdm_log_chan_msg(ftdm_chan, FTDM_LOG_DEBUG, "processing MN_UNBLOCK_TX\n"); - /* bring the channel signaling status to up */ - status = FTDM_SIG_STATE_UP; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - - /* clear the unblock flag */ - sngisdn_clear_flag(sngisdn_info, FLAG_CKT_MN_UNBLK_TX); - - /* send a ubl */ - ft_to_sngss7_ubl(ftdmchan); - - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } -#endif + /* IMPLEMENT ME */ } break; default: { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state)); + ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "unsupported sngisdn_rcvd state %s\n", ftdm_channel_state2str(ftdmchan->state)); } break; - } - - ftdm_mutex_unlock(ftdmchan->mutex); + + if (ftdmchan->state == initial_state) { + ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "state change flag is still set, but we did not change state\n"); + } +#ifdef FTDM_DEBUG_CHAN_MEMORY + if (ftdmchan->state == FTDM_CHANNEL_STATE_DIALING) { + ftdm_assert(mprotect(ftdmchan, sizeof(*ftdmchan), PROT_READ|PROT_WRITE)==0, "Failed to mprotect"); + } +#endif + ftdm_channel_unlock(ftdmchan); return; } static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call) { - sngisdn_chan_data_t *sngisdn_info; - int c; - + sngisdn_chan_data_t *sngisdn_info = ftdmchan->call_data; + ftdm_status_t status = FTDM_FAIL; + /* lock the channel while we check whether it is availble */ - ftdm_mutex_lock(ftdmchan->mutex); + ftdm_channel_lock(ftdmchan); switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_DOWN: - { - ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); + case FTDM_CHANNEL_STATE_DOWN: + { + if (sngisdn_test_flag(sngisdn_info, FLAG_GLARE)) { + /* A call came in after we called ftdm_channel_open_chan for this call, but before we got here */ + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected - aborting outgoing call\n"); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - /* now we have to wait for either the stack to reject the call because of - * glare or for the network to acknowledge the call */ - c = 0; - - while (c < 100) { - - /* lock the channel while we check whether it is availble */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* extract the sngisdn_chan_data structure */ - sngisdn_info = (sngisdn_chan_data_t *)ftdmchan->call_data; - - if (ftdm_test_flag(sngisdn_info, FLAG_GLARE)) { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Glare detected\n"); - goto outgoing_glare; + status = FTDM_BREAK; + } else { + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING); + status = FTDM_SUCCESS; } - - switch (ftdmchan->state) { - case FTDM_CHANNEL_STATE_DIALING: - break; - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: - { - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Outgoing call request successful\n"); - goto outgoing_successful; - } - break; - case FTDM_CHANNEL_STATE_TERMINATING: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - case FTDM_CHANNEL_STATE_DOWN: - { - /* Remote switch aborted this call */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Outgoing call request failed\n"); - goto outgoing_successful; - } - break; - default: - { - ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Channel in invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state)); - goto outgoing_glare; - } - break; - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - /* sleep for a bit to let the state change */ - ftdm_sleep(10); - - /* increment the timeout counter */ - c++; } - - /* only way we can get here is if we are still in STATE_DIALING. We did not get a glare, so exit thread and wait for PROCEED/PROGRESS/ALERT/CONNECT or RELEASE from remote switch */ - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Timeout waiting for outgoing call to be accepted by network, returning success anyways\n"); - - /* consider the call good .... for now */ - goto outgoing_successful; - } - break; - - default: + break; + default: { /* the channel is already used...this can't be, end the request */ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Outgoing call requested channel in already in use\n"); - goto outgoing_glare; + status = FTDM_BREAK; } break; } - ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "WE SHOULD NOT BE HERE!!!!\n"); - - ftdm_mutex_unlock(ftdmchan->mutex); - return FTDM_FAIL; - -outgoing_glare: - ftdm_mutex_unlock(ftdmchan->mutex); - return FTDM_BREAK; - -outgoing_successful: - ftdm_mutex_unlock(ftdmchan->mutex); - return FTDM_SUCCESS; + ftdm_channel_unlock(ftdmchan); + return status; } static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_sig_status) @@ -863,8 +743,8 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span) ftdm_sleep(10); } - /* FIXME: deconfigure any circuits, links, attached to this span */ - /* TODO: confirm with Moy whether we should start channels at 1 or 0 */ + /* FIXME: deconfigure any links, attached to this span */ + /* TODO: Use Moy's channel Iterator when its implemented */ for (i=1;i<=span->chan_count;i++) { ftdm_safe_free(span->channels[i]->call_data); } @@ -906,9 +786,6 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) span->start = ftdm_sangoma_isdn_start; span->stop = ftdm_sangoma_isdn_stop; span->signal_type = FTDM_SIGTYPE_ISDN; -#if 0 - span->signal_data = NULL; -#endif span->outgoing_call = ftdm_sangoma_isdn_outgoing_call; span->channel_request = NULL; span->signal_cb = sig_cb; @@ -916,6 +793,20 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config) span->set_channel_sig_status = ftdm_sangoma_isdn_set_sig_status; span->state_map = &sangoma_isdn_state_map; ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); + ftdm_set_flag(span, FTDM_SPAN_USE_SIGNALS_QUEUE); + + if (span->trunk_type == FTDM_TRUNK_BRI_PTMP || + span->trunk_type == FTDM_TRUNK_BRI) { + + ftdm_set_flag(span, FTDM_SPAN_USE_AV_RATE); + sng_isdn_set_avail_rate(span, SNGISDN_AVAIL_PWR_SAVING); + } + + /* Initialize scheduling context */ + ftdm_assert(ftdm_sched_create(&((sngisdn_span_data_t*)span->signal_data)->sched, "sngisdn_schedule") == FTDM_SUCCESS, "Failed to create a new schedule!!"); + + /* Initialize the event queue */ + ftdm_assert(ftdm_queue_create(&((sngisdn_span_data_t*)span->signal_data)->event_queue, SNGISDN_EVENT_QUEUE_SIZE) == FTDM_SUCCESS, "Failed to create a new queue!!"); ftdm_log(FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_isdn span = %s\n", span->name); return FTDM_SUCCESS; @@ -948,22 +839,22 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init) g_sngisdn_event_interface.cc.sng_rst_ind = sngisdn_rcv_rst_ind; g_sngisdn_event_interface.cc.sng_rst_cfm = sngisdn_rcv_rst_cfm; - g_sngisdn_event_interface.lg.sng_log = sngisdn_rcv_sng_log; + g_sngisdn_event_interface.lg.sng_log = sngisdn_rcv_sng_log; + g_sngisdn_event_interface.lg.sng_assert = sngisdn_rcv_sng_assert; + g_sngisdn_event_interface.sta.sng_phy_sta_ind = sngisdn_rcv_phy_ind; g_sngisdn_event_interface.sta.sng_q921_sta_ind = sngisdn_rcv_q921_ind; g_sngisdn_event_interface.sta.sng_q921_trc_ind = sngisdn_rcv_q921_trace; g_sngisdn_event_interface.sta.sng_q931_sta_ind = sngisdn_rcv_q931_ind; g_sngisdn_event_interface.sta.sng_q931_trc_ind = sngisdn_rcv_q931_trace; - g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind; + g_sngisdn_event_interface.sta.sng_cc_sta_ind = sngisdn_rcv_cc_ind; for(i=1;i<=MAX_VARIANTS;i++) { - ftdm_mutex_create(&g_sngisdn_data.ccs[i].request_mutex); + ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex); } + /* initalize sng_isdn library */ sng_isdn_init(&g_sngisdn_event_interface); - - /* crash on assert fail */ - ftdm_global_set_crash_policy(FTDM_CRASH_ON_ASSERT); return FTDM_SUCCESS; } @@ -975,7 +866,7 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_isdn_unload) sng_isdn_free(); for(i=1;i<=MAX_VARIANTS;i++) { - ftdm_mutex_destroy(&g_sngisdn_data.ccs[i].request_mutex); + ftdm_mutex_destroy(&g_sngisdn_data.ccs[i].mutex); } ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_isdn unload!\n"); @@ -1026,6 +917,23 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api) stream->write_function(stream, "-ERR invalid trace option \n"); } } + if (!strcasecmp(argv[0], "l1_stats")) { + ftdm_span_t *span; + if (argc < 2) { + ftdm_log(FTDM_LOG_ERROR, "Usage: ftdm sangoma_isdn l1_stats \n"); + status = FTDM_FAIL; + goto done; + } + status = ftdm_span_find_by_name(argv[1], &span); + if (FTDM_SUCCESS != status) { + stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]); + goto done; + } + /* TODO: implement PHY stats */ + } + if (!strcasecmp(argv[0], "check_ids")) { + sngisdn_check_free_ids(); + } done: ftdm_safe_free(mycmd); return status; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index d3877defd3..3f63fbc1d4 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -46,116 +46,28 @@ #include -#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,43 @@ 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); + +uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability); +uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot); +ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability); +ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_user(uint8_t layer1_prot); + +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__ */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index d0254fd714..ec44142303 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -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,34 @@ 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; + + span->default_caller_data.bearer_capability = IN_ITC_SPEECH; + + /* Cannot set default bearer_layer1 yet, as we do not know the switchtype */ + span->default_caller_data.bearer_layer1 = FTDM_INVALID_INT_PARM; + + 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 +195,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 +207,48 @@ 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 if (!strcasecmp(var, "outbound-bearer_cap")) { + ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); + } else if (!strcasecmp(var, "outbound-bearer_layer1")) { + ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); } else { ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var); } @@ -202,6 +262,14 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ ftdm_log(FTDM_LOG_ERROR, "%s: signalling not specified", span->name); return FTDM_FAIL; } + + if (span->default_caller_data.bearer_layer1 == FTDM_INVALID_INT_PARM) { + if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) { + span->default_caller_data.bearer_layer1 = IN_UIL1_G711ULAW; + } else { + span->default_caller_data.bearer_layer1 = IN_UIL1_G711ALAW; + } + } return FTDM_SUCCESS; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c index 5299c91b44..7aba6a66ce 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c @@ -48,7 +48,7 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status sig.span_id = ftdmchan->span_id; sig.channel = ftdmchan; sig.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sig.raw_data = &status; + sig.sigstatus = status; ftdm_span_send_signal(ftdmchan->span, &sig); return; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index c44228d033..f84e018f1e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -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; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c index d02314a82f..f92eceda5e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c @@ -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 diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c new file mode 100644 index 0000000000..c3d97e5c5c --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -0,0 +1,942 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * David Yat Sin + * 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_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); +extern ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); +extern ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); +extern ftdm_status_t cpy_calling_name_from_stack(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_mutex_lock(g_sngisdn_data.ccs[suId].mutex); + 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_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb); + cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb); + cpy_calling_name_from_stack(&ftdmchan->caller_data, &conEvnt->display); + + if (conEvnt->bearCap[0].eh.pres) { + ftdmchan->caller_data.bearer_layer1 = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].usrInfoLyr1Prot.val); + ftdmchan->caller_data.bearer_capability = sngisdn_get_infoTranCap_from_stack(conEvnt->bearCap[0].infoTranCap.val); + } + + 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\n"); + + 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; + 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; + + 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; + + 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 (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; + + 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_stack(&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; + + 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 (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_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: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: + /* 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; +} diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c deleted file mode 100644 index 04430cf0f0..0000000000 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_in.c +++ /dev/null @@ -1,935 +0,0 @@ -/* - * Copyright (c) 2010, Sangoma Technologies - * David Yat Sin - * 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;jb_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 (ib_wptr) { - tmp = tmp->b_cont; - if (tmp) cptr = tmp->b_rptr; - } - i++; - if (it.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: - */ - -/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index c5e986bea3..6e8e0e81fd 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -34,16 +34,16 @@ #include "ftmod_sangoma_isdn.h" -extern ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); -extern ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); -extern ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); +extern ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); +extern ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); +extern ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan); void sngisdn_snd_setup(ftdm_channel_t *ftdmchan); 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,17 +52,20 @@ 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; conEvnt.bearCap[0].infoTranCap.pres = PRSNT_NODEF; - - conEvnt.bearCap[0].infoTranCap.val = IN_ITC_SPEECH; + conEvnt.bearCap[0].infoTranCap.val = sngisdn_get_infoTranCap_from_user(ftdmchan->caller_data.bearer_capability); conEvnt.bearCap[0].codeStand0.pres = PRSNT_NODEF; conEvnt.bearCap[0].codeStand0.val = IN_CSTD_CCITT; @@ -92,18 +95,28 @@ 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; - } else { - conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF; + conEvnt.bearCap[0].usrInfoLyr1Prot.pres = PRSNT_NODEF; + conEvnt.bearCap[0].usrInfoLyr1Prot.val = sngisdn_get_usrInfoLyr1Prot_from_user(ftdmchan->caller_data.bearer_layer1); + + if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN && + conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ULAW) { + + /* We are bridging a call from T1 */ conEvnt.bearCap[0].usrInfoLyr1Prot.val = IN_UIL1_G711ALAW; + + } else if (conEvnt.bearCap[0].usrInfoLyr1Prot.val == IN_UIL1_G711ALAW) { + + /* We are bridging a call from E1 */ + 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 +143,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_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); + cpy_called_num_from_user(&conEvnt.cdPtyNmb, &ftdmchan->caller_data); + cpy_calling_num_from_user(&conEvnt.cgPtyNmb, &ftdmchan->caller_data); + cpy_calling_name_from_user(&conEvnt, ftdmchan); + + 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 +225,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 +267,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 +283,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 +325,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 +340,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 +361,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 +377,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 +394,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 +409,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 +451,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 +533,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 +569,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: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c new file mode 100644 index 0000000000..29cfb2330e --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -0,0 +1,930 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * David Yat Sin + * 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->spInstId = spInstId; + sngisdn_event->dChan = dChan; + sngisdn_event->ces = ces; + + 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); + + 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; + } + + 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(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; + } + + 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(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); + ftdm_assert(0, "Inconsistent call states\n"); + return; + } + + 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(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); + ftdm_assert(0, "Inconsistent call states\n"); + 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); + ftdm_assert(0, "Inconsistent call states\n"); + 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); + ftdm_assert(0, "Inconsistent call states\n"); + 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); + ftdm_assert(0, "Inconsistent call states\n"); + 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); + ftdm_assert(0, "Inconsistent call states\n"); + 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); + ftdm_assert(0, "Inconsistent call states\n"); + 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); + ftdm_assert(0, "Inconsistent call states\n"); + 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); + ftdm_assert(0, "Inconsistent call states\n"); + 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); + ftdm_assert(0, "Inconsistent call states\n"); + 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; + } + } + } + if (ftdmspan == NULL) { + ftdm_log(FTDM_LOG_WARNING, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb); + 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); + + 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;jb_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 (ib_wptr) { + tmp = tmp->b_cont; + if (tmp) cptr = tmp->b_rptr; + } + i++; + if (it.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: + */ + +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index b922efc809..29e7994c87 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -34,25 +34,30 @@ #include "ftmod_sangoma_isdn.h" -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_num_from_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb); +ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb); +ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb); +ftdm_status_t cpy_calling_name_from_stack(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 cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm); +ftdm_status_t cpy_calling_name_from_user(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,8 +132,21 @@ 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) { -ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb) + 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_stack(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb) { if (cgPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -132,7 +173,7 @@ ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *c return FTDM_SUCCESS; } -ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb) +ftdm_status_t cpy_called_num_from_stack(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb) { if (cdPtyNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -147,12 +188,14 @@ 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; } -ftdm_status_t cpy_redir_num_from_sngisdn(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb) +ftdm_status_t cpy_redir_num_from_stack(ftdm_caller_data_t *ftdm, RedirNmb *redirNmb) { if (redirNmb->eh.pres != PRSNT_NODEF) { return FTDM_FAIL; @@ -172,17 +215,20 @@ 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_stack(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; } -ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_calling_num_from_user(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->cid_num.digits); if (!len) { @@ -210,7 +256,7 @@ ftdm_status_t cpy_calling_num_to_sngisdn(CgPtyNmb *cgPtyNmb, ftdm_caller_data_t return FTDM_SUCCESS; } -ftdm_status_t cpy_called_num_to_sngisdn(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_called_num_from_user(CdPtyNmb *cdPtyNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->dnis.digits); if (!len) { @@ -219,19 +265,28 @@ 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; } -ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm) +ftdm_status_t cpy_redir_num_from_user(RedirNmb *redirNmb, ftdm_caller_data_t *ftdm) { uint8_t len = strlen(ftdm->rdnis.digits); if (!len) { @@ -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; @@ -255,7 +318,7 @@ ftdm_status_t cpy_redir_num_to_sngisdn(RedirNmb *redirNmb, ftdm_caller_data_t *f } -ftdm_status_t cpy_calling_name_to_sngisdn(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) +ftdm_status_t cpy_calling_name_from_user(ConEvnt *conEvnt, ftdm_channel_t *ftdmchan) { uint8_t len; ftdm_caller_data_t *ftdm = &ftdmchan->caller_data; @@ -308,28 +371,93 @@ 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"); -#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); + 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); - /* 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"); + sngisdn_snd_release(ftdmchan, 1); + clear_call_glare_data(sngisdn_info); + } 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 + * 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 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); +/******************************************************************************/ + +/* FUNCTIONS ******************************************************************/ +int ft_to_sngss7_cfg_all(void) +{ + int x = 0; + + /* check if we have done gen_config already */ + if (!(g_ftdm_sngss7_data.gen_config)) { + + if (sng_validate_license(g_ftdm_sngss7_data.cfg.license, + g_ftdm_sngss7_data.cfg.signature, + g_ftdm_sngss7_data.cfg.spc)) { + + SS7_CRITICAL("License verification failed..ending!\n"); + return 1; + } + + if (ftmod_ss7_mtp1_gen_config()) { + SS7_CRITICAL("MTP1 General configuration FAILED!\n"); + SS7_ASSERT + } else { + SS7_INFO("MTP1 General configuration DONE\n"); + } + + if (ftmod_ss7_mtp2_gen_config()) { + SS7_CRITICAL("MTP2 General configuration FAILED!\n"); + SS7_ASSERT + } else { + SS7_INFO("MTP2 General configuration DONE\n"); + } + + if (ftmod_ss7_mtp3_gen_config()) { + SS7_CRITICAL("MTP3 General configuration FAILED!\n"); + SS7_ASSERT + } else { + SS7_INFO("MTP3 General configuration DONE\n"); + } + + if (ftmod_ss7_isup_gen_config()) { + SS7_CRITICAL("ISUP General configuration FAILED!\n"); + SS7_ASSERT + } else { + SS7_INFO("ISUP General configuration DONE\n"); + } + + if (ftmod_ss7_cc_gen_config()) { + SS7_CRITICAL("CC General configuration FAILED!\n"); + SS7_ASSERT + } else { + SS7_INFO("CC General configuration DONE\n"); + } + + /* update the global gen_config so we don't do it again */ + g_ftdm_sngss7_data.gen_config = 1; + } + + + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + /* check if this link has been configured already */ + if (!(g_ftdm_sngss7_data.cfg.mtpLink[x].flags & CONFIGURED)) { + + /* configure mtp1 */ + if (ftmod_ss7_mtp1_psap_config(x)) { + SS7_CRITICAL("MTP1 PSAP %d configuration FAILED!\n", x); + SS7_ASSERT; + } else { + SS7_INFO("MTP1 PSAP %d configuration DONE!\n", x); + } + + /* configure mtp2 */ + if (ftmod_ss7_mtp2_dlsap_config(x)) { + SS7_CRITICAL("MTP2 DLSAP %d configuration FAILED!\n",x); + SS7_ASSERT; + } else { + SS7_INFO("MTP2 DLSAP %d configuration DONE!\n", x); + } + + /* configure mtp3 */ + if (ftmod_ss7_mtp3_dlsap_config(x)) { + SS7_CRITICAL("MTP3 DLSAP %d configuration FAILED!\n", x); + SS7_ASSERT; + } else { + SS7_INFO("MTP3 DLSAP %d configuration DONE!\n", x); + } + + /* set the CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.mtpLink[x].flags |= CONFIGURED; + } + + x++; + } /* while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) */ + + x = 1; + while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) { + /* check if this link has been configured already */ + if (!(g_ftdm_sngss7_data.cfg.nsap[x].flags & CONFIGURED)) { + + if (ftmod_ss7_mtp3_nsap_config(x)) { + SS7_CRITICAL("MTP3 NSAP %d configuration FAILED!\n", x); + SS7_ASSERT + } else { + SS7_INFO("MTP3 NSAP %d configuration DONE!\n", x); + } + + if (ftmod_ss7_isup_nsap_config(x)) { + SS7_CRITICAL("ISUP NSAP %d configuration FAILED!\n", x); + SS7_ASSERT + } else { + SS7_INFO("ISUP NSAP %d configuration DONE!\n", x); + } + + /* set the CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.nsap[x].flags |= CONFIGURED; + } /* if !CONFIGURED */ + + x++; + } /* while (g_ftdm_sngss7_data.cfg.nsap[x].id != 0) */ + + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) { + /* check if this link has been configured already */ + if (!(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags & CONFIGURED)) { + + if (ftmod_ss7_mtp3_linkset_config(x)) { + SS7_CRITICAL("MTP3 LINKSET %d configuration FAILED!\n", x); + SS7_ASSERT + } else { + SS7_INFO("MTP3 LINKSET %d configuration DONE!\n", x); + } + + /* set the CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= CONFIGURED; + } /* if !CONFIGURED */ + + x++; + } /* while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) */ + + x = 1; + while ((g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0)) { + /* check if this link has been configured already */ + if (!(g_ftdm_sngss7_data.cfg.mtpRoute[x].flags & CONFIGURED)) { + + if (ftmod_ss7_mtp3_route_config(x)) { + SS7_CRITICAL("MTP3 ROUTE %d configuration FAILED!\n", x); + SS7_ASSERT + } else { + SS7_INFO("MTP3 ROUTE %d configuration DONE!\n"); + } + + /* set the CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.mtpRoute[x].flags |= CONFIGURED; + } /* if !CONFIGURED */ + + x++; + } /* while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) */ + + if (!(g_ftdm_sngss7_data.cfg.mtpRoute[0].flags & CONFIGURED)) { + + if (ftmod_ss7_mtp3_route_config(0)) { + SS7_CRITICAL("MTP3 ROUTE 0 configuration FAILED!\n"); + SS7_ASSERT + } else { + SS7_INFO("MTP3 ROUTE %d configuration DONE!\n"); + } + + /* set the CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.mtpRoute[0].flags |= CONFIGURED; + } /* if !CONFIGURED */ + + + x = 1; + while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) { + /* check if this link has been configured already */ + if (!(g_ftdm_sngss7_data.cfg.isap[x].flags & CONFIGURED)) { + + if (ftmod_ss7_isup_isap_config(x)) { + SS7_CRITICAL("ISUP ISAP %d configuration FAILED!\n", x); + SS7_ASSERT + } else { + SS7_INFO("ISUP ISAP %d configuration DONE!\n", x); + } + + if (ftmod_ss7_cc_isap_config(x)) { + SS7_CRITICAL("CC ISAP %d configuration FAILED!\n", x); + SS7_ASSERT + } else { + SS7_INFO("CC ISAP %d configuration DONE!\n", x); + } + + /* set the CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.isap[x].flags |= CONFIGURED; + } /* if !CONFIGURED */ + + x++; + } /* while (g_ftdm_sngss7_data.cfg.isap[x].id != 0) */ + + x = 1; + while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) { + /* check if this link has been configured already */ + if (!(g_ftdm_sngss7_data.cfg.isupIntf[x].flags & CONFIGURED)) { + + if (ftmod_ss7_isup_intf_config(x)) { + SS7_CRITICAL("ISUP INTF %d configuration FAILED!\n", x); + SS7_ASSERT + } else { + SS7_INFO("ISUP INTF %d configuration DONE!\n", x); + } + + /* set the CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.isupIntf[x].flags |= CONFIGURED; + } /* if !CONFIGURED */ + + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) */ + + x = 1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + /* check if this link has been configured already */ + if (!(g_ftdm_sngss7_data.cfg.isupCkt[x].flags & CONFIGURED)) { + if ( g_ftdm_sngss7_data.cfg.isupCkt[x].type == 0) { + if (ftmod_ss7_isup_ckt_config(x)) { + SS7_CRITICAL("ISUP CKT %d configuration FAILED!\n", x); + SS7_ASSERT + } else { + SS7_INFO("ISUP CKT %d configuration DONE!\n", x); + } + } + + /* set the CONFIGURED flag */ + g_ftdm_sngss7_data.cfg.isupCkt[x].flags |= CONFIGURED; + } /* if !CONFIGURED */ + + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ + + return 0; +} + +/******************************************************************************/ +int ftmod_ss7_mtp1_gen_config(void) +{ + L1Mngmt cfg; /*configuration structure*/ + Pst pst; /*post structure*/ + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTL1; + + /* clear the configuration structure */ + memset(&cfg, 0x0, sizeof(L1Mngmt)); + + /* fill in some general sections of the header */ + smHdrInit(&cfg.hdr); + + /* fill in the post structure */ + smPstInit( &cfg.t.cfg.s.l1Gen.sm ); + + /*fill in the specific fields of the header */ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTL1; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STGEN; + + cfg.t.cfg.s.l1Gen.sm.srcEnt = ENTL1; + cfg.t.cfg.s.l1Gen.sm.dstEnt = ENTSM; + + cfg.t.cfg.s.l1Gen.nmbLnks = MAX_L1_LINKS; + cfg.t.cfg.s.l1Gen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ + cfg.t.cfg.s.l1Gen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ + + return(sng_cfg_mtp1(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_mtp2_gen_config(void) +{ + SdMngmt cfg; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSD; + + /* clear the configuration structure */ + memset(&cfg, 0x0, sizeof(SdMngmt)); + + /* fill in some general sections of the header */ + smHdrInit(&cfg.hdr); + + /* fill in the post structure */ + smPstInit( &cfg.t.cfg.s.sdGen.sm ); + + /* fill in the specific fields of the header */ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSD; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STGEN; + + cfg.t.cfg.s.sdGen.sm.srcEnt = ENTSD; + cfg.t.cfg.s.sdGen.sm.dstEnt = ENTSM; + + cfg.t.cfg.s.sdGen.nmbLnks = MAX_SD_LINKS; + cfg.t.cfg.s.sdGen.poolTrUpper = POOL_UP_TR; + cfg.t.cfg.s.sdGen.poolTrLower = POOL_LW_TR; + + return(sng_cfg_mtp2(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_mtp3_gen_config(void) +{ + SnMngmt cfg; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SnMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /* fill in the post structure */ + smPstInit(&cfg.t.cfg.s.snGen.sm); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STGEN; + + cfg.t.cfg.s.snGen.sm.srcEnt = ENTSN; + cfg.t.cfg.s.snGen.sm.dstEnt = ENTSM; + + + cfg.t.cfg.s.snGen.typeSP = LSN_TYPE_SP; /* type of signalling postatic int */ + cfg.t.cfg.s.snGen.spCode1 = g_ftdm_sngss7_data.cfg.spc; /* our DPC for CCITT version */ + +#if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA || defined(TDS_ROLL_UPGRADE_SUPPORT)) + cfg.t.cfg.s.snGen.spCode2 = g_ftdm_sngss7_data.cfg.spc; /* our DPC for ANSI or CHINA version */ +#endif + + cfg.t.cfg.s.snGen.ssfValid = TRUE; /* ssf validation required */ + cfg.t.cfg.s.snGen.nmbDLSap = MAX_SN_LINKS; /* number of MTP Data Link SAPs */ + cfg.t.cfg.s.snGen.nmbNSap = MAX_SN_VARIANTS; /* number of Upper Layer Saps */ + cfg.t.cfg.s.snGen.nmbRouts = MAX_SN_ROUTES; /* maximum number of routing entries */ + cfg.t.cfg.s.snGen.nmbLnkSets = MAX_SN_LINKSETS; /* number of link sets */ + cfg.t.cfg.s.snGen.nmbRteInst = MAX_SN_ROUTES*16; /* number of simultaneous Rte instances */ + cfg.t.cfg.s.snGen.cbTimeRes = SN_CB_PERIOD; /* link time resolution */ + cfg.t.cfg.s.snGen.spTimeRes = SN_SP_PERIOD; /* general time resolution */ + cfg.t.cfg.s.snGen.rteTimeRes = SN_RTE_PERIOD; /* route time resolution */ + cfg.t.cfg.s.snGen.extCmbndLnkst = FALSE; /* enbale extended combined linkset feature */ + +#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART)) + +#else + cfg.t.cfg.s.snGen.rstReq = LSN_NO_RST; /* restarting procedure required */ + cfg.t.cfg.s.snGen.tfrReq = FALSE; /* TFR procedure required or not */ + cfg.t.cfg.s.snGen.tmr.t15.enb = TRUE; /* t15 - waiting to start route set congestion test */ + cfg.t.cfg.s.snGen.tmr.t15.val = 30; + cfg.t.cfg.s.snGen.tmr.t16.enb = TRUE; /* t16 - waiting for route set congestion status update */ + cfg.t.cfg.s.snGen.tmr.t16.val = 20; + cfg.t.cfg.s.snGen.tmr.t18.enb = TRUE; /* t18 - waiting for links to become available */ + cfg.t.cfg.s.snGen.tmr.t18.val = 200; + cfg.t.cfg.s.snGen.tmr.t19.enb = TRUE; /* t19 - waiting to receive all traffic restart allowed */ + cfg.t.cfg.s.snGen.tmr.t19.val = 690; + cfg.t.cfg.s.snGen.tmr.t21.enb = TRUE; /* t21 - waiting to restart traffic routed through adjacent SP */ + cfg.t.cfg.s.snGen.tmr.t21.val = 650; +# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT)) + cfg.t.cfg.s.snGen.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */ + cfg.t.cfg.s.snGen.t26.val = 600; +# endif +#endif + +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS96) + cfg.t.cfg.s.snGen.mopc = FALSE; +#endif + + return(sng_cfg_mtp3(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_isup_gen_config(void) +{ + SiMngmt cfg; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSI; + + /* clear the configuration structure */ + memset(&cfg, 0x0, sizeof(SiMngmt)); + + /* fill in some general sections of the header */ + smHdrInit(&cfg.hdr); + + /* fill in the post structure */ + smPstInit( &cfg.t.cfg.s.siGen.sm ); + + /*fill in the specific fields of the header */ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSI; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STGEN; + + cfg.t.cfg.s.siGen.sm.srcEnt = ENTSI; + cfg.t.cfg.s.siGen.sm.dstEnt = ENTSM; + + cfg.t.cfg.s.siGen.nmbSaps = MAX_CC_INTERFACE; /* Number of ISUP Saps */ + cfg.t.cfg.s.siGen.nmbNSaps = MAX_SN_INTERFACE; /* Number of Network Saps */ + cfg.t.cfg.s.siGen.nmbCir = MAX_SI_CIRCUITS; /* Number of circuits */ + cfg.t.cfg.s.siGen.nmbIntf = MAX_SI_INTERFACES; /* Number of interfaces */ + cfg.t.cfg.s.siGen.nmbCirGrp = MAX_SI_CIR_GRP; /* Max number of circuit groups */ + cfg.t.cfg.s.siGen.nmbCalRef = MAX_SI_CALL_REF; /* Number of Call References */ + cfg.t.cfg.s.siGen.timeRes = SI_PERIOD; /* time resolution */ + cfg.t.cfg.s.siGen.sccpSup = FALSE; /* SCCP support */ + cfg.t.cfg.s.siGen.handleTTBinCC = FALSE; /* Flag used for controlling TTB feature */ + cfg.t.cfg.s.siGen.mapCPCandFCI = TRUE; /* Flag used for controlling TTB feature */ +#if (LSIV3 || LSIV4 || LSIV5) + cfg.t.cfg.s.siGen.lnkSelOpt = SI_LINK_SELECTION; /* link selector option */ +#endif + cfg.t.cfg.s.siGen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ + cfg.t.cfg.s.siGen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ + cfg.t.cfg.s.siGen.cirGrTmr.t18.enb = TRUE; /* t18 timer - group blocking sent */ + cfg.t.cfg.s.siGen.cirGrTmr.t18.val = 300; + cfg.t.cfg.s.siGen.cirGrTmr.t19.enb = TRUE; /* t19 timer - initial group blocking sent */ + cfg.t.cfg.s.siGen.cirGrTmr.t19.val = 3000; + cfg.t.cfg.s.siGen.cirGrTmr.t20.enb = TRUE; /* t20 timer - group unblocking sent */ + cfg.t.cfg.s.siGen.cirGrTmr.t20.val = 300; + cfg.t.cfg.s.siGen.cirGrTmr.t21.enb = TRUE; /* t21 timer - initial grp unblocking sent */ + cfg.t.cfg.s.siGen.cirGrTmr.t21.val = 3000; + cfg.t.cfg.s.siGen.cirGrTmr.t22.enb = TRUE; /* t22 timer - group reset sent */ + cfg.t.cfg.s.siGen.cirGrTmr.t22.val = 300; + cfg.t.cfg.s.siGen.cirGrTmr.t23.enb = TRUE; /* t23 timer - initial group reset sent */ + cfg.t.cfg.s.siGen.cirGrTmr.t23.val = 3000; +#ifndef SS7_UK + cfg.t.cfg.s.siGen.cirGrTmr.t28.enb = TRUE; /* t28 timer - circuit group query sent */ + cfg.t.cfg.s.siGen.cirGrTmr.t28.val = 100; +#endif +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + cfg.t.cfg.s.siGen.cirGrTmr.tFGR.enb = TRUE; /* first group received timer */ + cfg.t.cfg.s.siGen.cirGrTmr.tFGR.val = 50; +#endif +#if CGPN_CHK + cfg.t.cfg.s.siGen.cgPtyNumGenCfg = TRUE; /* Calling party number general config flag */ +#endif +#ifdef SI_SUPPRESS_CFN + cfg.t.cfg.s.siGen.suppressCfn = TRUE; /* Flag used for 'suppress CFN' feature */ +#endif + + return(sng_cfg_isup(&pst, &cfg)); + +} + +/******************************************************************************/ +int ftmod_ss7_cc_gen_config(void) +{ + CcMngmt cfg; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTCC; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(CcMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /* fill in the post structure */ + smPstInit( &cfg.t.cfg.s.ccGen.sm ); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTCC; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STGEN; + + cfg.t.cfg.s.ccGen.sm.srcEnt = ENTCC; + cfg.t.cfg.s.ccGen.sm.dstEnt = ENTSM; + + cfg.t.cfg.s.ccGen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */ + cfg.t.cfg.s.ccGen.poolTrLower = POOL_LW_TR; /* lower pool threshold */ + + return(sng_cfg_cc(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_mtp1_psap_config(int id) +{ + L1Mngmt cfg; + Pst pst; + sng_mtp_link_t *k = &g_ftdm_sngss7_data.cfg.mtpLink[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTL1; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(L1Mngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTL1; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STPSAP; + + cfg.hdr.elmId.elmntInst1 = k->id; + + cfg.t.cfg.s.l1PSAP.span = k->mtp1.span; + cfg.t.cfg.s.l1PSAP.chan = k->mtp1.chan; + cfg.t.cfg.s.l1PSAP.spId = k->id; + + return(sng_cfg_mtp1(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_mtp2_dlsap_config(int id) +{ + SdMngmt cfg; + Pst pst; + sng_mtp_link_t *k = &g_ftdm_sngss7_data.cfg.mtpLink[id]; + + /* initalize the post structure */ + smPstInit( &pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSD; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SdMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSD; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STDLSAP; + + cfg.hdr.elmId.elmntInst1 = k->id; + + cfg.t.cfg.s.sdDLSAP.mem.region = S_REG; /* memory region */ + cfg.t.cfg.s.sdDLSAP.mem.pool = S_POOL; /* memory pool */ + cfg.t.cfg.s.sdDLSAP.swtch = k->mtp2.linkType; /* protocol type */ + cfg.t.cfg.s.sdDLSAP.priorDl = PRIOR0; /* priority for data link layer */ + cfg.t.cfg.s.sdDLSAP.routeDl = RTESPEC; /* route for data link layer */ + cfg.t.cfg.s.sdDLSAP.selectorDl = 0; /* upper interface selector */ + cfg.t.cfg.s.sdDLSAP.dstProcId = SFndProcId(); /* the procid of MAC/L1/MTP1 */ + cfg.t.cfg.s.sdDLSAP.entMac = ENTL1; /* entity for MAC */ + cfg.t.cfg.s.sdDLSAP.instMac = S_INST; /* instance for MAC */ + cfg.t.cfg.s.sdDLSAP.priorMac = PRIOR0; /* priority for MAC layer */ + cfg.t.cfg.s.sdDLSAP.routeMac = RTESPEC; /* route for MAC layer */ + cfg.t.cfg.s.sdDLSAP.selectorMac = 0; /* lower interface selector */ + cfg.t.cfg.s.sdDLSAP.memMac.region = S_REG; /* memory region and pool id for MAC */ + cfg.t.cfg.s.sdDLSAP.memMac.pool = S_POOL; + cfg.t.cfg.s.sdDLSAP.maxOutsFrms = MAX_SD_OUTSTANDING; /* maximum outstanding frames */ + cfg.t.cfg.s.sdDLSAP.errType = SD_ERR_NRM; + cfg.t.cfg.s.sdDLSAP.t1.enb = TRUE; /* timer 1 - Alignment Ready Timer */ + cfg.t.cfg.s.sdDLSAP.t1.val = k->mtp2.t1; + cfg.t.cfg.s.sdDLSAP.t2.enb = TRUE; /* timer 2 - Not Aligned Timer */ + cfg.t.cfg.s.sdDLSAP.t2.val = k->mtp2.t2; + cfg.t.cfg.s.sdDLSAP.t3.enb = TRUE; /* timer 3 - Aligned Timer */ + cfg.t.cfg.s.sdDLSAP.t3.val = k->mtp2.t3; + cfg.t.cfg.s.sdDLSAP.t5.enb = TRUE; /* timer 5 - Sending SIB timer */ + cfg.t.cfg.s.sdDLSAP.t5.val = k->mtp2.t5; + cfg.t.cfg.s.sdDLSAP.t6.enb = TRUE; /* timer 6 - Remote Congestion Timer */ + cfg.t.cfg.s.sdDLSAP.t6.val = k->mtp2.t6; + cfg.t.cfg.s.sdDLSAP.t7.enb = TRUE; /* timer 7 - Excessive delay of acknowledgement timer */ + cfg.t.cfg.s.sdDLSAP.t7.val = k->mtp2.t7; + cfg.t.cfg.s.sdDLSAP.provEmrgcy = k->mtp2.t4e; /* emergency proving period */ + cfg.t.cfg.s.sdDLSAP.provNormal = k->mtp2.t4n; /* normal proving period */ + cfg.t.cfg.s.sdDLSAP.lssuLen = k->mtp2.lssuLength; /* one or two byte LSSU length */ + cfg.t.cfg.s.sdDLSAP.maxFrmLen = MAX_SD_FRAME_LEN; /* max frame length for MSU */ + cfg.t.cfg.s.sdDLSAP.congDisc = FALSE; /* congestion discard TRUE or FALSE */ + cfg.t.cfg.s.sdDLSAP.sdT = MAX_SD_SUERM; /* SUERM error rate threshold */ + cfg.t.cfg.s.sdDLSAP.sdTie = MAX_SD_AERM_EMERGENCY; /* AERM emergency error rate threshold */ + cfg.t.cfg.s.sdDLSAP.sdTin = MAX_SD_AERM_NORMAL; /* AERM normal error rate threshold */ + cfg.t.cfg.s.sdDLSAP.sdN1 = MAX_SD_MSU_RETRANS; /* maximum number of MSUs for retransmission */ + cfg.t.cfg.s.sdDLSAP.sdN2 = MAX_SD_OCTETS_RETRANS; /* maximum number of MSU octets for retrans */ + cfg.t.cfg.s.sdDLSAP.sdCp = MAX_SD_ALIGN_ATTEMPTS; /* maximum number of alignment attempts */ + cfg.t.cfg.s.sdDLSAP.spIdSE = k->mtp2.mtp1Id; /* service provider id */ + cfg.t.cfg.s.sdDLSAP.sdtFlcStartTr = 256; /* SDT interface flow control start thresh */ + cfg.t.cfg.s.sdDLSAP.sdtFlcEndTr = 512; /* SDT interface flow control end thresh */ + +#ifdef SD_HSL + cfg.t.cfg.s.sdDLSAP.sapType =; /* Indcates whether link is HSL or LSL */ + cfg.t.cfg.s.sdDLSAP.sapFormat =; /* The extened sequence no to be used or not */ + cfg.t.cfg.s.sdDLSAP.t8.enb =; /* timer 8 configuration structure */ + cfg.t.cfg.s.sdDLSAP.sdTe =; /* EIM threshold */ + cfg.t.cfg.s.sdDLSAP.sdUe =; /* increment constant */ + cfg.t.cfg.s.sdDLSAP.sdDe =; /* decrement constant */ +#endif /* HIGH_SPEED_SIGNALING_SUPPORT */ + +#if (SS7_TTC || SS7_NTT) + cfg.t.cfg.s.sdDLSAP.numRtb =; /* outstanding number of messages in RTB */ + cfg.t.cfg.s.sdDLSAP.tf =; /* FISU transmission interval */ + cfg.t.cfg.s.sdDLSAP.tfv =; /* FISU transmission interval during verification */ + cfg.t.cfg.s.sdDLSAP.to =; /* SIO transmission interval */ + cfg.t.cfg.s.sdDLSAP.ta =; /* SIE transmission interval */ + cfg.t.cfg.s.sdDLSAP.ts =; /* SIOS transmission interval */ + cfg.t.cfg.s.sdDLSAP.tso =; /* SIOS transmission duration when out of service */ + cfg.t.cfg.s.sdDLSAP.te =; /* SU normalization time */ +#endif /* (SS7_TTC || SS7_NTT) */ + +#if (SS7_NTT) /* NTTT - Q.703 */ + cfg.t.cfg.s.sdDLSAP.repMsuNack =; /* Nack on receipt of repeated MSU */ + cfg.t.cfg.s.sdDLSAP.invFibIgnore =; /* invalid FIB ignore or bring the link down */ + cfg.t.cfg.s.sdDLSAP.invBsnIgnore =; /* invalid BSN ignore or bring the link down */ + cfg.t.cfg.s.sdDLSAP.congAbatOnNack =; /* congestion abatement on nack or only on acks */ +#endif /* (SS7_NTT) */ + +#ifdef TDS_ROLL_UPGRADE_SUPPORT + cfg.t.cfg.s.sdDLSAP.hlremIntfValid = FALSE; /* Upper Sap Version number valid ? */ + cfg.t.cfg.s.sdDLSAP.remIntfVer = SDTIFVER; /* remote version info */ +#endif /*RUG*/ + + return(sng_cfg_mtp2(&pst, &cfg)); + return 0; +} + +/******************************************************************************/ +int ftmod_ss7_mtp3_dlsap_config(int id) +{ + Pst pst; + SnMngmt cfg; + sng_mtp_link_t *k = &g_ftdm_sngss7_data.cfg.mtpLink[id]; + + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SnMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STDLSAP; + + cfg.hdr.elmId.elmntInst1 = k->id; + + cfg.t.cfg.s.snDLSAP.lnkSetId = k->mtp3.linkSetId; /* link set ID */ + cfg.t.cfg.s.snDLSAP.opc = k->mtp3.spc; /* Originating Postatic int Code */ + cfg.t.cfg.s.snDLSAP.adjDpc = k->mtp3.apc; /* Adlacent Destination Postatic int Code */ + cfg.t.cfg.s.snDLSAP.lnkPrior = 0; /* link priority within the link set */ + cfg.t.cfg.s.snDLSAP.msgSize = MAX_SN_MSG_SIZE; /* message length */ + cfg.t.cfg.s.snDLSAP.msgPrior = 0; /* management message priority */ + cfg.t.cfg.s.snDLSAP.lnkType = k->mtp3.linkType; /* link type ANSI, ITU, BICI or CHINA */ + cfg.t.cfg.s.snDLSAP.upSwtch = k->mtp3.switchType; /* user part switch type */ +# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA) + cfg.t.cfg.s.snDLSAP.l2Type = LSN_MTP2_56KBPS; /* layer 2 type - 56kbps MTP2 link, 1.536Mbps MTP2 link or QSAAL link */ + cfg.t.cfg.s.snDLSAP.isCLink = FALSE; /* identifies if the link is a C type link.Required to check if sls has to be rotated.*/ +# endif + cfg.t.cfg.s.snDLSAP.maxSLTtry = MAX_SLTM_RETRIES; /* maximun times to retry SLTM */ + cfg.t.cfg.s.snDLSAP.p0QLen = 32; /* size of the priority 0 Q */ + cfg.t.cfg.s.snDLSAP.p1QLen = 32; /* size of the priority 1 Q */ + cfg.t.cfg.s.snDLSAP.p2QLen = 32; /* size of the priority 2 Q */ + cfg.t.cfg.s.snDLSAP.p3QLen = 32; /* size of the priority 3 Q */ + cfg.t.cfg.s.snDLSAP.discPrior = 0; /* discard priority */ +#ifndef SDT2 + cfg.t.cfg.s.snDLSAP.maxCredit = MAX_SN_CREDIT; /* max credit */ +#endif /* SDT2 */ + cfg.t.cfg.s.snDLSAP.lnkId = 0; /* signalling link allocation procedure identity */ + cfg.t.cfg.s.snDLSAP.lnkTstSLC = k->mtp3.slc; /* link selection code for link test */ + cfg.t.cfg.s.snDLSAP.tstLen = 6; /* link test pattern length */ + cfg.t.cfg.s.snDLSAP.tst[0] = 'K'; /* link test pattern */ + cfg.t.cfg.s.snDLSAP.tst[1] = 'O'; /* link test pattern */ + cfg.t.cfg.s.snDLSAP.tst[2] = 'N'; /* link test pattern */ + cfg.t.cfg.s.snDLSAP.tst[3] = 'R'; /* link test pattern */ + cfg.t.cfg.s.snDLSAP.tst[4] = 'A'; /* link test pattern */ + cfg.t.cfg.s.snDLSAP.tst[5] = 'D'; /* link test pattern */ + cfg.t.cfg.s.snDLSAP.ssf = k->mtp3.ssf; /* sub service field */ + cfg.t.cfg.s.snDLSAP.dstProcId = SFndProcId(); /* destination processor id */ + cfg.t.cfg.s.snDLSAP.dstEnt = ENTSD; /* entity */ + cfg.t.cfg.s.snDLSAP.dstInst = S_INST; /* instance */ + cfg.t.cfg.s.snDLSAP.prior = PRIOR0; /* priority */ + cfg.t.cfg.s.snDLSAP.route = RTESPEC; /* route */ + cfg.t.cfg.s.snDLSAP.selector = 0; /* lower layer selector */ + cfg.t.cfg.s.snDLSAP.mem.region = S_REG; /* memory region id */ + cfg.t.cfg.s.snDLSAP.mem.pool = S_POOL; /* memory pool id */ +#if( SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA ) + cfg.t.cfg.s.snDLSAP.dpcLen = DPC24; /* dpc length 24 bits */ +#else + cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */ +#endif + cfg.t.cfg.s.snDLSAP.spId = k->mtp3.mtp2Id ;/* service provider id */ +#if (SS7_ITU88 || SS7_CHINA || SS7_TTC || SS7_NTT || SS7_BICI ) + cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */ +#else + cfg.t.cfg.s.snDLSAP.flushContFlag = TRUE; /* flush continue handling */ +#endif + cfg.t.cfg.s.snDLSAP.tmr.t1.enb = TRUE; /* t1 - delay to avoid missequencing on changeover */ + cfg.t.cfg.s.snDLSAP.tmr.t1.val = k->mtp3.t1; + cfg.t.cfg.s.snDLSAP.tmr.t2.enb = TRUE; /* t2 - waiting for changeover ack */ + cfg.t.cfg.s.snDLSAP.tmr.t2.val = k->mtp3.t2; + cfg.t.cfg.s.snDLSAP.tmr.t3.enb = TRUE; /* t3 - delay to avoid missequencing on changeback */ + cfg.t.cfg.s.snDLSAP.tmr.t3.val = k->mtp3.t3; + cfg.t.cfg.s.snDLSAP.tmr.t4.enb = TRUE; /* t4 - waiting for first changeback ack */ + cfg.t.cfg.s.snDLSAP.tmr.t4.val = k->mtp3.t4; + cfg.t.cfg.s.snDLSAP.tmr.t5.enb = TRUE; /* t5 - waiting for second changeback ack */ + cfg.t.cfg.s.snDLSAP.tmr.t5.val = k->mtp3.t5; + cfg.t.cfg.s.snDLSAP.tmr.t7.enb = TRUE; /* t7 - waiting for link connection ack */ + cfg.t.cfg.s.snDLSAP.tmr.t7.val = k->mtp3.t7; + cfg.t.cfg.s.snDLSAP.tmr.t12.enb = TRUE; /* t12 - waiting for uninhibit ack */ + cfg.t.cfg.s.snDLSAP.tmr.t12.val = k->mtp3.t12; + cfg.t.cfg.s.snDLSAP.tmr.t13.enb = TRUE; /* t13 - waiting for forced uninhibit */ + cfg.t.cfg.s.snDLSAP.tmr.t13.val = k->mtp3.t13; + cfg.t.cfg.s.snDLSAP.tmr.t14.enb = TRUE; /* t14 - waiting for inhibition ack */ + cfg.t.cfg.s.snDLSAP.tmr.t14.val = k->mtp3.t14; + cfg.t.cfg.s.snDLSAP.tmr.t17.enb = TRUE; /* t17 - delay to avoid oscillation of initial alignment failure */ + cfg.t.cfg.s.snDLSAP.tmr.t17.val = k->mtp3.t17; + cfg.t.cfg.s.snDLSAP.tmr.t22.enb = TRUE; /* t22 - local inhibit test timer */ + cfg.t.cfg.s.snDLSAP.tmr.t22.val = k->mtp3.t22; + cfg.t.cfg.s.snDLSAP.tmr.t23.enb = TRUE; /* t23 - remote inhibit test timer */ + cfg.t.cfg.s.snDLSAP.tmr.t23.val = k->mtp3.t23; + cfg.t.cfg.s.snDLSAP.tmr.t24.enb = TRUE; /* t24 - stabilizing timer */ + cfg.t.cfg.s.snDLSAP.tmr.t24.val = k->mtp3.t24; + cfg.t.cfg.s.snDLSAP.tmr.t31.enb = TRUE; /* t31 - BSN requested timer */ + cfg.t.cfg.s.snDLSAP.tmr.t31.val = k->mtp3.t31; + cfg.t.cfg.s.snDLSAP.tmr.t32.enb = TRUE; /* t32 - SLT timer */ + cfg.t.cfg.s.snDLSAP.tmr.t32.val = k->mtp3.t32; + cfg.t.cfg.s.snDLSAP.tmr.t33.enb = TRUE; /* t33 - connecting timer */ + cfg.t.cfg.s.snDLSAP.tmr.t33.val = k->mtp3.t33; + cfg.t.cfg.s.snDLSAP.tmr.t34.enb = TRUE; /* t34 - periodic signalling link test timer */ + cfg.t.cfg.s.snDLSAP.tmr.t34.val = k->mtp3.t34; +#if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT)) + cfg.t.cfg.s.snDLSAP.tmr.t35.enb = TRUE; /* t35 - false link congestion timer, same as t31 of ANSI'96*/ + cfg.t.cfg.s.snDLSAP.tmr.t35.val = k->mtp3.t35; + cfg.t.cfg.s.snDLSAP.tmr.t36.enb = TRUE; /* t36 - false link congestion timer, same as t33 of ANSI'96*/ + cfg.t.cfg.s.snDLSAP.tmr.t36.val = k->mtp3.t36; + cfg.t.cfg.s.snDLSAP.tmr.t37.enb = TRUE; /* t37 - false link congestion timer, same as t34 of ANSI'96*/ + cfg.t.cfg.s.snDLSAP.tmr.t37.val = k->mtp3.t37; + cfg.t.cfg.s.snDLSAP.tmr.tCraft.enb = TRUE; /* link referral craft timer - T19 in ANSI */ + cfg.t.cfg.s.snDLSAP.tmr.tCraft.val = k->mtp3.tcraft; +#endif +#ifdef SDT2 + cfg.t.cfg.s.snDLSAP.tmr.tFlc.enb = TRUE; /* flow control timer */ + cfg.t.cfg.s.snDLSAP.tmr.tFlc.val = 300; + cfg.t.cfg.s.snDLSAP.tmr.tBnd.enb = TRUE; /* bind request timer */ + cfg.t.cfg.s.snDLSAP.tmr.tBnd.val = 20; +#endif /* SDT2 */ +#ifdef TDS_ROLL_UPGRADE_SUPPORT + cfg.t.cfg.s.snDLSAP.remIntfValid = FALSE; /* remote interface version is valid */ + cfg.t.cfg.s.snDLSAP.remIntfVer = SNTIFVER; /* remote interface version */ +#endif + + return(sng_cfg_mtp3(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_mtp3_nsap_config(int id) +{ + Pst pst; + SnMngmt cfg; + sng_nsap_t *k = &g_ftdm_sngss7_data.cfg.nsap[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SnMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STNSAP; + + cfg.hdr.elmId.elmntInst1 = k->spId; + + cfg.t.cfg.s.snNSAP.ssf = k->ssf; /* sub service field */ + cfg.t.cfg.s.snNSAP.lnkType = k->linkType; /* link type -ANSI, ITU, CHINA or BICI */ + cfg.t.cfg.s.snNSAP.upSwtch = k->switchType; /* user part switch type */ + cfg.t.cfg.s.snNSAP.selector = 0; /* upper layer selector */ + cfg.t.cfg.s.snNSAP.mem.region = S_REG; /* memory region id */ + cfg.t.cfg.s.snNSAP.mem.pool = S_POOL; /* memory pool id */ + cfg.t.cfg.s.snNSAP.prior = PRIOR0; /* priority */ + cfg.t.cfg.s.snNSAP.route = RTESPEC; /* route */ +#if( SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA ) + cfg.t.cfg.s.snNSAP.dpcLen = DPC24; /* dpc length 14 or 24 bits */ +#else + cfg.t.cfg.s.snNSAP.dpcLen = DPC14; /* dpc length 14 or 24 bits */ +#endif +#if (defined(SN_SG) || defined(TDS_ROLL_UPGRADE_SUPPORT)) + cfg.t.cfg.s.snNSAP.usrParts = ; /* user parts configured on self postatic int code on IP side */ +#endif +#ifdef TDS_ROLL_UPGRADE_SUPPORT + cfg.t.cfg.s.snNSAP.remIntfValid = FALSE; /* remote interface version is valid */ + cfg.t.cfg.s.snNSAP.remIntfVer = SNTIFVER; /* remote interface version */ +#endif + + return(sng_cfg_mtp3(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_mtp3_linkset_config(int id) +{ + Pst pst; + SnMngmt cfg; + U16 c; + sng_link_set_t *k = &g_ftdm_sngss7_data.cfg.mtpLinkSet[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SnMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STLNKSET; /* link set */ + + cfg.hdr.elmId.elmntInst1 = k->id; + + cfg.t.cfg.s.snLnkSet.lnkSetId = k->id; /* link set ID */ + cfg.t.cfg.s.snLnkSet.lnkSetType = k->linkType; /* link type */ + cfg.t.cfg.s.snLnkSet.adjDpc = k->apc; /* adjacent DPC */ + cfg.t.cfg.s.snLnkSet.nmbActLnkReqd = k->minActive; /* minimum number of active links */ + cfg.t.cfg.s.snLnkSet.nmbCmbLnkSet = 1; /* number of combined link sets */ + for (c = 0; c < LSN_MAXCMBLNK; c++) { + cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].cmbLnkSetId = c+1; + cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].lnkSetPrior = 0; + } + + return(sng_cfg_mtp3(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_mtp3_route_config(int id) +{ + Pst pst; + SnMngmt cfg; + sng_route_t *k = &g_ftdm_sngss7_data.cfg.mtpRoute[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SnMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSN; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STROUT; + + cfg.hdr.elmId.elmntInst1 = k->id; + + cfg.t.cfg.s.snRout.dpc = k->dpc; /* destination postatic int code */ + cfg.t.cfg.s.snRout.spType = LSN_TYPE_SP; /* signalling postatic int type */ + cfg.t.cfg.s.snRout.swtchType = k->linkType; /* switch type */ + cfg.t.cfg.s.snRout.upSwtch = k->switchType; /* user part switch type */ + cfg.t.cfg.s.snRout.cmbLnkSetId = k->cmbLinkSetId; /* combined link set ID */ + if (k->id == 0) { + cfg.t.cfg.s.snRout.dir = LSN_RTE_UP; /* direction */ + } else { + cfg.t.cfg.s.snRout.dir = LSN_RTE_DN; /* direction */ + } + cfg.t.cfg.s.snRout.rteToAdjSp = 0; /* flag indicating this route to adjacent SP */ + cfg.t.cfg.s.snRout.ssf = k->ssf; /* sub service field */ + cfg.t.cfg.s.snRout.brdcastFlg = TRUE; /* flag indicating to have TFP broadcast */ + if (cfg.t.cfg.s.snRout.swtchType == LSN_SW_ITU) { + cfg.t.cfg.s.snRout.rstReq = LSN_ITU92_RST; /* Restart type supported by the node */ + } else if ((cfg.t.cfg.s.snRout.swtchType == LSN_SW_ANS) || + (cfg.t.cfg.s.snRout.swtchType == LSN_SW_ANS96)) { + cfg.t.cfg.s.snRout.rstReq = LSN_ANS_RST; /* Restart type supported by the node */ + } else { + cfg.t.cfg.s.snRout.rstReq = LSN_NO_RST; /* Restart type supported by the node */ + } + if ((cfg.t.cfg.s.snRout.swtchType == LSN_SW_ITU) || + (cfg.t.cfg.s.snRout.swtchType == LSN_SW_CHINA) || + (cfg.t.cfg.s.snRout.swtchType == LSN_SW_BICI)) { + cfg.t.cfg.s.snRout.slsRange = LSN_ITU_SLS_RANGE; /* max value of SLS for this DPC */ + } else { + cfg.t.cfg.s.snRout.slsRange = LSN_ANSI_5BIT_SLS_RANGE; /* max value of SLS for this DPC */ + } + cfg.t.cfg.s.snRout.lsetSel = 0x1; /* linkset selection bit in SLS for STP */ + cfg.t.cfg.s.snRout.multiMsgPrior = FALSE; /* TRUE if multiple cong priorities of messages */ + cfg.t.cfg.s.snRout.rctReq = TRUE; /* route set congestion test required or not */ + cfg.t.cfg.s.snRout.slsLnk = FALSE; +#ifdef LSNV2 +# if (SS7_NTT || defined(TDS_ROLL_UPGRADE_SUPPORT)) + cfg.t.cfg.s.snRout.destSpec =; /* destination specfication A or B*/ +# endif +#endif +#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART)) + cfg.t.cfg.s.snRout.tfrReq =; /* TFR procedure required or not */ +#endif + cfg.t.cfg.s.snRout.tmr.t6.enb = TRUE; + cfg.t.cfg.s.snRout.tmr.t6.val = k->t6; + cfg.t.cfg.s.snRout.tmr.t8.enb = TRUE; /* t8 - transfer prohibited inhibition timer */ + cfg.t.cfg.s.snRout.tmr.t8.val = k->t8; + cfg.t.cfg.s.snRout.tmr.t10.enb = TRUE; /* t10 - waiting to repeat route set test */ + cfg.t.cfg.s.snRout.tmr.t10.val = k->t10; + cfg.t.cfg.s.snRout.tmr.t11.enb = TRUE; /* t11 - transfer restrict timer */ + cfg.t.cfg.s.snRout.tmr.t11.val = k->t11; + cfg.t.cfg.s.snRout.tmr.t19.enb = TRUE; /* t19 - TRA sent timer */ + cfg.t.cfg.s.snRout.tmr.t19.val = k->t19; + cfg.t.cfg.s.snRout.tmr.t21.enb = TRUE; /* t21 - waiting to restart traffic routed through adjacent SP */ + cfg.t.cfg.s.snRout.tmr.t21.val = k->t21; + +#if (defined(LSNV3) || defined(SN_MULTIPLE_NETWORK_RESTART)) + cfg.t.cfg.s.snRout.tmr.t15.enb = TRUE; /* t15 - waiting to start route set congestion test */ + cfg.t.cfg.s.snRout.tmr.t15.val = k->t15; + cfg.t.cfg.s.snRout.tmr.t16.enb = TRUE; /* t16 - waiting for route set congestion status update */ + cfg.t.cfg.s.snRout.tmr.t16.val = k->t16; + cfg.t.cfg.s.snRout.tmr.t18.enb = TRUE; /* t18 - transfer prohibited inhibition timer */ + cfg.t.cfg.s.snRout.tmr.t18.val = k->t18; +# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT)) + cfg.t.cfg.s.snRout.tmr.t25.enb = TRUE; /* t25 - waiting to traffic resatrt allowed message for ANSI */ + cfg.t.cfg.s.snRout.tmr.t25.val = k->t25; + cfg.t.cfg.s.snRout.tmr.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */ + cfg.t.cfg.s.snRout.tmr.t26.val = k->t26; +# endif +#endif +#if (SS7_TTC || SS7_NTT || defined(TDS_ROLL_UPGRADE_SUPPORT)) + cfg.t.cfg.s.snRout.tmr.tc.enb = TRUE; /* tc - Waiting for congestion abatement */ + cfg.t.cfg.s.snRout.tmr.tc.val = k->tc; +#endif +#if (defined(SN_SG) || defined(TDS_ROLL_UPGRADE_SUPPORT)) + cfg.t.cfg.s.snRout.tmr.tQry.enb = TRUE; /* Periodic query timer over the NIF */ + cfg.t.cfg.s.snRout.tmr.tQry.val = k->tqry; +#endif + + return(sng_cfg_mtp3(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_isup_nsap_config(int id) +{ + SiMngmt cfg; + Pst pst; + sng_nsap_t *k = &g_ftdm_sngss7_data.cfg.nsap[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSI; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SiMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSI; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STNSAP; + + cfg.hdr.elmId.elmntInst1 = k->id; + +#if (SI_LMINT3 || SMSI_LMINT3) + cfg.t.cfg.s.siNSap.nsapId = k->id; /* Id of the NSAP being configured */ +#endif + cfg.t.cfg.s.siNSap.nwId = k->nwId; /* Network Id */ + cfg.t.cfg.s.siNSap.spId = k->spId; /* service providor id */ + cfg.t.cfg.s.siNSap.ssf = k->ssf; /* sub service field */ + cfg.t.cfg.s.siNSap.dstEnt = ENTSN; /* entity */ + cfg.t.cfg.s.siNSap.dstInst = S_INST; /* instance */ + cfg.t.cfg.s.siNSap.prior = PRIOR0; /* priority */ + cfg.t.cfg.s.siNSap.route = RTESPEC; /* route */ + cfg.t.cfg.s.siNSap.dstProcId = SFndProcId(); /* destination processor id */ + cfg.t.cfg.s.siNSap.sapType = SAP_MTP; /* sap type */ + cfg.t.cfg.s.siNSap.selector = 0; /* selector */ + cfg.t.cfg.s.siNSap.tINT.enb = TRUE; /* interface (Bind Confirm) timer */ + cfg.t.cfg.s.siNSap.tINT.val = 50; + cfg.t.cfg.s.siNSap.mem.region = S_REG; /* memory region & pool id */ + cfg.t.cfg.s.siNSap.mem.pool = S_POOL; + +#ifdef TDS_ROLL_UPGRADE_SUPPORT + cfg.t.cfg.s.siNSap.remIntfValid = FALSE; /* remote interface version is valid */ + cfg.t.cfg.s.siNSap.remIntfVer; /* remote interface version */ +#endif + + return(sng_cfg_isup(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_isup_intf_config(int id) +{ + SiMngmt cfg; + Pst pst; + sng_isup_inf_t *k = &g_ftdm_sngss7_data.cfg.isupIntf[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSI; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SiMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSI; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = SI_STINTF; + + cfg.hdr.elmId.elmntInst1 = k->id; + + cfg.t.cfg.s.siIntfCb.intfId = k->id; /* Interface id */ + cfg.t.cfg.s.siIntfCb.nwId = k->nwId; /* Network Id */ + cfg.t.cfg.s.siIntfCb.sapId = k->isap; /* Id of the Upper ISUP SAP */ + cfg.t.cfg.s.siIntfCb.opc = k->spc; /* physical originating postatic int code */ + cfg.t.cfg.s.siIntfCb.phyDpc = k->dpc; /* physical destination postatic int code */ + cfg.t.cfg.s.siIntfCb.swtch = k->switchType; /* Protocol Switch */ + cfg.t.cfg.s.siIntfCb.ssf = k->ssf; /* subsystem service information */ + cfg.t.cfg.s.siIntfCb.pauseActn = SI_PAUSE_CLRTRAN; /* call clearing behavior upon rx. PAUSE */ + cfg.t.cfg.s.siIntfCb.dpcCbTmr.t4.enb = TRUE; /* t4 timer - user part test sent */ + cfg.t.cfg.s.siIntfCb.dpcCbTmr.t4.val = k->t4; + cfg.t.cfg.s.siIntfCb.dpcCbTmr.tPAUSE.enb = TRUE; /* waiting for PAUSE to be effective */ + cfg.t.cfg.s.siIntfCb.dpcCbTmr.tPAUSE.val = k->tpause; + cfg.t.cfg.s.siIntfCb.dpcCbTmr.tSTAENQ.enb = TRUE; /* status enquiry timer */ + cfg.t.cfg.s.siIntfCb.dpcCbTmr.tSTAENQ.val = k->tstaenq; +#if SS7_ANS95 + cfg.t.cfg.s.siIntfCb.availTest = FALSE; /* circuit validation test */ +#endif +#if (SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_ITU2000 || SS7_KZ) + cfg.t.cfg.s.siIntfCb.checkTable = LSI_CHKTBLE_MRATE; /* Validation flag for Table 3 p1/p2 Q.763 */ +#endif +#if (SS7_ANS95 || SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_ITU2000 || SS7_KZ) + switch (k->switchType) { + case LSI_SW_TST: + case LSI_SW_ITU: + case LSI_SW_ITU97: + case LSI_SW_ITU2000: + case LSI_SW_ETSI: + case LSI_SW_ETSIV3: + case LSI_SW_RUSSIA: + case LSI_SW_RUSS2000: + case LSI_SW_INDIA: + case LSI_SW_CHINA: + cfg.t.cfg.s.siIntfCb.trunkType = TRUE; /* truck type E1(TRUE)/T1(FALSE) at intf */ + break; + case LSI_SW_ANS88: + case LSI_SW_ANS92: + case LSI_SW_ANS95: + case LSI_SW_BELL: + cfg.t.cfg.s.siIntfCb.trunkType = FALSE; /* truck type E1(TRUE)/T1(FALSE) at intf */ + break; + } + +#endif +#if (LSIV4 || LSIV5) + cfg.t.cfg.s.siIntfCb.lnkSelOpt = LSI_LINSEK_CIC; /* link select option */ +# if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + cfg.t.cfg.s.siIntfCb.lnkSelBits = LSI_LNKSEL_8BITS; /* number of bits for link selection */ +# endif +#endif + + return(sng_cfg_isup(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_isup_ckt_config(int id) +{ + SiMngmt cfg; + Pst pst; + U32 tmp_flag; + sng_isup_ckt_t *k = &g_ftdm_sngss7_data.cfg.isupCkt[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSI; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SiMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSI; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STICIR; + + cfg.hdr.elmId.elmntInst1 = k->id; + + cfg.t.cfg.s.siCir.cirId = k->id; /* circuit id code */ + cfg.t.cfg.s.siCir.cic = k->cic; /* cic */ + cfg.t.cfg.s.siCir.intfId = k->infId; /* interface id */ + cfg.t.cfg.s.siCir.typeCntrl = k->typeCntrl; /* type of control */ + cfg.t.cfg.s.siCir.contReq = FALSE; /* continuity check required */ +#if (SI_218_COMP || SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + cfg.t.cfg.s.siCir.firstCic =; /* First cic in the circuit group */ + cfg.t.cfg.s.siCir.numCir =; /* Number of circuits in the circuit group */ + cfg.t.cfg.s.siCir.nonSS7Con = TRUE; /* connecting to non SS7 network */ + cfg.t.cfg.s.siCir.outTrkGrpN =; /* outgoing trunk group number (For EXM) */ + cfg.t.cfg.s.siCir.cvrTrkClli =; /* Trunk Group number (For CVR validation) */ + cfg.t.cfg.s.siCir.clli =; /* common language location identifier */ +#endif + cfg.t.cfg.s.siCir.cirTmr.t3.enb = TRUE; /* t3 timer - overload received */ + cfg.t.cfg.s.siCir.cirTmr.t3.val = k->t3; + cfg.t.cfg.s.siCir.cirTmr.t12.enb = TRUE; /* t12 timer - blocking sent */ + cfg.t.cfg.s.siCir.cirTmr.t12.val = k->t12; + cfg.t.cfg.s.siCir.cirTmr.t13.enb = TRUE; /* t13 timer - initial blocking sent */ + cfg.t.cfg.s.siCir.cirTmr.t13.val = k->t13; + cfg.t.cfg.s.siCir.cirTmr.t14.enb = TRUE; /* t14 timer - unblocking sent */ + cfg.t.cfg.s.siCir.cirTmr.t14.val = k->t14; + cfg.t.cfg.s.siCir.cirTmr.t15.enb = TRUE; /* t15 timer - initial unblocking sent */ + cfg.t.cfg.s.siCir.cirTmr.t15.val = k->t15; + cfg.t.cfg.s.siCir.cirTmr.t16.enb = TRUE; /* t16 timer - reset sent */ + cfg.t.cfg.s.siCir.cirTmr.t16.val = k->t16; + cfg.t.cfg.s.siCir.cirTmr.t17.enb = TRUE; /* t17 timer - initial reset sent */ + cfg.t.cfg.s.siCir.cirTmr.t17.val = k->t17; +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + cfg.t.cfg.s.siCir.cirTmr.tVal.enb = TRUE; /* circuit validation timer */ + cfg.t.cfg.s.siCir.cirTmr.tVal.val = k->tval; +#endif +#if (SS7_ANS95 || SS7_ITU97 || SS7_ETSIV3 || SS7_UK) + tmp_flag = 0x0; + /* bit 0 - 4 is the timeslot on the span for this circuit */ + tmp_flag = ( 1 ); + + /* bit 5 -> can this timeslot be used for contigous M-rate call */ + tmp_flag |= !(0x20); + + /* bit 6 -> does this timeslot support contigous M-rate call */ + tmp_flag |= !(0x40); + + cfg.t.cfg.s.siCir.slotId = tmp_flag ; /* physical slot id bit wise flag */ + cfg.t.cfg.s.siCir.ctrlMult = 0; /* Controller for multirate calls */ +#endif + + tmp_flag = 0x0; + /* bit 0 -> ANSI international support or national support */ + tmp_flag = k->ssf; + + /* bit 1 -> confusion message on */ + tmp_flag |= LSI_CIRFLG_CFN_ON; + + /*bit 2-3 -> circuit group carrier information */ + tmp_flag |= LSI_CFCI_ANALDIG; + + /*bit 4-5 -> alarm carrier */ + tmp_flag |= LSI_CFAC_UNKNOWN; + + /*bit 6-7 -> continuity check requirement*/ + tmp_flag |= LSI_CFCO_NONE; + + cfg.t.cfg.s.siCir.cirFlg = tmp_flag; /* Flag indicating diff cfg options for ckt */ + + return(sng_cfg_isup(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_isup_isap_config(int id) +{ + SiMngmt cfg; + Pst pst; + sng_isap_t *k = &g_ftdm_sngss7_data.cfg.isap[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSI; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(SiMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTSI; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STISAP; + + cfg.hdr.elmId.elmntInst1 = k->id; + +#if (SI_LMINT3 || SMSI_LMINT3) + cfg.t.cfg.s.siSap.sapId = k->id; /* Id of the SAP being configured */ +#endif + cfg.t.cfg.s.siSap.swtch = k->switchType; /* Protocol Switch */ + cfg.t.cfg.s.siSap.ssf = k->ssf; /* Sub service field */ + cfg.t.cfg.s.siSap.sidIns = FALSE; /* SID insertion Flag */ + cfg.t.cfg.s.siSap.sidVer = FALSE; /* SID verification Flag */ + if ( cfg.t.cfg.s.siSap.sidIns == TRUE ) { /* SID */ + #if 0 + cfg.t.cfg.s.siSap.sid =; + cfg.t.cfg.s.siSap.natAddrInd =; /* SID Nature of Addres Indicator */ + cfg.t.cfg.s.siSap.sidNPlan =; /* SID Numbering Plan */ + cfg.t.cfg.s.siSap.sidPresInd =; /* default presentation indicator */ + cfg.t.cfg.s.siSap.incSidPresRes =; /* Presentation Restriction of incoming SID */ + cfg.t.cfg.s.siSap.sidPresRes =; /* Presentation Restriction */ + #endif + } else { + cfg.t.cfg.s.siSap.sid.length = 0; + /*cfg.t.cfg.s.siSap.sid.strg[0] =*/ + cfg.t.cfg.s.siSap.natAddrInd = ADDR_NOTPRSNT; /* SID Nature of Addres Indicator */ + cfg.t.cfg.s.siSap.sidNPlan = NP_ISDN; /* SID Numbering Plan */ + cfg.t.cfg.s.siSap.sidPresInd = FALSE; /* default presentation indicator */ + cfg.t.cfg.s.siSap.incSidPresRes = TRUE; /* Presentation Restriction of incoming SID */ + cfg.t.cfg.s.siSap.sidPresRes = 0; /* Presentation Restriction */ + } + cfg.t.cfg.s.siSap.reqOpt = FALSE; /* Request option */ + cfg.t.cfg.s.siSap.allCallMod = TRUE; /* call modification allowed flag */ + cfg.t.cfg.s.siSap.maxLenU2U = MAX_SI_USER_2_USER_LEN; /* Max length of user to user messages */ + cfg.t.cfg.s.siSap.passOnFlag = TRUE; /* flag for passing unknown par/msg */ + cfg.t.cfg.s.siSap.relLocation = ILOC_PRIVNETLU; /* release location indicator in cause val */ + cfg.t.cfg.s.siSap.prior = PRIOR0; /* priority */ + cfg.t.cfg.s.siSap.route = RTESPEC; /* route */ + cfg.t.cfg.s.siSap.selector = 0; /* selector */ + cfg.t.cfg.s.siSap.mem.region = S_REG; /* memory region & pool id */ + cfg.t.cfg.s.siSap.mem.pool = S_POOL; /* memory region & pool id */ + + cfg.t.cfg.s.siSap.tmr.t1.enb = TRUE; /* t1 timer - release sent */ + cfg.t.cfg.s.siSap.tmr.t1.val = k->t1; + cfg.t.cfg.s.siSap.tmr.t2.enb = TRUE; /* t2 timer - suspend received */ + cfg.t.cfg.s.siSap.tmr.t2.val = k->t2; + cfg.t.cfg.s.siSap.tmr.t5.enb = TRUE; /* t5 timer - initial release sent */ + cfg.t.cfg.s.siSap.tmr.t5.val = k->t5; + cfg.t.cfg.s.siSap.tmr.t6.enb = TRUE; /* t6 timer - suspend received */ + cfg.t.cfg.s.siSap.tmr.t6.val = k->t6; + cfg.t.cfg.s.siSap.tmr.t7.enb = TRUE; /* t7 timer - latest address sent */ + cfg.t.cfg.s.siSap.tmr.t7.val = k->t7; + cfg.t.cfg.s.siSap.tmr.t8.enb = TRUE; /* t8 timer - initial address received */ + cfg.t.cfg.s.siSap.tmr.t8.val = k->t8; + cfg.t.cfg.s.siSap.tmr.t9.enb = TRUE; /* t9 timer - latest address sent after ACM */ + cfg.t.cfg.s.siSap.tmr.t9.val = k->t9; + cfg.t.cfg.s.siSap.tmr.t27.enb = TRUE; /* t27 timer - wait. for continuity recheck */ + cfg.t.cfg.s.siSap.tmr.t27.val = k->t27; + cfg.t.cfg.s.siSap.tmr.t31.enb = TRUE; /* t31 timer - call reference frozen period */ + cfg.t.cfg.s.siSap.tmr.t31.val = k->t31; + cfg.t.cfg.s.siSap.tmr.t33.enb = TRUE; /* t33 timer - INR sent */ + cfg.t.cfg.s.siSap.tmr.t33.val = k->t33; + cfg.t.cfg.s.siSap.tmr.t34.enb = TRUE; /* t34 timer - wait. for continuity after recheck */ + cfg.t.cfg.s.siSap.tmr.t34.val = k->t34; + cfg.t.cfg.s.siSap.tmr.t36.enb = TRUE; /* waiting SGM */ + cfg.t.cfg.s.siSap.tmr.t36.val = k->t36; + cfg.t.cfg.s.siSap.tmr.tCCR.enb = TRUE; /* tCCR timer - continuity recheck timer */ + cfg.t.cfg.s.siSap.tmr.tCCR.val = k->tccr; + cfg.t.cfg.s.siSap.tmr.tRELRSP.enb = TRUE; /* waiting for release response */ + cfg.t.cfg.s.siSap.tmr.tRELRSP.val = k->trelrsp; + cfg.t.cfg.s.siSap.tmr.tFNLRELRSP.enb = TRUE; /* waiting for final release response */ + cfg.t.cfg.s.siSap.tmr.tFNLRELRSP.val = k->tfnlrelrsp; +#if (SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) + cfg.t.cfg.s.siSap.tmr.tEx.enb = TRUE; /* tEx timer - Exit to be sent */ + cfg.t.cfg.s.siSap.tmr.tEx.val = k->tex; + cfg.t.cfg.s.siSap.tmr.tCCRt.enb = TRUE; /* tCCR timer (o/g side) - continuity recheck timer */ + cfg.t.cfg.s.siSap.tmr.tCCRt.val = k->tccrt; +#endif +#if (SS7_ANS92 || SS7_ANS95 || SS7_BELL) + cfg.t.cfg.s.siSap.tmr.tCRM.enb = TRUE; /* circuit reservation message timer */ + cfg.t.cfg.s.siSap.tmr.tCRM.val = k->tcrm; + cfg.t.cfg.s.siSap.tmr.tCRA.enb = TRUE; /* circuit reservation ack. timer */ + cfg.t.cfg.s.siSap.tmr.tCRA.val = k->tcra; +#endif +#if (SS7_ETSI || SS7_ITU97 || SS7_ETSIV3 || SS7_UK || SS7_NZL || SS7_KZ) + cfg.t.cfg.s.siSap.tmr.tECT.enb = TRUE; /* Explicit Call Transfer - waiting for loop prvnt rsp */ + cfg.t.cfg.s.siSap.tmr.tECT.val = k->tect; +#endif + +#ifdef TDS_ROLL_UPGRADE_SUPPORT + cfg.t.cfg.s.siSap.remIntfValid = FALSE; /* remote interface version is valid */ + cfg.t.cfg.s.siSap.remIntfVer =; /* remote interface version */ +#endif + + return(sng_cfg_isup(&pst, &cfg)); +} + +/******************************************************************************/ +int ftmod_ss7_cc_isap_config(int id) +{ + CcMngmt cfg; + Pst pst; + sng_isap_t *k = &g_ftdm_sngss7_data.cfg.isap[id]; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTCC; + + /*clear the configuration structure*/ + memset(&cfg, 0x0, sizeof(CcMngmt)); + + /*fill in some general sections of the header*/ + smHdrInit(&cfg.hdr); + + /*fill in the specific fields of the header*/ + cfg.hdr.msgType = TCFG; + cfg.hdr.entId.ent = ENTCC; + cfg.hdr.entId.inst = S_INST; + cfg.hdr.elmId.elmnt = STISAP; + + cfg.hdr.elmId.elmntInst1 = k->id; + + cfg.t.cfg.s.ccISAP.suId = k->suId; + cfg.t.cfg.s.ccISAP.spId = k->spId; + cfg.t.cfg.s.ccISAP.pst.dstProcId = SFndProcId(); + cfg.t.cfg.s.ccISAP.pst.dstEnt = ENTSI; + cfg.t.cfg.s.ccISAP.pst.dstInst = S_INST; + cfg.t.cfg.s.ccISAP.pst.srcProcId = SFndProcId(); + cfg.t.cfg.s.ccISAP.pst.srcEnt = ENTCC; + cfg.t.cfg.s.ccISAP.pst.srcInst = S_INST; + cfg.t.cfg.s.ccISAP.pst.prior = PRIOR0; + cfg.t.cfg.s.ccISAP.pst.route = RTESPEC; + cfg.t.cfg.s.ccISAP.pst.region = S_REG; + cfg.t.cfg.s.ccISAP.pst.pool = S_POOL; + cfg.t.cfg.s.ccISAP.pst.selector = 0; + + return(sng_cfg_cc(&pst, &cfg)); +} + +/******************************************************************************/ + +/******************************************************************************/ +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c index eaf36cffab..edb15604e5 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c @@ -50,6 +50,8 @@ static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int static ftdm_status_t handle_set_message_trace(ftdm_stream_handle_t *stream, int on, int level); static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose); static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, int chan, int verbose); +static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name); +static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *name); static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, int chan, int verbose); static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, int chan, int verbose); @@ -58,6 +60,9 @@ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, i static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose); static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose); +static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose); +static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose); + static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name); static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name); @@ -68,946 +73,1254 @@ static ftdm_status_t check_arg_count(int args, int min); /* FUNCTIONS ******************************************************************/ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data) { - char *mycmd = NULL; - char *argv[10] = { 0 }; - int argc = 0; - int span = 0; - int chan = 0; - int trace = 0; - int trace_level = 7; - int verbose = 1; - int c = 0; + char *mycmd = NULL; + char *argv[10] = { 0 }; + int argc = 0; + int span = 0; + int chan = 0; + int range = 0; + int trace = 0; + int trace_level = 7; + int verbose = 1; + int c = 0; - if (data) { - mycmd = ftdm_strdup(data); - argc = ftdm_separate_string(mycmd,' ',argv,(sizeof(argv) / sizeof(argv[0]))); - } + if (data) { + mycmd = ftdm_strdup(data); + argc = ftdm_separate_string(mycmd,' ',argv,(sizeof(argv) / sizeof(argv[0]))); + } - if (check_arg_count(argc, 1)) goto handle_cli_error_argc; - - if (!strcasecmp(argv[c], "show")) { - /**************************************************************************/ - if (check_arg_count(argc, 4)) goto handle_cli_error_argc; - c++; + if (check_arg_count(argc, 1)) goto handle_cli_error_argc; + + if (!strcasecmp(argv[c], "show")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; - if (!strcasecmp(argv[c], "status")) { - /**********************************************************************/ - c++; + if (!strcasecmp(argv[c], "status")) { + /**********************************************************************/ + c++; - if (!strcasecmp(argv[c], "link")) { - /******************************************************************/ - c++; - handle_status_link(stream, argv[c]); - /******************************************************************/ - } else if (!strcasecmp(argv[c], "linkset")) { - /******************************************************************/ - c++; - handle_status_linkset(stream, argv[c]); - /******************************************************************/ - } else if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + if (!strcasecmp(argv[c], "link")) { + /******************************************************************/ + c++; + handle_status_link(stream, argv[c]); + /******************************************************************/ + } else if (!strcasecmp(argv[c], "linkset")) { + /******************************************************************/ + c++; + handle_status_linkset(stream, argv[c]); + /******************************************************************/ + } else if (!strcasecmp(argv[c], "span")) { + /******************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - handle_show_status(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"status\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "inuse")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; + handle_show_status(stream, span, chan, verbose); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"status\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "inuse")) { + /**********************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + c++; - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + if (!strcasecmp(argv[c], "span")) { + /******************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - handle_show_inuse(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"inuse\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "inreset")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; + handle_show_inuse(stream, span, chan, verbose); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"inuse\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "inreset")) { + /**********************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + c++; - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + if (!strcasecmp(argv[c], "span")) { + /******************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - handle_show_inreset(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"inreset\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "free")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; + handle_show_inreset(stream, span, chan, verbose); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"inreset\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "free")) { + /**********************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + c++; - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + if (!strcasecmp(argv[c], "span")) { + /******************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - handle_show_free(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"free\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "blocks")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; + handle_show_free(stream, span, chan, verbose); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"free\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "blocks")) { + /**********************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + c++; - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + if (!strcasecmp(argv[c], "span")) { + /******************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - handle_show_blocks(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"blocks\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "flags")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; + handle_show_blocks(stream, span, chan, verbose); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"blocks\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "flags")) { + /**********************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + c++; - if (!strcasecmp(argv[c], "span")) { - /******************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + if (!strcasecmp(argv[c], "span")) { + /******************************************************************/ + if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - handle_show_flags(stream, span, chan, verbose); - /******************************************************************/ - } else { - /******************************************************************/ - stream->write_function(stream, "Unknown \"flags\" command\n"); - goto handle_cli_error; - /******************************************************************/ - } - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"show\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "set")) { - /**************************************************************************/ - if (check_arg_count(argc, 4)) goto handle_cli_error_argc; - c++; + handle_show_flags(stream, span, chan, verbose); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"flags\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "mem")) { + /**********************************************************************/ + /*uint32_t availMem;*/ - if (!strcasecmp(argv[c], "ftrace")) { - /**********************************************************************/ - c++; - trace = atoi(argv[c]); - c++; - trace_level = atoi(argv[c]); - c++; - handle_set_function_trace(stream, trace, trace_level); - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "mtrace")) { - /**********************************************************************/ - c++; - trace = atoi(argv[c]); - c++; - trace_level = atoi(argv[c]); - c++; - handle_set_message_trace(stream, trace, trace_level); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"set\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "block")) { - /**************************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; + /*sng_sta_mem(&availMem);*/ + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "stats")) { + /**********************************************************************/ +/* sng_mtp1_sts_t sts; - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + memset(&sts, 0x0, sizeof(sng_mtp1_sts_t)); - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + sng_mtp1_sts(1, &sts); - handle_set_blocks(stream, span, chan, verbose); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"block\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else if (!strcasecmp(argv[c], "unblock")) { - /**************************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; - c++; + stream->write_function(stream,"MTP1 tx stats:|tx_frm=%d|tx_err=%d|tx_fisu=%d|tx_lssu=%d|tx_msu=%d|\n", + sts.tx_frm, sts.tx_err, sts.tx_fisu, sts.tx_lssu, sts.tx_msu); + stream->write_function(stream,"MTP1 rx stats:|rx_frm=%d|rx_err=%d|rx_fisu=%d|rx_lssu=%d|rx_msu=%d|\n", + sts.rx_frm, sts.rx_err, sts.rx_fisu, sts.rx_lssu, sts.rx_msu); +*/ + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"show\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "set")) { + /**************************************************************************/ + if (check_arg_count(argc, 4)) goto handle_cli_error_argc; + c++; - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 6)) goto handle_cli_error_argc; + if (!strcasecmp(argv[c], "ftrace")) { + /**********************************************************************/ + c++; + trace = atoi(argv[c]); + c++; + trace_level = atoi(argv[c]); + c++; + handle_set_function_trace(stream, trace, trace_level); + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "mtrace")) { + /**********************************************************************/ + c++; + trace = atoi(argv[c]); + c++; + trace_level = atoi(argv[c]); + c++; + handle_set_message_trace(stream, trace, trace_level); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"set\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "block")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - handle_set_unblks(stream, span, chan, verbose); - /**********************************************************************/ - } else { - /**********************************************************************/ - stream->write_function(stream, "Unknown \"unblock\" command\n"); - goto handle_cli_error; - /**********************************************************************/ - } - /**************************************************************************/ - } else { - /**************************************************************************/ - goto handle_cli_error; - /**************************************************************************/ - } + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - return FTDM_SUCCESS; + handle_set_blocks(stream, span, chan, verbose); + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "link")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_set_inhibit(stream, argv[c]); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"block\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "unblock")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + + handle_set_unblks(stream, span, chan, verbose); + /**********************************************************************/ + } else if (!strcasecmp(argv[c], "link")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_set_uninhibit(stream, argv[c]); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"unblock\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "rsc")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + + handle_tx_rsc(stream, span, chan, verbose); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"rsc\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "grs")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + c = c + 4; + + if (check_arg_count(argc, 7)) goto handle_cli_error_argc; + + if (!strcasecmp(argv[c], "range")) { + /******************************************************************/ + c++; + range = atoi(argv[c]); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"grs range\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + + handle_tx_grs(stream, span, chan, range, verbose); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"grs\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else { + /**************************************************************************/ + goto handle_cli_error; + /**************************************************************************/ + } + + return FTDM_SUCCESS; handle_cli_error_argc: - stream->write_function(stream, "Invalid # of arguments in command\n"); - handle_print_usuage(stream); - return FTDM_SUCCESS; + stream->write_function(stream, "Invalid # of arguments in command\n"); + handle_print_usuage(stream); + return FTDM_SUCCESS; handle_cli_error_span_chan: - stream->write_function(stream, "Unknown \"span\\chan\" command\n"); - handle_print_usuage(stream); - return FTDM_SUCCESS; + stream->write_function(stream, "Unknown \"span\\chan\" command\n"); + handle_print_usuage(stream); + return FTDM_SUCCESS; handle_cli_error: - stream->write_function(stream, "Unknown command requested\n"); - handle_print_usuage(stream); - return FTDM_SUCCESS; + stream->write_function(stream, "Unknown command requested\n"); + handle_print_usuage(stream); + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream) { - stream->write_function(stream, "Sangoma SS7 CLI usuage:\n\n"); + stream->write_function(stream, "Sangoma SS7 CLI usuage:\n\n"); - stream->write_function(stream, "Ftmod_sangoma_ss7 general control:\n"); - stream->write_function(stream, "ftdm ss7 set ftace X Y\n"); - stream->write_function(stream, "ftdm ss7 set mtace X Y\n"); - stream->write_function(stream, "\n"); - stream->write_function(stream, "Ftmod_sangoma_ss7 information:\n"); - stream->write_function(stream, "ftdm ss7 show status link X\n"); - stream->write_function(stream, "ftdm ss7 show status linkset X\n"); - stream->write_function(stream, "ftdm ss7 show status span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 show free span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 show inuse span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 show inreset span X chan Y\n"); - stream->write_function(stream, "\n"); - stream->write_function(stream, "Ftmod_sangoma_ss7 circuit control:\n"); - stream->write_function(stream, "ftdm ss7 set block span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 set unblk span X chan Y\n"); - stream->write_function(stream, "\n"); + stream->write_function(stream, "Ftmod_sangoma_ss7 general control:\n"); + stream->write_function(stream, "ftdm ss7 set ftace X Y\n"); + stream->write_function(stream, "ftdm ss7 set mtace X Y\n"); + stream->write_function(stream, "\n"); + stream->write_function(stream, "Ftmod_sangoma_ss7 information:\n"); + stream->write_function(stream, "ftdm ss7 show status link X\n"); + stream->write_function(stream, "ftdm ss7 show status linkset X\n"); + stream->write_function(stream, "ftdm ss7 show status span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 show free span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 show inuse span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 show inreset span X chan Y\n"); + stream->write_function(stream, "\n"); + stream->write_function(stream, "Ftmod_sangoma_ss7 circuit control:\n"); + stream->write_function(stream, "ftdm ss7 block span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 unblk span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 rsc span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 grs span X chan Y range Z\n"); + stream->write_function(stream, "\n"); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int on, int level) { - stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace was %s, level = %d\n", - (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF", - g_ftdm_sngss7_data.function_trace_level); + stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace was %s, level = %d\n", + (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF", + g_ftdm_sngss7_data.function_trace_level); - g_ftdm_sngss7_data.function_trace = on; - g_ftdm_sngss7_data.function_trace_level = level; + g_ftdm_sngss7_data.function_trace = on; + g_ftdm_sngss7_data.function_trace_level = level; - stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace now is %s, level = %d\n", - (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF", - g_ftdm_sngss7_data.function_trace_level); + stream->write_function(stream, "ftmod_sangoma_ss7 Function Trace now is %s, level = %d\n", + (g_ftdm_sngss7_data.function_trace == 1) ? "ON" : "OFF", + g_ftdm_sngss7_data.function_trace_level); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_set_message_trace(ftdm_stream_handle_t *stream, int on, int level) { - stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace was %s, level = %d\n", - (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF", - g_ftdm_sngss7_data.message_trace_level); + stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace was %s, level = %d\n", + (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF", + g_ftdm_sngss7_data.message_trace_level); - g_ftdm_sngss7_data.message_trace = on; - g_ftdm_sngss7_data.message_trace_level = level; + g_ftdm_sngss7_data.message_trace = on; + g_ftdm_sngss7_data.message_trace_level = level; - stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace now is %s, level = %d\n", - (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF", - g_ftdm_sngss7_data.message_trace_level); + stream->write_function(stream, "ftmod_sangoma_ss7 Message Trace now is %s, level = %d\n", + (g_ftdm_sngss7_data.message_trace == 1) ? "ON" : "OFF", + g_ftdm_sngss7_data.message_trace_level); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - int free; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + int x; + int free; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; - x=1; - free = 0; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj; - ftdmchan = ss7_info->ftdmchan; + x=1; + free = 0; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - switch (ftdmchan->state) { - /******************************************************************/ - case (FTDM_CHANNEL_STATE_DOWN): - if (verbose) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic, - ftdm_channel_state2str(ftdmchan->state)); - } /* if (verbose) */ + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + switch (ftdmchan->state) { + /******************************************************************/ + case (FTDM_CHANNEL_STATE_DOWN): + if (verbose) { + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id, + ss7_info->circuit->cic, + ftdm_channel_state2str(ftdmchan->state)); + } /* if (verbose) */ - /*increment the count of circuits in reset */ - free++; - break; - /******************************************************************/ - default: - break; - /******************************************************************/ - } /* switch (ftdmchan->state) */ - } /* if ( span and chan) */ - } /* if ( cic != 0) */ + /*increment the count of circuits in reset */ + free++; + break; + /******************************************************************/ + default: + break; + /******************************************************************/ + } /* switch (ftdmchan->state) */ + } /* if ( span and chan) */ + } /* if ( cic != 0) */ - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */ + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - stream->write_function(stream, "\nTotal # of CICs free = %d\n",free); + stream->write_function(stream, "\nTotal # of CICs free = %d\n",free); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - int in_use; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + int x; + int in_use; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; - x=1; - in_use = 0; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj; - ftdmchan = ss7_info->ftdmchan; + x=1; + in_use = 0; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - switch (ftdmchan->state) { - /******************************************************************/ - case (FTDM_CHANNEL_STATE_COLLECT): - 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): - case (FTDM_CHANNEL_STATE_TERMINATING): - case (FTDM_CHANNEL_STATE_HANGUP): - if (verbose) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic, - ftdm_channel_state2str(ftdmchan->state)); - } /* if (verbose) */ + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + switch (ftdmchan->state) { + /******************************************************************/ + case (FTDM_CHANNEL_STATE_COLLECT): + 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): + case (FTDM_CHANNEL_STATE_TERMINATING): + case (FTDM_CHANNEL_STATE_HANGUP): + if (verbose) { + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|state=%s\n", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id, + ss7_info->circuit->cic, + ftdm_channel_state2str(ftdmchan->state)); + } /* if (verbose) */ - /*increment the count of circuits in reset */ - in_use++; - break; - /******************************************************************/ - default: - break; - /******************************************************************/ - } /* switch (ftdmchan->state) */ - } /* if ( span and chan) */ - } /* if ( cic != 0) */ + /*increment the count of circuits in reset */ + in_use++; + break; + /******************************************************************/ + default: + break; + /******************************************************************/ + } /* switch (ftdmchan->state) */ + } /* if ( span and chan) */ + } /* if ( cic != 0) */ - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */ + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - stream->write_function(stream, "\nTotal # of CICs in use = %d\n",in_use); + stream->write_function(stream, "\nTotal # of CICs in use = %d\n",in_use); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - int in_reset; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + int x; + int in_reset; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; - x=1; - in_reset = 0; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj; - ftdmchan = ss7_info->ftdmchan; + x=1; + in_reset = 0; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX)) || (sngss7_test_flag(ss7_info, FLAG_RESET_TX))) { - if (verbose) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|in_reset=Y\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic); - } /* if (verbose) */ - - /*increment the count of circuits in reset */ - in_reset++; - } /* if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX) ... */ - } /* if ( span and chan) */ - } /* if ( cic != 0) */ + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX)) || + (sngss7_test_flag(ss7_info, FLAG_RESET_TX)) || + (sngss7_test_flag(ss7_info, FLAG_GRP_RESET_RX)) || + (sngss7_test_flag(ss7_info, FLAG_GRP_RESET_TX))) { + + if (verbose) { + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|in_reset=Y\n", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id, + ss7_info->circuit->cic); + } /* if (verbose) */ + + /*increment the count of circuits in reset */ + in_reset++; + } /* if ((sngss7_test_flag(ss7_info, FLAG_RESET_RX) ... */ + } /* if ( span and chan) */ + } /* if ( cic != 0) */ - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */ + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - stream->write_function(stream, "\nTotal # of CICs in reset = %d\n",in_reset); + stream->write_function(stream, "\nTotal # of CICs in reset = %d\n",in_reset); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - int bit; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + int x; + int bit; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; - x=1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj; - ftdmchan = ss7_info->ftdmchan; + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic); - - for (bit = 0; bit < 33; bit++) { - stream->write_function(stream, "|"); - if (ss7_info->flags & ( 0x1 << bit)) { - stream->write_function(stream, "%2d=1", bit); - } else { - stream->write_function(stream, "%2d=0", bit); - } - } + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id, + ss7_info->circuit->cic); + + for (bit = 0; bit < 33; bit++) { + stream->write_function(stream, "|"); + if (ss7_info->flags & ( 0x1 << bit)) { + stream->write_function(stream, "%2d=1", bit); + } else { + stream->write_function(stream, "%2d=0", bit); + } + } - stream->write_function(stream, "\n"); - } /* if ( span and chan) */ + stream->write_function(stream, "\n"); + } /* if ( span and chan) */ - } /* if ( cic != 0) */ + } /* if ( cic != 0) */ - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */ + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + int x; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; - x=1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj; - ftdmchan = ss7_info->ftdmchan; + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic); + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id, + ss7_info->circuit->cic); - if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { - stream->write_function(stream, "l_mn=Y|"); - }else { - stream->write_function(stream, "l_mn=N|"); - } + if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { + stream->write_function(stream, "l_mn=Y|"); + }else { + stream->write_function(stream, "l_mn=N|"); + } - if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { - stream->write_function(stream, "r_mn=Y|"); - }else { - stream->write_function(stream, "r_mn=N|"); - } + if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { + stream->write_function(stream, "r_mn=Y|"); + }else { + stream->write_function(stream, "r_mn=N|"); + } - if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { - stream->write_function(stream, "l_hw=Y|"); - }else { - stream->write_function(stream, "l_hw=N|"); - } + if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { + stream->write_function(stream, "l_hw=Y|"); + }else { + stream->write_function(stream, "l_hw=N|"); + } - if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { - stream->write_function(stream, "r_hw=Y\n"); - }else { - stream->write_function(stream, "r_hw=N\n"); - } - } /* if ( span and chan) */ + if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { + stream->write_function(stream, "r_hw=Y|"); + }else { + stream->write_function(stream, "r_hw=N|"); + } - } /* if ( cic != 0) */ + if(sngss7_test_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) { + stream->write_function(stream, "l_mngmt=Y|"); + }else { + stream->write_function(stream, "l_mngmt=N|"); + } - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */ + if(sngss7_test_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) { + stream->write_function(stream, "l_ucic=Y|"); + }else { + stream->write_function(stream, "l_ucic=N|"); + } - return FTDM_SUCCESS; + stream->write_function(stream, "\n"); + } /* if ( span and chan) */ + + } /* if ( cic != 0) */ + + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; + int x; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; + ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; - x=1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj; - ftdmchan = ss7_info->ftdmchan; + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - /* grab the signaling_status */ - ftdm_channel_get_sig_status(ftdmchan, &sigstatus); + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + /* grab the signaling_status */ + ftdm_channel_get_sig_status(ftdmchan, &sigstatus); - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%s|state=%s|", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic, - ftdm_signaling_status2str(sigstatus), - ftdm_channel_state2str(ftdmchan->state)); + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%s|state=%s|", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id, + ss7_info->circuit->cic, + ftdm_signaling_status2str(sigstatus), + ftdm_channel_state2str(ftdmchan->state)); - if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { - stream->write_function(stream, "l_mn=Y|"); - }else { - stream->write_function(stream, "l_mn=N|"); - } + if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { + stream->write_function(stream, "l_mn=Y|"); + }else { + stream->write_function(stream, "l_mn=N|"); + } - if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { - stream->write_function(stream, "r_mn=Y|"); - }else { - stream->write_function(stream, "r_mn=N|"); - } + if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { + stream->write_function(stream, "r_mn=Y|"); + }else { + stream->write_function(stream, "r_mn=N|"); + } - if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { - stream->write_function(stream, "l_hw=Y|"); - }else { - stream->write_function(stream, "l_hw=N|"); - } + if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { + stream->write_function(stream, "l_hw=Y|"); + }else { + stream->write_function(stream, "l_hw=N|"); + } - if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { - stream->write_function(stream, "r_hw=Y\n"); - }else { - stream->write_function(stream, "r_hw=N\n"); - } - } /* if ( span and chan) */ + if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { + stream->write_function(stream, "r_hw=Y|"); + }else { + stream->write_function(stream, "r_hw=N|"); + } - } /* if ( cic != 0) */ + if(sngss7_test_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) { + stream->write_function(stream, "l_mngmt=Y|"); + }else { + stream->write_function(stream, "l_mngmt=N|"); + } - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */ + if(sngss7_test_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) { + stream->write_function(stream, "l_ucic=Y|"); + }else { + stream->write_function(stream, "l_ucic=N|"); + } - return FTDM_SUCCESS; + stream->write_function(stream, "flags=0x%X",ss7_info->flags); - return FTDM_SUCCESS; + stream->write_function(stream, "\n"); + } /* if ( span and chan) */ + + } /* if ( cic != 0) */ + + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + int x; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; - x=1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj; - ftdmchan = ss7_info->ftdmchan; + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); - /* check if there is a pending state change|give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); - } else { - /* throw the ckt block flag */ - sngss7_set_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); + /* check if there is a pending state change|give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); + SS7_ASSERT; + } else { + /* throw the ckt block flag */ + sngss7_set_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); - } /* if ( span and chan) */ + } /* if ( span and chan) */ - } /* if ( cic != 0) */ + } /* if ( cic != 0) */ - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */ + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - handle_show_blocks(stream, span, chan, verbose); + handle_show_blocks(stream, span, chan, verbose); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + int x; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; - x=1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink != 1) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCircuit[x].obj; - ftdmchan = ss7_info->ftdmchan; + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - /* if span == 0 then all spans should be printed */ - if (span == 0) { - lspan = ftdmchan->physical_span_id; - } else { - lspan = span; - } + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } - /* if chan == 0 then all chans should be printed */ - if (chan == 0) { - lchan = ftdmchan->physical_chan_id; - } else { - lchan = chan; - } + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); - /* check if there is a pending state change|give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); - } else { - /* throw the ckt block flag */ - sngss7_set_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX); + /* check if there is a pending state change|give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); + SS7_ASSERT; + } else { + /* throw the ckt block flag */ + sngss7_set_flag(ss7_info, FLAG_CKT_MN_UNBLK_TX); - /* clear the block flag */ - sngss7_clear_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); + /* clear the block flag */ + sngss7_clear_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX); - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - } + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); - } /* if ( span and chan) */ + } /* if ( span and chan) */ - } /* if ( cic != 0) */ + } /* if ( cic != 0) */ - /* go the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */ + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ - handle_show_blocks(stream, span, chan, verbose); + handle_show_blocks(stream, span, chan, verbose); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name) { - int x; - sng_mtp3Link_sta_t sta; + int x = 0; + SnMngmt sta; + + /* find the link request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) { - /* find the link request by it's name */ - x = 1; - while(g_ftdm_sngss7_data.cfg.mtp3Link[x].id != 0) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) { - /* send the status request */ - if (sng_sta_mtp3_link(&g_ftdm_sngss7_data.cfg, x, &sta)) { - stream->write_function(stream, "Failed to read link=%s status\n", name); - return FTDM_FAIL; - } + /* send the status request */ + if (ftmod_ss7_mtplink_sta(x, &sta)) { + stream->write_function(stream, "Failed to read link=%s status\n", name); + return FTDM_FAIL; + } - /* print the results */ - stream->write_function(stream, "%s|state=%s|l_blk=%s|r_blk=%s|l_inhbt=%s|r_inhbt=%s\n", - name, - DECODE_LSN_LINK_STATUS(sta.state), - (sta.lblkd) ? "Y":"N", - (sta.rblkd) ? "Y":"N", - (sta.linhbt) ? "Y":"N", - (sta.rinhbt) ? "Y":"N"); - break; - } - - /* move to the next link */ - x++; - } /* while (id != 0) */ + /* print the results */ + stream->write_function(stream, "%s|span=%d|chan=%d|sap=%d|state=%s|l_blk=%s|r_blk=%s|l_inhbt=%s|r_inhbt=%s\n", + name, + g_ftdm_sngss7_data.cfg.mtpLink[x].mtp1.span, + g_ftdm_sngss7_data.cfg.mtpLink[x].mtp1.chan, + g_ftdm_sngss7_data.cfg.mtpLink[x].id, + DECODE_LSN_LINK_STATUS(sta.t.ssta.s.snDLSAP.state), + (sta.t.ssta.s.snDLSAP.locBlkd) ? "Y":"N", + (sta.t.ssta.s.snDLSAP.remBlkd) ? "Y":"N", + (sta.t.ssta.s.snDLSAP.locInhbt) ? "Y":"N", + (sta.t.ssta.s.snDLSAP.rmtInhbt) ? "Y":"N"); + break; + } + + /* move to the next link */ + x++; + } /* while (id != 0) */ - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name) { - int x; - sng_mtp3LinkSet_sta_t sta; + int x = 0; + SnMngmt sta; - /* find the linkset request by it's name */ - x = 1; - while(g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].id != 0) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].name, name)) { - /* send the status request */ - if (sng_sta_mtp3_linkset(&g_ftdm_sngss7_data.cfg, x, 0, &sta)) { - stream->write_function(stream, "Failed to read linkset=%s status\n", name); - return FTDM_FAIL; - } + /* find the linkset request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, name)) { - /* print the results */ - stream->write_function(stream, "%s|state=%s|nmbActLnk=%d\n", - name, - DECODE_LSN_LINKSET_STATUS(sta.state), - sta.nmbActLnks); - break; - } + /* send the status request */ + if (ftmod_ss7_mtplinkSet_sta(x, &sta)) { + stream->write_function(stream, "Failed to read linkset=%s status\n", name); + return FTDM_FAIL; + } + + /* print the results */ + stream->write_function(stream, "%s|state=%s|nmbActLnk=%d\n", + name, + DECODE_LSN_LINKSET_STATUS(sta.t.ssta.s.snLnkSet.state), + sta.t.ssta.s.snLnkSet.nmbActLnks); + break; + } - /* move to the next linkset */ - x++; - } /* while (id != 0) */ + /* move to the next linkset */ + x++; + } /* while (id != 0) */ - return FTDM_SUCCESS; + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name) +{ + int x = 0; + + /* find the link request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) { + + /* send the inhibit request */ + if (ftmod_ss7_inhibit_mtplink(x)) { + stream->write_function(stream, "Failed to inhibit link=%s\n", name); + return FTDM_FAIL; + } + + /* print the new status of the link */ + handle_status_link(stream, &name[0]); + + break; + } + + /* move to the next linkset */ + x++; + } /* while (id != 0) */ + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *name) +{ + int x = 0; + + /* find the link request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) { + + /* send the uninhibit request */ + if (ftmod_ss7_uninhibit_mtplink(x)) { + stream->write_function(stream, "Failed to uninhibit link=%s\n", name); + return FTDM_FAIL; + } + + /* print the new status of the link */ + handle_status_link(stream, &name[0]); + + break; + } + + /* move to the next linkset */ + x++; + } /* while (id != 0) */ + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose) +{ + int x; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; + + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; + + /* if span == 0 then all spans should be printed */ + if (span == 0) { + lspan = ftdmchan->physical_span_id; + } else { + lspan = span; + } + + /* if chan == 0 then all chans should be printed */ + if (chan == 0) { + lchan = ftdmchan->physical_chan_id; + } else { + lchan = chan; + } + + if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change|give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); + SS7_ASSERT; + } else { + /* throw the ckt block flag */ + sngss7_set_flag(ss7_info, FLAG_RESET_TX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* if ( span and chan) */ + + } /* if ( cic != 0) */ + + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose) +{ + int x; + sngss7_chan_data_t *sngss7_info; + ftdm_channel_t *ftdmchan; + sngss7_span_data_t *sngss7_span; + + if (range > 31) { + stream->write_function(stream, "Invalid range value %d", range); + return FTDM_SUCCESS; + } + + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + + sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = sngss7_info->ftdmchan; + sngss7_span = ftdmchan->span->mod_data; + + if ((ftdmchan->physical_span_id == span) && + ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change|give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + SS7_ASSERT; + } else { + /* throw the grp reset flag */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); + if (ftdmchan->physical_chan_id == chan) { + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE); + sngss7_span->tx_grs.circuit = sngss7_info->circuit->id; + sngss7_span->tx_grs.range = range-1; + } + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* if ( span and chan) */ + + } /* if ( cic != 0) */ + + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + + + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan) { - if (!strcasecmp(argv[pos], "span")) { - /**************************************************************************/ - pos++; - *span = atoi(argv[pos]); + if (!strcasecmp(argv[pos], "span")) { + /**************************************************************************/ + pos++; + *span = atoi(argv[pos]); - pos++; - if (!strcasecmp(argv[pos], "chan")) { - /**********************************************************************/ - pos++; - *chan = atoi(argv[pos]); - /**********************************************************************/ - } else { - /**********************************************************************/ - return FTDM_FAIL; - /**********************************************************************/ - } - /**************************************************************************/ - } else { - /**************************************************************************/ - *span = atoi(argv[pos]); + pos++; + if (!strcasecmp(argv[pos], "chan")) { + /**********************************************************************/ + pos++; + *chan = atoi(argv[pos]); + /**********************************************************************/ + } else { + /**********************************************************************/ + return FTDM_FAIL; + /**********************************************************************/ + } + /**************************************************************************/ + } else { + /**************************************************************************/ + *span = atoi(argv[pos]); - pos++; - if (!strcasecmp(argv[pos], "chan")) { - /**********************************************************************/ - pos++; - *chan = atoi(argv[pos]); - /**********************************************************************/ - } else { - /**********************************************************************/ - return FTDM_FAIL; - /**********************************************************************/ - } - /**************************************************************************/ - } + pos++; + if (!strcasecmp(argv[pos], "chan")) { + /**********************************************************************/ + pos++; + *chan = atoi(argv[pos]); + /**********************************************************************/ + } else { + /**********************************************************************/ + return FTDM_FAIL; + /**********************************************************************/ + } + /**************************************************************************/ + } - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static ftdm_status_t check_arg_count(int args, int min) { - if ( args < min ) { - return FTDM_FAIL; - } else { - return FTDM_SUCCESS; - } -} + if ( args < min ) { + return FTDM_FAIL; + } else { + return FTDM_SUCCESS; + } +} /******************************************************************************/ /* For Emacs: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c index 66f3003832..52b3860375 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c @@ -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: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c new file mode 100644 index 0000000000..f0cfa0237a --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -0,0 +1,2004 @@ +/* + * Copyright (c) 2009 Konrad Hammel + * All rights reserved. + * + * Redistribution and use in source and binary forms|with or without + * modification|are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice|this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice|this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT + * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, + * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* INCLUDE ********************************************************************/ +#include "ftmod_sangoma_ss7_main.h" +/******************************************************************************/ + +/* DEFINES ********************************************************************/ +/******************************************************************************/ + +/* GLOBALS ********************************************************************/ +/******************************************************************************/ + +/* PROTOTYPES *****************************************************************/ +ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); +ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); +ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); +ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); +ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); +ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt); +ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); +ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); +ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); +ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); + +ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +/******************************************************************************/ + +/* FUNCTIONS ******************************************************************/ +ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) { + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM (glare detected on circuit)\n"); + } else { + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IAM\n"); + } + + /* check if the circuit has a remote block */ + if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { + + /* as per Q.764, 2.8.2.3 xiv ... remove the block from this channel */ + sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + sngss7_clear_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); + sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); + + /* KONRAD FIX ME : check in case there is a ckt and grp block */ + } + + /* check whether the ftdm channel is in a state to accept a call */ + switch (ftdmchan->state) { + /**************************************************************************/ + case (FTDM_CHANNEL_STATE_DOWN): /* only state it is valid to get IAM (except if there is glare */ + + /* check if there is any reason why we can't use this channel */ + if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { + /* channel is already requested for use by the ftdm core */ + goto handle_glare; + } else if(ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { + /* channel is not inuse but we can't open it...fail the call */ + SS7_ERROR("Failed to open span: %d, chan: %d\n", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id); + + /* set the flag to indicate this hangup is started from the local side */ + sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL); + + ftdmchan->caller_data.hangup_cause = 41; + + /* move the state to CANCEL */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + + } else { + + /* fill in the channels SS7 Stack information */ + sngss7_info->suInstId = get_unique_id(); + sngss7_info->spInstId = spInstId; + + /* fill in calling party information */ + if (siConEvnt->cgPtyNum.eh.pres) { + if (siConEvnt->cgPtyNum.addrSig.pres) { + /* fill in cid_num */ + copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig, + ftdmchan->caller_data.cid_num.digits, + siConEvnt->cgPtyNum.oddEven); + + /* fill in cid Name */ + ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits); + + /* fill in ANI */ + ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits); + } + + if (siConEvnt->cgPtyNum.scrnInd.pres) { + /* fill in the screening indication value */ + ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val; + } + + if (siConEvnt->cgPtyNum.presRest.pres) { + /* fill in the presentation value */ + ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val; + } + } else { + SS7_INFO_CHAN(ftdmchan,"No Calling party (ANI) information in IAM!%s\n", " "); + } + + /* fill in called party infomation */ + if (siConEvnt->cdPtyNum.eh.pres) { + if (siConEvnt->cdPtyNum.addrSig.pres) { + /* fill in the called number/dnis */ + copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, + ftdmchan->caller_data.dnis.digits, + siConEvnt->cdPtyNum.oddEven); + } + } else { + SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in IAM!%s\n", " "); + } + + /* fill in rdnis information*/ + if (siConEvnt->redirgNum.eh.pres) { + if (siConEvnt->redirgNum.addrSig.pres) { + /* fill in the rdnis digits */ + copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig, + ftdmchan->caller_data.rdnis.digits, + siConEvnt->cgPtyNum.oddEven); + } + } else { + SS7_DEBUG_CHAN(ftdmchan,"No RDNIS party information in IAM!%s\n", " "); + } + + /* fill in the TMR/bearer capability */ + if (siConEvnt->txMedReq.eh.pres) { + if (siConEvnt->txMedReq.trMedReq.pres) { + /* fill in the bearer type */ + ftdmchan->caller_data.bearer_capability = siConEvnt->txMedReq.trMedReq.val; + } + } else { + SS7_DEBUG_CHAN(ftdmchan,"No TMR/Bearer Cap information in IAM!%s\n", " "); + } + + /* add any special variables for the dialplan */ + /*ftdm_channel_add_var(ftdmchan, "ss7_stuff", "s");*/ + + /* set the state of the channel to collecting...the rest is done by the chan monitor */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); + + } /* if (channel is usable */ + + break; + /**************************************************************************/ + case (FTDM_CHANNEL_STATE_DIALING): + case (FTDM_CHANNEL_STATE_TERMINATING): + case (FTDM_CHANNEL_STATE_HANGUP): + case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE): +handle_glare: + /* the core already has plans for this channel...glare */ + SS7_INFO_CHAN(ftdmchan, "Got IAM on channel that is already inuse (state=%s|inuse=%d)...glare!\n", + ftdm_channel_state2str (ftdmchan->state), + ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)); + + /* save the info so that we can use it later on */ + sngss7_info->glare.spInstId = spInstId; + sngss7_info->glare.circuit = circuit; + memcpy(&sngss7_info->glare.iam, siConEvnt, sizeof(*siConEvnt)); + + if (!(sngss7_test_flag(sngss7_info, FLAG_GLARE))) { + /* glare, throw the flag */ + sngss7_set_flag(sngss7_info, FLAG_GLARE); + + /* setup the hangup cause */ + ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */ + + /* this is a remote hangup request */ + sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + + /* move the state of the channel to Terminating to end the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + } /* if (!(sngss7_test_flag(sngss7_info, FLAG_GLARE))) */ + break; + /**************************************************************************/ + default: /* should not have gotten an IAM while in this state */ + SS7_ERROR_CHAN(ftdmchan, "Got IAM on channel in invalid state(%s)...reset!\n", ftdm_channel_state2str (ftdmchan->state)); + + /* move the state of the channel to RESTART to force a reset */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + + break; + /**************************************************************************/ + } /* switch (ftdmchan->state) */ + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + } + + switch (evntType) { + /**************************************************************************/ + case (ADDRCMPLT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ACM\n"); + switch (ftdmchan->state) { + /**********************************************************************/ + case FTDM_CHANNEL_STATE_DIALING: + /* KONRAD: should we confirm the instance ids ? */ + + /* need to grab the sp instance id */ + sngss7_info->spInstId = spInstId; + + /* go to PROGRESS */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); + break; + /**********************************************************************/ + default: /* incorrect state...reset the CIC */ + /* go to RESTART */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); + break; + /**********************************************************************/ + } /* switch (ftdmchan->state) */ + /**************************************************************************/ + case (MODIFY): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY\n"); + break; + /**************************************************************************/ + case (MODCMPLT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY-COMPLETE\n"); + break; + /**************************************************************************/ + case (MODREJ): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MODIFY-REJECT\n"); + break; + /**************************************************************************/ + case (PROGRESS): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CPG\n"); + break; + /**************************************************************************/ + case (FRWDTRSFR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FOT\n"); + break; + /**************************************************************************/ + case (INFORMATION): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx INF\n"); + break; + /**************************************************************************/ + case (INFORMATREQ): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx INR\n"); + break; + /**************************************************************************/ + case (SUBSADDR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SAM\n"); + break; + /**************************************************************************/ + case (EXIT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx EXIT\n"); + break; + /**************************************************************************/ + case (NETRESMGT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx NRM\n"); + break; + /**************************************************************************/ + case (IDENTREQ): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IDR\n"); + break; + /**************************************************************************/ + case (IDENTRSP): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx IRS\n"); + break; + /**************************************************************************/ + case (MALCLLPRNT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx MALICIOUS CALL\n"); + break; + /**************************************************************************/ + case (CHARGE): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG\n"); + break; + /**************************************************************************/ + case (TRFFCHGE): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG-TARIFF\n"); + break; + /**************************************************************************/ + case (CHARGEACK): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CRG-ACK\n"); + break; + /**************************************************************************/ + case (CALLOFFMSG): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALL-OFFER\n"); + break; + /**************************************************************************/ + case (LOOPPRVNT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LOP\n"); + break; + /**************************************************************************/ + case (TECT_TIMEOUT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ECT-Timeout\n"); + break; + /**************************************************************************/ + case (RINGSEND): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RINGING-SEND\n"); + break; + /**************************************************************************/ + case (CALLCLEAR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALL-LINE Clear\n"); + break; + /**************************************************************************/ + case (PRERELEASE): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx PRI\n"); + break; + /**************************************************************************/ + case (APPTRANSPORT): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx APM\n"); + break; + /**************************************************************************/ + case (OPERATOR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx OPERATOR\n"); + break; + /**************************************************************************/ + case (METPULSE): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx METERING-PULSE\n"); + break; + /**************************************************************************/ + case (CLGPTCLR): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CALLING_PARTY_CLEAR\n"); + break; + /**************************************************************************/ + case (SUBDIRNUM): + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SUB-DIR\n"); + break; + /**************************************************************************/ + default: + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Unknown Msg\n"); + break; + /**************************************************************************/ + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + + /* check whether the ftdm channel is in a state to accept a call */ + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_PROGRESS: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ANM\n"); + + /* go to UP */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DIALING: + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CON\n"); + + /* go to UP */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); + + break; + /**************************************************************************/ + default: /* incorrect state...reset the CIC */ + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx ANM/CON\n"); + + /* throw the TX reset flag */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); + + /* go to RESTART */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + + break; + /**************************************************************************/ + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx REL\n"); + + /* check whether the ftdm channel is in a state to release a call */ + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DIALING: + + /* pass the release code up to FTDM */ + if (siRelEvnt->causeDgn.causeVal.pres) { + ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; + } else { + SS7_ERROR("REL does not have a cause code!\n"); + ftdmchan->caller_data.hangup_cause = 0; + } + + /* this is a remote hangup request */ + sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + + /* move the state of the channel to CANCEL to end the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RING: + case FTDM_CHANNEL_STATE_PROGRESS: + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: + case FTDM_CHANNEL_STATE_UP: + + /* pass the release code up to FTDM */ + if (siRelEvnt->causeDgn.causeVal.pres) { + ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; + } else { + SS7_ERROR("REL does not have a cause code!\n"); + ftdmchan->caller_data.hangup_cause = 0; + } + + /* this is a remote hangup request */ + sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + + /* move the state of the channel to TERMINATING to end the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + + break; + /**************************************************************************/ + default: + + /* throw the reset flag */ + sngss7_set_flag(sngss7_info, FLAG_RESET_RX); + + /* set the state to RESTART */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } /* switch (ftdmchan->state) */ + + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RLC\n"); + + /* check whether the ftdm channel is in a state to accept a call */ + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + + /* go to DOWN */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: + /* do nothing, just drop the message */ + break; + /**************************************************************************/ + default: + /* KONRAD: should just stop the call...but a reset is easier for now (since it does hangup the call) */ + + /* go to RESTART */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + + break; + /**************************************************************************/ + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx DATA IND\n"); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FAC\n"); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx FAC-CON\n"); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx USER-USER msg\n"); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + switch (evntType) { + /**************************************************************************/ + case SIT_STA_REATTEMPT: /* reattempt indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Reattempt indication\n"); + handle_reattempt(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_ERRORIND: /* error indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Error indication\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CONTCHK: /* continuity check */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT start\n"); + handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CONTREP: /* continuity report */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT report\n"); + handle_cot(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_STPCONTIN: /* stop continuity */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx COT stop\n"); + handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CGQRYRSP: /* circuit grp query response from far end forwarded to upper layer by ISUP */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CQM\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CONFUSION: /* confusion */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CFN\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LOOPBACKACK: /* loop-back acknowledge */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LPA\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRRSRVREQ: /* circuit reservation request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Ckt Resveration req\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRRSRVACK: /* circuit reservation acknowledgement */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Ckt Res ack\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRBLOREQ: /* circuit blocking request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx BLO\n"); + handle_blo_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRBLORSP: /* circuit blocking response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx BLA\n"); + handle_blo_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRUBLREQ: /* circuit unblocking request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UBL\n"); + handle_ubl_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRUBLRSP: /* circuit unblocking response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UBA\n"); + handle_ubl_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRRESREQ: /* circuit reset request - RSC */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RSC\n"); + handle_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRLOCRES: /* reset initiated locally by the software */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local RSC\n"); + handle_local_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRRESRSP: /* circuit reset response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RSC-RLC\n"); + handle_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CGBREQ: /* CGB request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGUREQ: /* CGU request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGU\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGQRYREQ: /* circuit group query request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CQM\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGBRSP: /* mntc. oriented CGB response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGB\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGURSP: /* mntc. oriented CGU response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGU\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_GRSREQ: /* circuit group reset request */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx GRS\n"); + handle_grs_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRUNEQPD: /* circuit unequipped indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UCIC\n"); + handle_ucic(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_GRSRSP: /* circuit group reset response */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx GRA\n"); + handle_grs_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_PAUSEIND: /* pause indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx SUS\n"); + handle_pause(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_RESUMEIND: /* resume indication */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx RES\n"); + handle_resume(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_USRPARTA: /* user part available */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx UPA\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_RMTUSRUNAV: /* remote user not available */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Remote User not Available\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPCONG0: /* congestion indication level 0 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L0\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPCONG1: /* congestion indication level 1 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L1\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPCONG2: /* congestion indication level 2 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L2\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPCONG3: /* congestion indication level 3 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Congestion L3\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_MTPSTPCONG: /* stop congestion indication level 0 */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Stop Congestion\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRLOCALBLOIND: /* Mngmt local blocking */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local BLO\n"); + handle_local_blk(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_CIRLOCALUBLIND: /* Mngmt local unblocking */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local UBL\n"); + handle_local_ubl(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); + break; + /**************************************************************************/ + case SIT_STA_OVERLOAD: /* Overload */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Overload\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LMCGBREQ: /* when LM requests ckt grp blocking */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CGB\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LMCGUREQ: /* when LM requests ckt grp unblocking */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CGU\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LMGRSREQ: /* when LM requests ckt grp reset */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM RSC\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CQM\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + case SIT_STA_CIRLOCGRS: /* group reset initiated locally by the software */ + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx Local GRS\n"); + SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + break; + /**************************************************************************/ + default: + SS7_INFO("[SNG-CC] Received Unknown indication %d\n", evntType); + break; + } /* switch (evntType) */ + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; + +} + +/******************************************************************************/ +ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) { + /* the glare flag is already up so it was caught ... do nothing */ + SS7_DEBUG_CHAN(ftdmchan, "Glare flag is already up...nothing to do!%s\n", " "); + } else { + SS7_DEBUG_CHAN(ftdmchan, "Glare flag is not up yet...indicating glare from reattempt!%s\n", " "); + /* glare, throw the flag */ + sngss7_set_flag(sngss7_info, FLAG_GLARE); + + /* clear any existing glare data from the channel */ + memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t)); + + /* setup the hangup cause */ + ftdmchan->caller_data.hangup_cause = 34; /* Circuit Congrestion */ + + /* this is a remote hangup request */ + sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + + /* move the state of the channel to Terminating to end the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + int infId; + int i; + + /* extract the affect infId from the circuit structure */ + infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; + + /* go through all the circuits now and find any other circuits on this infId */ + i = 1; + while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) { + + /* check that the infId matches and that this is not a siglink */ + if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && + (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) { + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + i++; + continue; + } + + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + i++; + SS7_ASSERT; + }; + + /* check if the circuit is fully started */ + if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_IN_THREAD)) { + /* set the pause flag on the channel */ + sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED); + + /* set the statet o SUSPENDED to bring the sig status down */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */ + + /* move to the next circuit */ + i++; + + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */ + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + int infId; + int i; + + /* extract the affect infId from the circuit structure */ + infId = g_ftdm_sngss7_data.cfg.isupCkt[circuit].infId; + + /* go through all the circuits now and find any other circuits on this infId */ + i = 1; + while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) { + + /* check that the infId matches and that this is not a siglink */ + if ((g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) && + (g_ftdm_sngss7_data.cfg.isupCkt[i].type == VOICE)) { + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + i++; + continue; + } + + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + i++; + SS7_ASSERT; + }; + + /* only resume if we are paused */ + if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { + /* set the resume flag on the channel */ + sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME); + + /* clear the paused flag */ + sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED); + + /* set the statet to SUSPENDED to bring the sig status up */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* if (g_ftdm_sngss7_data.cfg.isupCkt[i].infId == infId) */ + + /* move to the next circuit */ + i++; + + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[i].id != 0) */ + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* open the channel if it is not open */ + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { + if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { + SS7_ERROR("Failed to open CIC %d for COT test!\n", sngss7_info->circuit->cic); + /* KONRAD FIX ME */ + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + } + + /* tell the core to loop the channel */ + ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); + + /* switch to the IN_LOOP state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); + + /* store the sngss7 ids */ + if (suInstId == 0) { + sngss7_info->suInstId = get_unique_id(); + } else { + sngss7_info->suInstId = suInstId; + } + sngss7_info->spInstId = spInstId; + sngss7_info->globalFlg = globalFlg; + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* tell the core to stop looping the channel */ + ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); + + /* exit out of the LOOP state to the last state */ + ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + if ( (siStaEvnt->contInd.eh.pres > 0) && (siStaEvnt->contInd.contInd.pres > 0)) { + SS7_INFO("Continuity Test result for CIC = %d (span %d, chan %d) is: \"%s\"\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + g_ftdm_sngss7_data.cfg.isupCkt[circuit].span, + g_ftdm_sngss7_data.cfg.isupCkt[circuit].chan, + (siStaEvnt->contInd.contInd.val) ? "PASS" : "FAIL"); + } else { + SS7_ERROR("Recieved Continuity report containing no results!\n"); + } + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ + + +/******************************************************************************/ +ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* check if the circuit is already blocked or not */ + if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { + SS7_WARN("Received BLO on circuit that is already blocked!\n"); + } + + /* throw the ckt block flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* KONRAD FIX ME */ + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* check if the channel is blocked */ + if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) { + SS7_WARN("Received UBL on circuit that is not blocked!\n"); + } + + /* throw the unblock flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); + + /* clear the block flag */ + sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* KONRAD FIX ME */ + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* throw the reset flag */ + sngss7_set_flag(sngss7_info, FLAG_RESET_RX); + + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* go to idle so that we can redo the restart state*/ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + + break; + /**************************************************************************/ + default: + + /* set the state of the channel to restart...the rest is done by the chan monitor */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* throw the reset flag */ + sngss7_set_flag(sngss7_info, FLAG_RESET_RX); + + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* go to idle so that we can redo the restart state*/ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + + break; + /**************************************************************************/ + default: + + /* set the state of the channel to restart...the rest is done by the chan monitor */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + switch (ftdmchan->state) { + /**********************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + if ( sngss7_test_flag(sngss7_info, FLAG_RESET_TX) ) { + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP); + + /* go to DOWN */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + } else { + SS7_ERROR("Received RSC-RLC but we're not waiting on a RSC-RLC on CIC #, dropping\n", sngss7_info->circuit->cic); + } + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: + + /* do nothing, just drop the message */ + SS7_DEBUG("Receveived RSC-RLC in down state, dropping\n"); + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_TERMINATING: + case FTDM_CHANNEL_STATE_HANGUP: + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_flag(sngss7_info, FLAG_RESET_TX_RSP); + + /* go to DOWN */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + break; + /**********************************************************************/ + default: + /* ITU Q764-2.9.5.1.c -> release the circuit */ + if ((siStaEvnt != NULL) && + (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && + (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { + ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val; + } else { + ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ + } + + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + break; + /**********************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} +/******************************************************************************/ +ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_span_data_t *sngss7_span = NULL; + int range; + int x; + + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* extract the range value from the event structure */ + if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { + range = siStaEvnt->rangStat.range.val; + } else { + SS7_ERROR("Received GRS with no range value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* loop over the cics starting from circuit until range+1 */ + for (x = circuit; x < (circuit + range + 1); x++) { + /* grab the circuit in question */ + if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x); + break; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_ASSERT; + }; + + /* fill in the span structure for this circuit */ + sngss7_span = ftdmchan->span->mod_data; + sngss7_span->rx_grs.circuit = circuit; + sngss7_span->rx_grs.range = range; + + SS7_INFO_CHAN(ftdmchan, "Rx GRS (%d:%d)\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); + + /* flag the channel as having received a reset */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX); + + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* go to idle so that we can redo the restart state*/ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + + break; + /**************************************************************************/ + default: + + /* set the state of the channel to restart...the rest is done by the chan monitor */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + int range; + int x; + + /* extract the range value from the event structure */ + if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { + range = siStaEvnt->rangStat.range.val; + } else { + SS7_ERROR("Received GRA with no range value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* go through all the circuits in the range */ + for ( x = circuit; x < (circuit + range + 1); x++) { + + /* grab the circuit in question */ + if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + break; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_ASSERT; + }; + + SS7_INFO_CHAN(ftdmchan, "Rx GRA (%d:%d)\n", + g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic, + (g_ftdm_sngss7_data.cfg.isupCkt[circuit].cic + range)); + + switch (ftdmchan->state) { + /**********************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); + + /* go to DOWN */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: + + /* do nothing, just drop the message */ + SS7_DEBUG("Receveived GRA in down state, dropping\n"); + + break; + /**********************************************************************/ + case FTDM_CHANNEL_STATE_TERMINATING: + case FTDM_CHANNEL_STATE_HANGUP: + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + + /* throw the FLAG_RESET_TX_RSP to indicate we have acknowledgement from the remote side */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); + + break; + /**********************************************************************/ + default: + /* ITU Q764-2.9.5.1.c -> release the circuit */ + if ((siStaEvnt != NULL) && + (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && + (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { + ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val; + } else { + ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ + } + + /* go to terminating to hang up the call */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + break; + /**********************************************************************/ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* for (( x = 0; x < (circuit + range); x++) */ + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* check if the circuit is already blocked or not */ + if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { + SS7_WARN("Received local BLO on circuit that is already blocked!\n"); + } + + /* throw the ckt block flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_LC_BLOCK_RX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* check if the circuit is already blocked or not */ + if (sngss7_test_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { + SS7_WARN("Received local UBL on circuit that is already unblocked!\n"); + } + + /* throw the ckt block flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_LC_UNBLK_RX); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; + + /* throw the ckt block flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK); + + /* set the channel to suspended state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_SUCCESS; +} + + +/******************************************************************************/ +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c index b947bc7304..34893cf5aa 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_in.c @@ -53,1481 +53,396 @@ void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); -static ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_local_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); -static ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - -static ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); - - - /******************************************************************************/ /* FUNCTIONS ******************************************************************/ void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); + SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - } + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - }; + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_CON_IND_EVENT; + memcpy(&sngss7_event->event.siConEvnt, siConEvnt, sizeof(*siConEvnt)); - SS7_MSG_TRACE("Received IAM on CIC # %d\n", sngss7_info->circuit->cic); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case (FTDM_CHANNEL_STATE_DOWN): /* only state it is fully valid to get IAM */ - - /* fill in the channels SS7 Stack information */ - sngss7_info->suInstId = get_unique_id(); - sngss7_info->spInstId = spInstId; - - /* try to open the ftdm channel */ - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - SS7_ERROR("Failed to open span: %d, chan: %d\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); - - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL); - - ftdmchan->caller_data.hangup_cause = 41; - - /* move the state to CANCEL */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - - } else { - - /* fill in cid/ani number */ - if (siConEvnt->cgPtyNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->cgPtyNum.addrSig, - ftdmchan->caller_data.cid_num.digits, - siConEvnt->cgPtyNum.oddEven); - - /* fill in cid Name */ - ftdm_set_string(ftdmchan->caller_data.cid_name, ftdmchan->caller_data.cid_num.digits); - - ftdm_set_string(ftdmchan->caller_data.ani.digits, ftdmchan->caller_data.cid_num.digits); - - } else { - SS7_INFO("No Calling party (ANI) information in IAM!\n"); - } - - /* fill in dnis */ - if (siConEvnt->cdPtyNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->cdPtyNum.addrSig, - ftdmchan->caller_data.dnis.digits, - siConEvnt->cdPtyNum.oddEven); - } else { - SS7_INFO("No Called party (DNIS) information in IAM!\n"); - } - - /* fill in rdnis */ - if (siConEvnt->redirgNum.addrSig.pres) { - copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig, - ftdmchan->caller_data.rdnis.digits, - siConEvnt->cgPtyNum.oddEven); - } else { - SS7_INFO("No RDNIS party information in IAM!\n"); - } - - /* fill in screening/presentation */ - ftdmchan->caller_data.screen = siConEvnt->cgPtyNum.scrnInd.val; - ftdmchan->caller_data.pres = siConEvnt->cgPtyNum.presRest.val; - - /* set the state of the channel to collecting...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); - - } /* if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) */ - - break; - /**************************************************************************/ - case (FTDM_CHANNEL_STATE_DIALING): /* glare */ - SS7_ERROR("Got IAM in DIALING state...glare!\n"); - - /* the flag the channel as having a collision */ - sngss7_set_flag(sngss7_info, FLAG_GLARE); - - /* save the IAM for processing once the channel has gone to DOWN */ - memcpy(&sngss7_info->glare.iam, siConEvnt, sizeof(*siConEvnt)); - sngss7_info->glare.suInstId = suInstId; - sngss7_info->glare.spInstId = spInstId; - sngss7_info->glare.circuit = circuit; - SS7_DEBUG("Queuing incoming cal request on Circuit = %d (CIC # %d\n", - sngss7_info->glare.circuit, - sngss7_info->circuit->cic); - - break; - /**************************************************************************/ - default: /* should not have gotten an IAM while in this state */ - SS7_ERROR("Got IAM in an invalid state (%s) on span=%d, chan=%d!\n", - ftdm_channel_state2str(ftdmchan->state), - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); - - /* move the state of the channel to RESTART to force a reset */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) */ - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } /******************************************************************************/ void sngss7_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); + SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - } + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - }; + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_CON_CFM_EVENT; + memcpy(&sngss7_event->event.siConEvnt, siConEvnt, sizeof(*siConEvnt)); - SS7_MSG_TRACE("Received ANM on CIC # %d\n", sngss7_info->circuit->cic); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - - /* go to UP */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP); - - break; - /**************************************************************************/ - default: /* incorrect state...reset the CIC */ - - /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - - break; - /**************************************************************************/ - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } /******************************************************************************/ void sngss7_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); + SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - } + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - } + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->evntType = evntType; + sngss7_event->event_id = SNGSS7_CON_STA_EVENT; + memcpy(&sngss7_event->event.siCnStEvnt, siCnStEvnt, sizeof(*siCnStEvnt)); - switch (evntType) { - /**************************************************************************/ - case (ADDRCMPLT): - SS7_MSG_TRACE("Received ACM on CIC # %d\n", sngss7_info->circuit->cic); - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - /* KONRAD: should we confirm the instance ids ? */ + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); - /* need to grab the sp instance id */ - sngss7_info->spInstId = spInstId; - - /* go to PROGRESS */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - break; - /**********************************************************************/ - default: /* incorrect state...reset the CIC */ - /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); - break; - /**********************************************************************/ - } /* switch (ftdmchan->state) */ - /**************************************************************************/ - case (MODIFY): - SS7_MSG_TRACE("Received MODIFY on CIC # %d\n", sngss7_info->circuit->cic); - break; - /**************************************************************************/ - case (MODCMPLT): - SS7_MSG_TRACE( "Received MODIFY_COMPLETE on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (MODREJ): - SS7_MSG_TRACE( "Received MODIFY_REJECT on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (PROGRESS): - SS7_MSG_TRACE( "Received CPG on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (FRWDTRSFR): - SS7_MSG_TRACE( "Received FOT on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (INFORMATION): - SS7_MSG_TRACE( "Received INF on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (INFORMATREQ): - SS7_MSG_TRACE( "Received INR on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (SUBSADDR): - SS7_MSG_TRACE( "Received SAM on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (EXIT): - SS7_MSG_TRACE( "Received EXIT on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (NETRESMGT): - SS7_MSG_TRACE( "Received NRM on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (IDENTREQ): - SS7_MSG_TRACE( "Received IDR on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (IDENTRSP): - SS7_MSG_TRACE( "Received IRS on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (MALCLLPRNT): - SS7_MSG_TRACE( "Received MALICIOUS CALL on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (CHARGE): - SS7_MSG_TRACE( "Received CRG on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (TRFFCHGE): - SS7_MSG_TRACE( "Received CRG-Tariff Change on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (CHARGEACK): - SS7_MSG_TRACE( "Received CRG-Acknowledge on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (CALLOFFMSG): - SS7_MSG_TRACE( "Received CALL_OFFER on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (LOOPPRVNT): - SS7_MSG_TRACE( "Received LOP on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (TECT_TIMEOUT): - SS7_MSG_TRACE( "Received ECT Timeout on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (RINGSEND): - SS7_MSG_TRACE( "Received Ringing Send on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (CALLCLEAR): - SS7_MSG_TRACE( "Received Call_Line_clear on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (PRERELEASE): - SS7_MSG_TRACE( "Received PRI on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (APPTRANSPORT): - SS7_MSG_TRACE( "Received APM on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (OPERATOR): - SS7_MSG_TRACE( "Received Operator on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (METPULSE): - SS7_MSG_TRACE( "Received Metering Pulse on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (CLGPTCLR): - SS7_MSG_TRACE( "Received Calling_Party_Clear on circuit # %d\n", circuit); - break; - /**************************************************************************/ - case (SUBDIRNUM): - SS7_MSG_TRACE( "Received subsequent directory number on circuit # %d\n", circuit); - break; - /**************************************************************************/ - default: - ftdm_log(FTDM_LOG_ERROR, "Received Unknown message on circuit # %d\n", circuit); - break; - /**************************************************************************/ - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } /******************************************************************************/ void sngss7_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); + SS7_FUNC_TRACE_ENTER(__FUNCTION__); - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - } + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - }; + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_REL_IND_EVENT; + memcpy(&sngss7_event->event.siRelEvnt, siRelEvnt, sizeof(*siRelEvnt)); - SS7_MSG_TRACE("Received REL on CIC # %d\n", sngss7_info->circuit->cic); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); - /* check whether the ftdm channel is in a state to release a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RING: - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: - - /* pass the release code up to FTDM */ - if (siRelEvnt->causeDgn.causeVal.pres) { - ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; - } else { - SS7_ERROR("REL does not have a cause code!\n"); - ftdmchan->caller_data.hangup_cause = 0; - } - - /* move the state of the channel to TERMINATING to end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - - /* pass the release code up to FTDM */ - if (siRelEvnt->causeDgn.causeVal.pres) { - ftdmchan->caller_data.hangup_cause = siRelEvnt->causeDgn.causeVal.val; - } else { - SS7_ERROR("REL does not have a cause code!\n"); - ftdmchan->caller_data.hangup_cause = 0; - } - - /* move the state of the channel to TERMINATING to end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - - break; - /**************************************************************************/ - default: - - /* fill in the channels SS7 Stack information */ - sngss7_info->suInstId = get_unique_id(); - sngss7_info->spInstId = spInstId; - - /* throw the reset flag */ - sngss7_set_flag(sngss7_info, FLAG_RESET_RX); - - /* set the state to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } /* switch (ftdmchan->state) */ - - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } - /******************************************************************************/ void sngss7_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info ; - ftdm_channel_t *ftdmchan; + SS7_FUNC_TRACE_ENTER(__FUNCTION__); - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - } + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; - }; + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); - SS7_MSG_TRACE("Received RLC on CIC # %d\n", sngss7_info->circuit->cic); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_REL_CFM_EVENT; + memcpy(&sngss7_event->event.siRelEvnt, siRelEvnt, sizeof(*siRelEvnt)); - /* check whether the ftdm channel is in a state to accept a call */ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); - /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - /* do nothing, just drop the message */ - break; - /**************************************************************************/ - default: - /* KONRAD: should just stop the call...but a reset is easier for now (since it does hangup the call) */ - - /* go to RESTART */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - break; - /**************************************************************************/ - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } /******************************************************************************/ void sngss7_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - SS7_MSG_TRACE( "Received DATA indication on circuit # %d\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); + + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_DAT_IND_EVENT; + memcpy(&sngss7_event->event.siInfoEvnt, siInfoEvnt, sizeof(*siInfoEvnt)); + + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } /******************************************************************************/ void sngss7_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - SS7_MSG_TRACE( "Received FAC request on circuit # %d\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); + + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->evntType = evntType; + sngss7_event->event_id = SNGSS7_FAC_IND_EVENT; + memcpy(&sngss7_event->event.siFacEvnt, siFacEvnt, sizeof(*siFacEvnt)); + + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } /******************************************************************************/ void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - SS7_MSG_TRACE( "Received FAC confirm on circuit # %d\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); + + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->evntType = evntType; + sngss7_event->event_id = SNGSS7_FAC_CFM_EVENT; + memcpy(&sngss7_event->event.siFacEvnt, siFacEvnt, sizeof(*siFacEvnt)); + + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } /******************************************************************************/ void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); + SS7_FUNC_TRACE_ENTER(__FUNCTION__); - SS7_MSG_TRACE( "Received User to User message on circuit # %d\n", circuit); + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); + + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->event_id = SNGSS7_UMSG_IND_EVENT; + + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); + + SS7_FUNC_TRACE_EXIT(__FUNCTION__); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; } - /* GENERAL STATUS *************************************************************/ void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) { - SS7_FUNC_TRACE_ENTER(__FUNCTION__); + SS7_FUNC_TRACE_ENTER(__FUNCTION__); - SS7_MSG_TRACE("[SNG-CC] Received %s indicaton on cic = %d\n", - DECODE_LCC_EVENT(evntType), - g_ftdm_sngss7_data.cfg.isupCircuit[circuit].cic); + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sngss7_event_data_t *sngss7_event = NULL; - switch (evntType) { - /**************************************************************************/ - case SIT_STA_REATTEMPT: /* reattempt indication */ - handle_reattempt(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_ERRORIND: /* error indication */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CONTCHK: /* continuity check */ - handle_cot_start(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CONTREP: /* continuity report */ - handle_cot(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_STPCONTIN: /* stop continuity */ - handle_cot_stop(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CGQRYRSP: /* circuit grp query response from far end forwarded to upper layer by ISUP */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CONFUSION: /* confusion */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LOOPBACKACK: /* loop-back acknowledge */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRRSRVREQ: /* circuit reservation request */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRRSRVACK: /* circuit reservation acknowledgement */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRBLOREQ: /* circuit blocking request */ - handle_blo_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRBLORSP: /* circuit blocking response */ - handle_blo_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUBLREQ: /* circuit unblocking request */ - handle_ubl_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUBLRSP: /* circuit unblocking response */ - handle_ubl_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRRESREQ: /* circuit reset request - RSC */ - handle_rsc_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCRES: /* reset initiated locally by the software */ - handle_local_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRRESRSP: /* circuit reset response */ - handle_rsc_rsp(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CGBREQ: /* CGB request */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGUREQ: /* CGU request */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGQRYREQ: /* circuit group query request */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGBRSP: /* mntc. oriented CGB response */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGURSP: /* mntc. oriented CGU response */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_GRSREQ: /* circuit group reset request */ - handle_grs_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_CIRUNEQPD: /* circuit unequipped indication */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_GRSRSP: /* circuit group reset response */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_PAUSEIND: /* pause indication */ - handle_pause(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_RESUMEIND: /* resume indication */ - handle_resume(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); - break; - /**************************************************************************/ - case SIT_STA_USRPARTA: /* user part available */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_RMTUSRUNAV: /* remote user not available */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG0: /* congestion indication level 0 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG1: /* congestion indication level 1 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG2: /* congestion indication level 2 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPCONG3: /* congestion indication level 3 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_MTPSTPCONG: /* stop congestion indication level 0 */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCALBLOIND: /* Mngmt local blocking */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCALUBLIND: /* Mngmt local unblocking */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_OVERLOAD: /* Overload */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMCGBREQ: /* when LM requests ckt grp blocking */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMCGUREQ: /* when LM requests ckt grp unblocking */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMGRSREQ: /* when LM requests ckt grp reset */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_CIRLOCGRS: /* group reset initiated locally by the software */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_GRSRSPIND: /* indication to IW to idle the RM */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - case SIT_STA_RLCIND: /* RLC indicattion to IW to idle the RM */ - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); - break; - /**************************************************************************/ - default: - SS7_INFO("[SNG-CC] Received Unknown indication %d\n", evntType); - break; - } /* switch (evntType) */ - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return; -} - -/******************************************************************************/ -static ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for ISUP circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* glare, throw the flag, go to down state*/ - sngss7_set_flag(sngss7_info, FLAG_GLARE); - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int infId; - int i; - - /* extract the affect infId from the circuit structure */ - infId = g_ftdm_sngss7_data.cfg.isupCircuit[circuit].infId; - - /* go through all the circuits now and find any other circuits on this infId */ - i = 1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) { - - /* check that the infId matches and that this is not a siglink */ - if ((g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) && - (g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0)) { - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - i++; - continue; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - i++; - continue; - }; - - /* set the pause flag on the channel */ - sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED); - - /* set the statet o SUSPENDED to bring the sig status down */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* if (g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) */ - - /* move to the next circuit */ - i++; - - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) */ - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int infId; - int i; - - /* extract the affect infId from the circuit structure */ - infId = g_ftdm_sngss7_data.cfg.isupCircuit[circuit].infId; - - /* go through all the circuits now and find any other circuits on this infId */ - i = 1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) { - - /* check that the infId matches and that this is not a siglink */ - if ((g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) && - (g_ftdm_sngss7_data.cfg.isupCircuit[i].siglink == 0)) { - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - i++; - continue; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - i++; - continue; - }; - - /* set the resume flag on the channel */ - sngss7_set_flag(sngss7_info, FLAG_INFID_RESUME); - - /* clear the paused flag */ - sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED); - - /* set the statet to SUSPENDED to bring the sig status up */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - } /* if (g_ftdm_sngss7_data.cfg.isupCircuit[i].infId == infId) */ - - /* move to the next circuit */ - i++; - - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[i].id != 0) */ - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* open the channel if it is not open */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) { - SS7_ERROR("Failed to open CIC %d for COT test!\n", sngss7_info->circuit->cic); - /* KONRAD FIX ME */ - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - } - - /* tell the core to loop the channel */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_ENABLE_LOOP, NULL); - - /* switch to the IN_LOOP state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IN_LOOP); - - /* store the sngss7 ids */ - if (suInstId == 0) { - sngss7_info->suInstId = get_unique_id(); - } else { - sngss7_info->suInstId = suInstId; - } - sngss7_info->spInstId = spInstId; - sngss7_info->globalFlg = globalFlg; - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* tell the core to stop looping the channel */ - ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL); - - /* exit out of the LOOP state to the last state */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - if ( (siStaEvnt->contInd.eh.pres > 0) && (siStaEvnt->contInd.contInd.pres > 0)) { - SS7_INFO("Continuity Test result for CIC = %d (span %d, chan %d) is: \"%s\"\n", - g_ftdm_sngss7_data.cfg.isupCircuit[circuit].cic, - g_ftdm_sngss7_data.cfg.isupCircuit[circuit].span, - g_ftdm_sngss7_data.cfg.isupCircuit[circuit].chan, - (siStaEvnt->contInd.contInd.val) ? "PASS" : "FAIL"); - } else { - SS7_ERROR("Recieved Continuity report containing no results!\n"); - } - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - /* since we are already in RESTART, the channel is already free... - * just waitng for the other side to clean up it's channel. - * just send an acknowledge to this reset, don't go through the master - * state handler....bad but... - */ - - sngss7_info->spInstId = 0; - sngss7_info->suInstId = 0; - sngss7_info->globalFlg = globalFlg; - - ft_to_sngss7_rsca(ftdmchan); - break; - /**************************************************************************/ - default: - /* throw the channels RESET_RX flag */ - sngss7_set_flag(sngss7_info, FLAG_RESET_RX); - - sngss7_info->spInstId = 0; - sngss7_info->suInstId = 0; - sngss7_info->globalFlg = globalFlg; - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - break; - /**************************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_local_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* the stack is sending out a RSC for us */ - sngss7_set_flag(sngss7_info, FLAG_RESET_RX); - - sngss7_info->spInstId = 0; - sngss7_info->suInstId = 0; - sngss7_info->globalFlg = globalFlg; - - /* set the state of the channel to restart...the rest is done by the chan monitor */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - switch (ftdmchan->state) { - /**********************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: - - /* 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_TERMINATING: - case FTDM_CHANNEL_STATE_HANGUP: - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /**********************************************************************/ - /* go to DOWN */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - break; - /**********************************************************************/ - default: - /* ITU Q764-2.9.5.1.c -> release the circuit */ - if ((siStaEvnt != NULL) && - (siStaEvnt->causeDgn.eh.pres ==PRSNT_NODEF) && - (siStaEvnt->causeDgn.causeVal.pres == PRSNT_NODEF)) { - ftdmchan->caller_data.hangup_cause = siStaEvnt->causeDgn.causeVal.val; - } else { - ftdmchan->caller_data.hangup_cause = 98; /* Message not compatiable with call state */ - } - - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /**********************************************************************/ - } - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* check if the circuit is already blocked or not */ - if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { - SS7_WARN("Received BLO on circuit that is already blocked!\n"); - } - - /* throw the ckt block flag */ - sngss7_set_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* KONRAD FIX ME */ - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* check if the channel is blocked */ - if (!(sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX))) { - SS7_WARN("Received UBL on circuit that is not blocked!\n"); - } - - /* throw the unblock flag */ - sngss7_set_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); - - /* clear the block flag */ - sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX); - - /* set the channel to suspended state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* KONRAD FIX ME */ - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} - -/******************************************************************************/ -static ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); - - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - int range; - int x; - - /* extract the range value from the event structure */ - if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { - range = siStaEvnt->rangStat.range.val; - } else { - SS7_ERROR("Received GRS with no range value on CIC = %d\n", sngss7_info->circuit->cic); + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* loop over the cics starting from circuit until range+1 */ - for (x = circuit; x < (circuit + range + 1); x++) { - /* grab the circuit in question */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - /* konrad fix me */ - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - /* konrad fix me */ - }; - - /* store the circuit and range into the sngss7 info so that we can figure out when to send GRA */ - sngss7_info->grs.circuit = circuit; - sngss7_info->grs.range = range; - sngss7_info->globalFlg = globalFlg; - - /* flag the channel as having received a reset */ - sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX); - - /* throw the channel into RESTART state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - + return; } - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; -} + /* initalize the sngss7_event */ + sngss7_event = ftdm_malloc(sizeof(*sngss7_event)); + if (sngss7_event == NULL) { + SS7_ERROR("Failed to allocate memory for sngss7_event!\n"); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return; + } + memset(sngss7_event, 0x0, sizeof(*sngss7_event)); + /* fill in the sngss7_event struct */ + sngss7_event->spInstId = spInstId; + sngss7_event->suInstId = suInstId; + sngss7_event->circuit = circuit; + sngss7_event->globalFlg = globalFlg; + sngss7_event->evntType = evntType; + sngss7_event->event_id = SNGSS7_STA_IND_EVENT; + if (siStaEvnt != NULL) { + memcpy(&sngss7_event->event.siStaEvnt, siStaEvnt, sizeof(*siStaEvnt)); + } -/******************************************************************************/ -#if 0 -{ - SS7_FUNC_TRACE_ENTER(__FUNCTION__); + /* enqueue this event */ + ftdm_queue_enqueue(((sngss7_span_data_t*)sngss7_info->ftdmchan->span->mod_data)->event_queue, sngss7_event); - sngss7_chan_data_t *sngss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - - /* get the ftdmchan and ss7_chan_data from the circuit */ - if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - } - - /* now that we have the right channel...put a lock on it so no-one else can use it */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; - - /* fill in here */ - - /* unlock the channel again before we exit */ - ftdm_mutex_unlock(ftdmchan->mutex); - - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_SUCCESS; + SS7_FUNC_TRACE_EXIT(__FUNCTION__); } /******************************************************************************/ -#endif -/******************************************************************************/ + /******************************************************************************/ /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c new file mode 100644 index 0000000000..b666f726a1 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c @@ -0,0 +1,592 @@ +/* + * Copyright (c) 2009|Konrad Hammel + * All rights reserved. + * + * Redistribution and use in source and binary forms|with or without + * modification|are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice|this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice|this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT + * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, + * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* INCLUDE ********************************************************************/ +#include "ftmod_sangoma_ss7_main.h" +/******************************************************************************/ + +/* DEFINES ********************************************************************/ +/******************************************************************************/ + +/* GLOBALS ********************************************************************/ +/******************************************************************************/ + +/* PROTOTYPES *****************************************************************/ +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: + */ +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 7259931ca7..66efe1ab12 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -39,1206 +39,1524 @@ /******************************************************************************/ /* GLOBALS ********************************************************************/ -static sng_isup_event_interface_t sng_event; -static ftdm_io_interface_t g_ftdm_sngss7_interface; -ftdm_sngss7_data_t g_ftdm_sngss7_data; -ftdm_sched_t *sngss7_sched; +static sng_isup_event_interface_t sng_event; +static ftdm_io_interface_t g_ftdm_sngss7_interface; +ftdm_sngss7_data_t g_ftdm_sngss7_data; /******************************************************************************/ /* PROTOTYPES *****************************************************************/ -static void *ftdm_sangoma_ss7_run(ftdm_thread_t *me, void *obj); -static void ftdm_sangoma_ss7_process_state_change(ftdm_channel_t *ftdmchan); +static void *ftdm_sangoma_ss7_run (ftdm_thread_t * me, void *obj); +static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t *ftdmchan); +static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event); -static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t *span); -static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t *span); +static ftdm_status_t ftdm_sangoma_ss7_stop (ftdm_span_t * span); +static ftdm_status_t ftdm_sangoma_ss7_start (ftdm_span_t * span); /******************************************************************************/ /* STATE MAP ******************************************************************/ ftdm_state_map_t sangoma_ss7_state_map = { - { - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_ANY_STATE, FTDM_END}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_CANCEL, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING, - FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_END}, - {FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}, - {FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RING, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_END} - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}, - }, - { - ZSD_INBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - }, - /**************************************************************************/ - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_ANY_STATE, FTDM_END}, - {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_RESTART, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_CANCEL, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_DIALING, - FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, - FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - {FTDM_CHANNEL_STATE_DIALING, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_DIALING, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_CANCEL, FTDM_END} - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_UP, FTDM_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_UP, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}, - }, - { - ZSD_OUTBOUND, - ZSM_UNACCEPTABLE, - {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}, - {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, - } - } + { + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}, + {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_DOWN, + FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_COLLECT, + FTDM_CHANNEL_STATE_RING, FTDM_CHANNEL_STATE_PROGRESS, + FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, + FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING, + FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_RESTART, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, + FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, + FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_IDLE, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_IDLE, FTDM_END}, + {FTDM_CHANNEL_STATE_RESTART, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_COLLECT, FTDM_CHANNEL_STATE_DOWN, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_COLLECT, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_RING, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_RING, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_PROGRESS, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_UP, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_UP, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_CANCEL, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_HANGUP, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_HANGUP, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} + }, + { + ZSD_INBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_DOWN, FTDM_END} + }, + /**************************************************************************/ + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_END}, + {FTDM_CHANNEL_STATE_RESTART, FTDM_CHANNEL_STATE_DOWN, + FTDM_CHANNEL_STATE_IN_LOOP, FTDM_CHANNEL_STATE_DIALING, + FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_PROGRESS_MEDIA, + FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_CANCEL, + FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_RESTART, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_TERMINATING, + FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_HANGUP_COMPLETE, + FTDM_CHANNEL_STATE_DOWN, FTDM_CHANNEL_STATE_IDLE, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_IDLE, FTDM_END}, + {FTDM_CHANNEL_STATE_RESTART, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_DOWN, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_IN_LOOP, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_DIALING, FTDM_CHANNEL_STATE_DOWN, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_DIALING, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_CANCEL, FTDM_CHANNEL_STATE_TERMINATING, + FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, + FTDM_CHANNEL_STATE_UP, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROGRESS, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, + FTDM_CHANNEL_STATE_UP, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_UP, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_CANCEL, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_HANGUP, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_HANGUP, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_HANGUP, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END} + }, + { + ZSD_OUTBOUND, + ZSM_UNACCEPTABLE, + {FTDM_CHANNEL_STATE_HANGUP_COMPLETE, FTDM_END}, + {FTDM_CHANNEL_STATE_SUSPENDED, FTDM_CHANNEL_STATE_RESTART, + FTDM_CHANNEL_STATE_DOWN, FTDM_END} + }, + } }; + /******************************************************************************/ /* MONITIOR THREADS ***********************************************************/ -static void *ftdm_sangoma_ss7_run(ftdm_thread_t *me, void *obj) +static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) { - ftdm_interrupt_t *ftdm_sangoma_ss7_int = NULL; - ftdm_span_t *span = (ftdm_span_t *) obj; - ftdm_channel_t *ftdmchan = NULL; + ftdm_interrupt_t *ftdm_sangoma_ss7_int[2]; + ftdm_span_t *ftdmspan = (ftdm_span_t *) obj; + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_event_data_t *sngss7_event = NULL; + sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data; + int i; - ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", span->span_id); + ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id); - /* set IN_THREAD flag so that we know this thread is running */ - ftdm_set_flag(span, FTDM_SPAN_IN_THREAD); + /* set IN_THREAD flag so that we know this thread is running */ + ftdm_set_flag (ftdmspan, FTDM_SPAN_IN_THREAD); - /* get an interrupt queue for this span */ - if(ftdm_queue_get_interrupt(span->pendingchans, &ftdm_sangoma_ss7_int) != FTDM_SUCCESS) { - SS7_CRITICAL("Failed to get a ftdm_interrupt for span = %d!\n", span->span_id); - goto ftdm_sangoma_ss7_run_exit; - } + /* get an interrupt queue for this span for channel state changes */ + if (ftdm_queue_get_interrupt (ftdmspan->pendingchans, &ftdm_sangoma_ss7_int[0]) != FTDM_SUCCESS) { + SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for channel state changes!\n", ftdmspan->span_id); + goto ftdm_sangoma_ss7_run_exit; + } - while (ftdm_running() && !(ftdm_test_flag(span, FTDM_SPAN_STOP_THREAD))) { + /* get an interrupt queue for this span for Trillium events */ + if (ftdm_queue_get_interrupt (sngss7_span->event_queue, &ftdm_sangoma_ss7_int[1]) != FTDM_SUCCESS) { + SS7_CRITICAL ("Failed to get a ftdm_interrupt for span = %d for Trillium event queue!\n", ftdmspan->span_id); + goto ftdm_sangoma_ss7_run_exit; + } - /* find out why we returned from the interrupt queue */ - switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) { - /**********************************************************************/ - case FTDM_SUCCESS: /* there was a state change on the span */ - /* process all pending state changes */ - while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) { - /* double check that this channel has a state change pending */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - ftdm_sangoma_ss7_process_state_change(ftdmchan); - } else { - SS7_ERROR("ftdm_core reported state change, but state change flag not set on ft-span = %d, ft-chan = %d\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); - } - } /* while ((ftdmchan = ftdm_queue_dequeue(span->pendingchans))) */ + while (ftdm_running () && !(ftdm_test_flag (ftdmspan, FTDM_SPAN_STOP_THREAD))) { - break; - /**********************************************************************/ - case FTDM_TIMEOUT: - SS7_DEVEL_DEBUG("ftdm_interrupt_wait timed-out on span = %d\n", span->span_id); - break; - /**********************************************************************/ - case FTDM_FAIL: - SS7_ERROR("ftdm_interrupt_wait returned error!\non span = %d\n", span->span_id); - break; - /**********************************************************************/ - default: - SS7_ERROR("ftdm_interrupt_wait returned with unknown code on span = %d\n", span->span_id); - break; - /**********************************************************************/ - } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */ + /* check the channel state queue for an event*/ + switch ((ftdm_interrupt_multiple_wait(ftdm_sangoma_ss7_int, 2, 100))) { + /**********************************************************************/ + case FTDM_SUCCESS: /* process all pending state changes */ - } /* master while loop */ + /* clean out all pending channel state changes */ + while ((ftdmchan = ftdm_queue_dequeue (ftdmspan->pendingchans))) { + + /*first lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); - /* clear the IN_THREAD flag so that we know the thread is done */ - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); + /* process state changes for this channel until they are all done */ + while (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_ss7_process_state_change (ftdmchan); + } + + /* unlock the channel */ + ftdm_mutex_unlock (ftdmchan->mutex); + }/* while ((ftdmchan = ftdm_queue_dequeue(ftdmspan->pendingchans))) */ - ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u stopping.\n", span->span_id); + /* clean out all pending stack events */ + while ((sngss7_event = ftdm_queue_dequeue(sngss7_span->event_queue))) { + ftdm_sangoma_ss7_process_stack_event(sngss7_event); + ftdm_safe_free(sngss7_event); + }/* while ((sngss7_event = ftdm_queue_dequeue(ftdmspan->signal_data->event_queue))) */ - return NULL; + /* signal the core that sig events are queued for processing */ + ftdm_span_trigger_signals(ftdmspan); + + break; + /**********************************************************************/ + case FTDM_TIMEOUT: + SS7_DEVEL_DEBUG ("ftdm_interrupt_wait timed-out on span = %d\n",ftdmspan->span_id); + + break; + /**********************************************************************/ + case FTDM_FAIL: + SS7_ERROR ("ftdm_interrupt_wait returned error!\non span = %d\n", ftdmspan->span_id); + + break; + /**********************************************************************/ + default: + SS7_ERROR("ftdm_interrupt_wait returned with unknown code on span = %d\n",ftdmspan->span_id); + + break; + /**********************************************************************/ + } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */ + + /* extract the span data structure */ + sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data; + + /* check if there is a GRS being processed on the span */ + if (sngss7_span->rx_grs.range > 0) { + ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id); + /*SS7_DEBUG("Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);*/ + + /* check all the circuits in the range to see if they are done resetting */ + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + SS7_ASSERT; + } + + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a state change pending on the channel */ + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + /* check the state to the GRP_RESET_RX_DN flag */ + if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) { + /* this channel is still resetting...do nothing */ + goto GRS_UNLOCK_ALL; + } /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */ + } else { + /* state change pending */ + goto GRS_UNLOCK_ALL; + } + } /* for ( i = circuit; i < (circuit + range + 1); i++) */ + + SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", + sngss7_span->rx_grs.circuit, + sngss7_span->rx_grs.range); + + /* check all the circuits in the range to see if they are done resetting */ + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i); + SS7_ASSERT; + } + + /* throw the GRP reset flag complete flag */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); + + /* move the channel to the down state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + } /* for ( i = circuit; i < (circuit + range + 1); i++) */ + +GRS_UNLOCK_ALL: + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + SS7_ASSERT; + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + } + + } /* if (ftdmspan->grs.range > 0) */ + } /* master while loop */ + + /* clear the IN_THREAD flag so that we know the thread is done */ + ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD); + + ftdm_log (FTDM_LOG_INFO,"ftmod_sangoma_ss7 monitor thread for span=%u stopping.\n",ftdmspan->span_id); + + return NULL; ftdm_sangoma_ss7_run_exit: - /* clear the IN_THREAD flag so that we know the thread is done */ - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); + /* clear the IN_THREAD flag so that we know the thread is done */ + ftdm_clear_flag (ftdmspan, FTDM_SPAN_IN_THREAD); - ftdm_log(FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u stopping due to error.\n", span->span_id); + ftdm_log (FTDM_LOG_INFO,"ftmod_sangoma_ss7 monitor thread for span=%u stopping due to error.\n",ftdmspan->span_id); - ftdm_sangoma_ss7_stop(span); + ftdm_sangoma_ss7_stop (ftdmspan); - return NULL; + return NULL; } /******************************************************************************/ -static void ftdm_sangoma_ss7_process_state_change(ftdm_channel_t *ftdmchan) +static void ftdm_sangoma_ss7_process_stack_event (sngss7_event_data_t *sngss7_event) { - ftdm_sigmsg_t sigev; - ftdm_signaling_status_t status; - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - sngss7_chan_data_t *tmp_ss7info = NULL; - ftdm_channel_t *tmp_chan = NULL; - int i = 0; + sngss7_chan_data_t *sngss7_info ; + ftdm_channel_t *ftdmchan; - memset(&sigev, 0, sizeof(sigev)); + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(sngss7_event->circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", sngss7_event->circuit); + return; + } - sigev.chan_id = ftdmchan->chan_id; - sigev.span_id = ftdmchan->span_id; - sigev.channel = ftdmchan; + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); - /*first lock the channel*/ - ftdm_mutex_lock(ftdmchan->mutex); + /* while there's a state change present on this channel process it */ + while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_ss7_process_state_change(ftdmchan); + } - /*clear the state change flag...since we might be setting a new state*/ - ftdm_clear_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE); + /* figure out the type of event and send it to the right handler */ + switch (sngss7_event->event_id) { + /**************************************************************************/ + case (SNGSS7_CON_IND_EVENT): + handle_con_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siConEvnt); + break; + /**************************************************************************/ + case (SNGSS7_CON_CFM_EVENT): + handle_con_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siConEvnt); + break; + /**************************************************************************/ + case (SNGSS7_CON_STA_EVENT): + handle_con_sta(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siCnStEvnt, sngss7_event->evntType); + break; + /**************************************************************************/ + case (SNGSS7_REL_IND_EVENT): + handle_rel_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt); + break; + /**************************************************************************/ + case (SNGSS7_REL_CFM_EVENT): + handle_rel_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siRelEvnt); + break; + /**************************************************************************/ + case (SNGSS7_DAT_IND_EVENT): + handle_dat_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, &sngss7_event->event.siInfoEvnt); + break; + /**************************************************************************/ + case (SNGSS7_FAC_IND_EVENT): + handle_fac_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType, &sngss7_event->event.siFacEvnt); + break; + /**************************************************************************/ + case (SNGSS7_FAC_CFM_EVENT): + handle_fac_cfm(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->evntType, &sngss7_event->event.siFacEvnt); + break; + /**************************************************************************/ + case (SNGSS7_UMSG_IND_EVENT): + handle_umsg_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit); + break; + /**************************************************************************/ + case (SNGSS7_STA_IND_EVENT): + handle_sta_ind(sngss7_event->suInstId, sngss7_event->spInstId, sngss7_event->circuit, sngss7_event->globalFlg, sngss7_event->evntType, &sngss7_event->event.siStaEvnt); + break; + /**************************************************************************/ + default: + SS7_ERROR("Unknown Event Id!\n"); + break; + /**************************************************************************/ + } /* switch (sngss7_event->event_id) */ - /*check what state we are supposed to be in*/ - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_COLLECT: /* IAM received but wating on digits */ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + /* while there's a state change present on this channel process it */ + while (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + ftdm_sangoma_ss7_process_state_change(ftdmchan); + } - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); - while (ftdmchan->caller_data.cid_num.digits[i] != '\0') { - i++; - } + return; +} - /* check if the end of pulsing character has arrived or the right number of digits */ - if (ftdmchan->caller_data.cid_num.digits[i] == 0xF) { - SS7_DEBUG("Received the end of pulsing character\n"); +/******************************************************************************/ +static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) +{ + ftdm_sigmsg_t sigev; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + int i = 0; - /*now go to the RING state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - } else if (i >= g_ftdm_sngss7_data.min_digits) { - SS7_DEBUG("Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits); + memset (&sigev, 0, sizeof (sigev)); - /*now go to the RING state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RING); - } else { - SS7_INFO("Received %d out of %d so far: %s...starting T35\n", - i, - g_ftdm_sngss7_data.min_digits, - ftdmchan->caller_data.cid_num.digits); + sigev.chan_id = ftdmchan->chan_id; + sigev.span_id = ftdmchan->span_id; + sigev.channel = ftdmchan; - /* start ISUP t35 */ - if (ftdm_sched_timer(sngss7_info->t35.sched, - "t35", - sngss7_info->t35.beat, - sngss7_info->t35.callback, - &sngss7_info->t35, - &sngss7_info->t35.heartbeat_timer)) { + SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state)); - SS7_ERROR("Unable to schedule timer, hanging up call!\n"); + /* clear the state change flag...since we might be setting a new state */ + ftdm_clear_flag (ftdmchan, FTDM_CHANNEL_STATE_CHANGE); + + /*check what state we are supposed to be in */ + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_COLLECT: /* IAM received but wating on digits */ - ftdmchan->caller_data.hangup_cause = 41; + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL); + while (ftdmchan->caller_data.dnis.digits[i] != '\0'){ + i++; + } - /* end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - } else { - if(ftdm_sched_free_run(sngss7_info->t35.sched)) { - SS7_ERROR("Unable to run timer, hanging up call!\n"); + /* check if the end of pulsing character has arrived or the right number of digits */ + if (ftdmchan->caller_data.dnis.digits[i] == 0xF) { + SS7_DEBUG_CHAN(ftdmchan, "Received the end of pulsing character %s\n", ""); - ftdmchan->caller_data.hangup_cause = 41; + /*now go to the RING state */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); + + } else if (i >= g_ftdm_sngss7_data.min_digits) { + SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits); - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL); + /*now go to the RING state */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); + + } else { + SS7_INFO_CHAN(ftdmchan,"Received %d out of %d so far: %s...starting T35\n", + i, + g_ftdm_sngss7_data.min_digits, + ftdmchan->caller_data.dnis.digits); - /* end the call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); - } /* if(ftdm_sched_free_run(sngss7_info->t35.sched)) */ - } /* if (ftdm_sched_timer(sngss7_info->t35.sched, */ + /* start ISUP t35 */ + if (ftdm_sched_timer (sngss7_info->t35.sched, + "t35", + sngss7_info->t35.beat, + sngss7_info->t35.callback, + &sngss7_info->t35, + &sngss7_info->t35.heartbeat_timer)) { - } /* checking ST/#digits */ + SS7_ERROR ("Unable to schedule timer, hanging up call!\n"); - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RING: /*incoming call request*/ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + ftdmchan->caller_data.hangup_cause = 41; - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + /* set the flag to indicate this hangup is started from the local side */ + sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL); + + /* end the call */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_CANCEL); + } /* if (ftdm_sched_timer(sngss7_info->t35.sched, */ + } /* checking ST/#digits */ + + break; + + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RING: /*incoming call request */ + + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } /* kill t35 if active */ if (sngss7_info->t35.heartbeat_timer) { - ftdm_sched_cancel_timer(sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer); - } + ftdm_sched_cancel_timer (sngss7_info->t35.sched,&sngss7_info->t35.heartbeat_timer); + } + + SS7_DEBUG_CHAN(ftdmchan, "Sending incoming call from %s to %s to FTDM core\n", + ftdmchan->caller_data.ani.digits, + ftdmchan->caller_data.dnis.digits); + /* we have enough information to inform FTDM of the call */ + sigev.event_id = FTDM_SIGEVENT_START; + ftdm_span_send_signal (ftdmchan->span, &sigev); - SS7_DEBUG("Sending incoming call from %s to %s to FTDM core\n", - ftdmchan->caller_data.ani.digits, - ftdmchan->caller_data.dnis.digits); + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DIALING: /*outgoing call request */ + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - /* we have enough information to inform FTDM of the call*/ - sigev.event_id = FTDM_SIGEVENT_START; - ftdm_span_send_signal(ftdmchan->span, &sigev); + SS7_DEBUG_CHAN(ftdmchan, "Sending outgoing call from \"%s\" to \"%s\" to LibSngSS7\n", + ftdmchan->caller_data.ani.digits, + ftdmchan->caller_data.dnis.digits); + /*call sangoma_ss7_dial to make outgoing call */ + ft_to_sngss7_iam(ftdmchan); - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: /*outgoing call request*/ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_PROGRESS: - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - /* clear the glare flag if it is on from a preivous call */ - sngss7_clear_flag(sngss7_info, FLAG_GLARE); + /*check if the channel is inbound or outbound */ + if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + /*OUTBOUND...so we were told by the line of this so noifiy the user */ + sigev.event_id = FTDM_SIGEVENT_PROGRESS; + ftdm_span_send_signal (ftdmchan->span, &sigev); - /*call sangoma_ss7_dial to make outgoing call*/ - ft_to_sngss7_iam(ftdmchan); + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + } else { + /* inbound call so we need to send out ACM */ + ft_to_sngss7_acm (ftdmchan); + } - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_PROGRESS: - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - /*check if the channel is inbound or outbound*/ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + /* nothing to do at this time */ + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_UP: /*call is accpeted...both incoming and outgoing */ - /*OUTBOUND...so we were told by the line of this so noifiy the user*/ - sigev.event_id = FTDM_SIGEVENT_PROGRESS; - ftdm_span_send_signal(ftdmchan->span, &sigev); + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); + /*check if the channel is inbound or outbound */ + if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OUTBOUND)) { + /*OUTBOUND...so we were told by the line that the other side answered */ + sigev.event_id = FTDM_SIGEVENT_UP; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } else { + /*INBOUND...so FS told us it was going to answer...tell the stack */ + ft_to_sngss7_anm(ftdmchan); + } - } else { - /* inbound call so we need to send out ACM */ - ft_to_sngss7_acm(ftdmchan); - } - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_CANCEL: - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - /* nothing to do at this time */ - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_UP: /*call is accpeted...both incoming and outgoing*/ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + SS7_ERROR_CHAN(ftdmchan,"Hanging up call before informing user%s\n", " "); - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + /*now go to the HANGUP complete state */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_HANGUP); - /*check if the channel is inbound or outbound*/ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { - /*OUTBOUND...so we were told by the line that the other side answered*/ - sigev.event_id = FTDM_SIGEVENT_UP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_TERMINATING: /*call is hung up remotely */ - } else { - /*INBOUND...so FS told us it was going to answer...tell the stack*/ - ft_to_sngss7_anm(ftdmchan); - } - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_CANCEL: - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + /* set the flag to indicate this hangup is started from the remote side */ + sngss7_set_flag (sngss7_info, FLAG_REMOTE_REL); - SS7_ERROR("Hanging up call before informing user on span = %d, chan = %d!\n", ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + /*this state is set when the line is hanging up */ + sigev.event_id = FTDM_SIGEVENT_STOP; + ftdm_span_send_signal (ftdmchan->span, &sigev); - /*now go to the HANGUP complete state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_HANGUP: /*call is hung up locally */ - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_TERMINATING: /*call is hung up remotely*/ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + /* check for remote hangup flag */ + if (sngss7_test_flag (sngss7_info, FLAG_REMOTE_REL)) { + /* remote release ...do nothing here */ + SS7_DEBUG_CHAN(ftdmchan,"Hanging up remotely requested call!%s\n", ""); + } else if (sngss7_test_flag (sngss7_info, FLAG_GLARE)) { + /* release due to glare */ + SS7_DEBUG_CHAN(ftdmchan,"Hanging up requested call do to glare%s\n", ""); + } else { + /* set the flag to indicate this hangup is started from the local side */ + sngss7_set_flag (sngss7_info, FLAG_LOCAL_REL); - /* set the flag to indicate this hangup is started from the remote side */ - sngss7_set_flag(sngss7_info, FLAG_REMOTE_REL); + /*this state is set when FS is hanging up...so tell the stack */ + ft_to_sngss7_rel (ftdmchan); - /*this state is set when the line is hanging up*/ - sigev.event_id = FTDM_SIGEVENT_STOP; - ftdm_span_send_signal(ftdmchan->span, &sigev); + SS7_DEBUG_CHAN(ftdmchan,"Hanging up locally requested call!%s\n", ""); + } - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP: /*call is hung up locally*/ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + /*now go to the HANGUP complete state */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + break; - /* check for remote hangup flag */ - if (sngss7_test_flag(sngss7_info, FLAG_REMOTE_REL)) { - SS7_DEBUG("Hanging up remotely requested call!\n"); - } else { - SS7_DEBUG("Hanging up Locally requested call!\n"); + /**************************************************************************/ + case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - /* set the flag to indicate this hangup is started from the local side */ - sngss7_set_flag(sngss7_info, FLAG_LOCAL_REL); + if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { + SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); + break; + } - /*this state is set when FS is hanging up...so tell the stack*/ - ft_to_sngss7_rel(ftdmchan); - } + if (sngss7_test_flag (sngss7_info, FLAG_REMOTE_REL)) { + /* check if this hangup is from a tx RSC */ + if (sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) { + /* go to RESTART State until RSCa is received */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART); + } else { + /* if the hangup is from a rx RSC, rx GRS, or glare don't sent RLC */ + if (!(sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) && + !(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) && + !(sngss7_test_flag(sngss7_info, FLAG_GLARE))) { - /*now go to the HANGUP complete state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE); - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HANGUP_COMPLETE: - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + /* send out the release complete */ + ft_to_sngss7_rlc (ftdmchan); + } - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + /*now go to the DOWN state */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN); + } - if (sngss7_test_flag(sngss7_info, FLAG_REMOTE_REL)) { + SS7_DEBUG_CHAN(ftdmchan,"Completing remotely requested hangup!%s\n", ""); + } else if (sngss7_test_flag (sngss7_info, FLAG_LOCAL_REL)) { - /* check if this hangup is from a tx RSC */ - if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) { + /* if this hang up is do to a rx RESET we need to sit here till the RSP arrives */ + if (sngss7_test_flag (sngss7_info, FLAG_RESET_TX_RSP)) { + /* go to the down state as we have already received RSC-RLC */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN); + } - /* go to RESTART State until RSCa is received */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } else { - if (!(sngss7_test_flag(sngss7_info, FLAG_RESET_RX))) { - /* send out the release complete */ - ft_to_sngss7_rlc(ftdmchan); - } - /*now go to the DOWN state*/ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } + /* if it's a local release the user sends us to down */ + SS7_DEBUG_CHAN(ftdmchan,"Completing locally requested hangup!%s\n", ""); + } else if (sngss7_test_flag (sngss7_info, FLAG_GLARE)) { + SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup due to glare!%s\n", ""); - SS7_DEBUG("Completing remotely requested hangup!\n"); - } else { - SS7_DEBUG("Completing locally requested hangup!\n"); - } + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN); + } else { + SS7_DEBUG_CHAN(ftdmchan,"Completing requested hangup for unknown reason!%s\n", ""); + } - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: /*the call is finished and removed*/ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + break; - if (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED) { - SS7_DEBUG("re-entering state from processing block/unblock request ... do nothing\n"); - break; - } + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: /*the call is finished and removed */ + + /* check if there is a reset response that needs to be sent */ + if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) { + /* send a RSC-RLC */ + ft_to_sngss7_rsca (ftdmchan); + + /* clear the reset flag */ + sngss7_clear_flag (sngss7_info, FLAG_RESET_RX); + } + + /* check if there was a GRS that needs a GRA */ + if ((sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) && + (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) && + (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT))) { + + /* check if this is the base circuit and send out the GRA + * we insure that this is the last circuit to have the state change queued + */ + sngss7_span_data_t *span = ftdmchan->span->mod_data; + if (span->rx_grs.circuit == sngss7_info->circuit->id) { + /* send out the GRA */ + ft_to_sngss7_gra(ftdmchan); + + /* clean out the spans GRS structure */ + sngss7_span_data_t *span = ftdmchan->span->mod_data; + span->rx_grs.circuit = 0; + span->rx_grs.range = 0; + } + + /* clear the grp reset flag */ + sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX); + sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX_DN); + sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); + + }/* if ( sngss7_test_flag ( sngss7_info, FLAG_GRP_RESET_RX ) ) */ + + /* check if we got the reset response */ + if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX_RSP)) { + /* clear the reset flag */ + sngss7_clear_flag(sngss7_info, FLAG_RESET_TX_RSP); + sngss7_clear_flag(sngss7_info, FLAG_RESET_SENT); + sngss7_clear_flag(sngss7_info, FLAG_RESET_TX); + } + + if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP)) { + /* clear the reset flag */ + sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX_RSP); + sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_TX); + sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_BASE); + sngss7_clear_flag(sngss7_info, FLAG_GRP_RESET_SENT); + } + + /* check if we came from reset (aka we just processed a reset) */ + if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) || + (ftdmchan->last_state == FTDM_CHANNEL_STATE_SUSPENDED)) { + + /* check if reset flags are up indicating there is more processing to do yet */ + if (!(sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) && + !(sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) && + !(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) && + !(sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) { + + /* check if the sig status is down, and bring it up if it isn't */ + if (!ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { + SS7_DEBUG_CHAN(ftdmchan,"All reset flags cleared %s\n", ""); + /* all flags are down so we can bring up the sig status */ + sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sigev.sigstatus = FTDM_SIG_STATE_UP; + ftdm_span_send_signal (ftdmchan->span, &sigev); + } + } else { + + SS7_DEBUG_CHAN(ftdmchan,"Reset flags present (0x%X)\n", sngss7_info->flags); + + /* there is still another reset pending so go back to reset*/ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + } + } /* if ((ftdmchan->last_state == FTDM_CHANNEL_STATE_RESTART) */ /* check if t35 is active */ if (sngss7_info->t35.heartbeat_timer) { - ftdm_sched_cancel_timer(sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer); + ftdm_sched_cancel_timer (sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer); } - /* check if there is a reset response that needs to be sent */ - if (sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) { - /* send a RLC */ - ft_to_sngss7_rsca(ftdmchan); + /* clear all of the call specific data store in the channel structure */ + sngss7_info->suInstId = 0; + sngss7_info->spInstId = 0; + sngss7_info->globalFlg = 0; + sngss7_info->spId = 0; - /* inform Ftdm that the "sig" is up now for this channel */ - status = FTDM_SIG_STATE_UP; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } + /* clear any call related flags */ + sngss7_clear_flag (sngss7_info, FLAG_REMOTE_REL); + sngss7_clear_flag (sngss7_info, FLAG_LOCAL_REL); - /* check if there was a GRS that needs a GRA */ - if (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) { - /* 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) { - /* extract the sngss7_info for the circuit */ - tmp_ss7info = g_ftdm_sngss7_data.cfg.isupCircuit[i].obj; - tmp_chan = tmp_ss7info->ftdmchan; - /* check if the circuit is done going through reset */ /* KONRAD FIX ME...better way to check this??? */ - if (!(tmp_chan->state == FTDM_CHANNEL_STATE_DOWN) && (sngss7_test_flag(tmp_ss7info, FLAG_GRP_RESET_RX))) { - /* exit the for loop since we found a circuit still in reset */ - continue; - } /* if inreset */ - } /* if not siglink */ - } /* for */ - /* if we got through the whole range send out a GRA */ - if (i == (sngss7_info->grs.range + 1)) { - ft_to_sngss7_gra(ftdmchan); - } - } + if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) { + ftdm_channel_t *close_chan = ftdmchan; + /* close the channel */ + ftdm_channel_close (&close_chan); + } /* if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_OPEN)) */ - /* check if we got the reset response */ - if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) { - /* inform Ftdm that the "sig" is up now for this channel */ - status = FTDM_SIG_STATE_UP; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); - } + /* check if there is a glared call that needs to be processed */ + if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) { + + /* clear the glare flag */ + sngss7_clear_flag (sngss7_info, FLAG_GLARE); - /* check if the circuit has the glare flag up */ - if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) { - sngss7_info->suInstId = 0; - sngss7_info->spInstId = 0; - sngss7_info->globalFlg = 0; - sngss7_info->spId = 0; - sngss7_info->flags = 0; - sngss7_set_flag(sngss7_info, FLAG_GLARE); - - /* close the channel */ - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_t *close_chan = ftdmchan; - /* close the channel */ - ftdm_channel_close(&close_chan); - } - - /* check if the glare was caused by in incoming call aka glare structure is valid */ + /* check if we have an IAM stored...if we don't have one just exit */ if (sngss7_info->glare.circuit != 0) { - SS7_DEBUG("Glare flag is up....spoofing incoming call on span=%d, chan=%d (Cir=%d)\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - sngss7_info->glare.circuit); - /* clear all the call specific data */ + /* send the saved call back in to us */ + handle_con_ind (0, + sngss7_info->glare.spInstId, + sngss7_info->glare.circuit, + &sngss7_info->glare.iam); - /* spoof an incoming call */ - sngss7_con_ind(sngss7_info->glare.suInstId, - sngss7_info->glare.spInstId, - sngss7_info->glare.circuit, - &sngss7_info->glare.iam); + /* clear the glare info */ + memset(&sngss7_info->glare, 0x0, sizeof(sngss7_glare_data_t)); + } /* if (sngss7_info->glare.circuit != 0) */ + } /* if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) */ + + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: /* CICs needs a Reset */ + + if (sngss7_test_flag(sngss7_info, FLAG_CKT_UCIC_BLOCK)) { + if ((sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX))) { + + SS7_DEBUG_CHAN(ftdmchan,"Incoming Reset request on CIC in UCIC block, removing UCIC block%s\n", ""); + + /* set the unblk flag */ + sngss7_set_flag(sngss7_info, FLAG_CKT_UCIC_UNBLK); + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* break out of the processing for now */ + break; } - } else { - /* clear all of the call specific data store in the channel structure */ - sngss7_info->suInstId = 0; - sngss7_info->spInstId = 0; - sngss7_info->globalFlg = 0; - sngss7_info->spId = 0; - sngss7_info->flags = 0; - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OPEN)) { - ftdm_channel_t *close_chan = ftdmchan; - /* close the channel */ - ftdm_channel_close(&close_chan); - } - } + } + + /* if we're not coming from HANGUP_COMPLETE we need to check for resets + * we can also check if we are in a PAUSED state (no point in sending message + */ + if ((ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) && + (!sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED))) { + + /* check if this is an outgoing RSC */ + if ((sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) && + !(sngss7_test_flag(sngss7_info, FLAG_RESET_SENT))) { + + /* send a reset request */ + ft_to_sngss7_rsc (ftdmchan); + sngss7_set_flag(sngss7_info, FLAG_RESET_SENT); + + } /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) */ + + /* check if this is the first channel of a GRS (this flag is thrown when requesting reset) */ + if ( (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) && + !(sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_SENT)) && + (sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_BASE))) { + + /* send out the grs */ + ft_to_sngss7_grs (ftdmchan); + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_SENT); + + }/* if ( sngss7_test_flag ( sngss7_info, FLAG_GRP_RESET_TX ) ) */ + } /* if ( last_state != HANGUP && !PAUSED */ + + /* if the sig_status is up...bring it down */ + if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { + sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sigev.sigstatus = FTDM_SIG_STATE_DOWN; + ftdm_span_send_signal (ftdmchan->span, &sigev); + } + + if (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX)) { + /* set the grp reset done flag so we know we have finished this reset */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_DN); + } /* if (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX)) */ - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_RESTART: /* CICs needs a Reset */ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_INUSE)) { + /* bring the call down first...then process the rest of the reset */ + switch (ftdmchan->last_state){ + /******************************************************************/ + case (FTDM_CHANNEL_STATE_TERMINATING): + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_HANGUP); + break; + /******************************************************************/ + case (FTDM_CHANNEL_STATE_HANGUP): + case (FTDM_CHANNEL_STATE_HANGUP_COMPLETE): + /* go back to the last state after taking care of the rest of the restart state */ + ftdm_set_state_locked (ftdmchan, ftdmchan->last_state); + break; + /******************************************************************/ + default: + /* KONRAD: find out what the cause code should be */ + ftdmchan->caller_data.hangup_cause = 41; - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_INUSE)) { - /* bring the call down first...then process the rest of the reset */ - switch (ftdmchan->last_state) { - /******************************************************************/ - case(FTDM_CHANNEL_STATE_TERMINATING): - case(FTDM_CHANNEL_STATE_HANGUP): - case(FTDM_CHANNEL_STATE_HANGUP_COMPLETE): - /* go back to the last state after taking care of the rest of the restart state */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - break; - /******************************************************************/ - default: - /* KONRAD: find out what the cause code should be */ - ftdmchan->caller_data.hangup_cause = 41; + /* change the state to terminatting, it will throw us back here + * once the call is done + */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + break; + /******************************************************************/ + } /* switch (ftdmchan->last_state) */ + } else { + /* check if this an incoming RSC or we have a response already */ + if (sngss7_test_flag (sngss7_info, FLAG_RESET_RX) || + sngss7_test_flag (sngss7_info, FLAG_RESET_TX_RSP) || + sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX_RSP) || + sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX_CMPLT)) { + + SS7_DEBUG_CHAN(ftdmchan, "Reset processed moving to DOWN (0x%X)\n", sngss7_info->flags); + + /* go to a down state to clear the channel and send the response */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DOWN); + } else { + SS7_DEBUG_CHAN(ftdmchan, "Waiting on Reset Rsp/Grp Reset to move to DOWN (0x%X)\n", sngss7_info->flags); + } + } - /* change the state to terminatting, it will throw us back here - * once the call is done - */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); - break; - /******************************************************************/ - } - } else { + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_SUSPENDED: /* circuit has been blocked */ - /* check if this an incoming RSC */ - if (sngss7_test_flag(sngss7_info, FLAG_RESET_RX) || sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX)) { - /* go to a down state to clear the channel and send RSCa */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - } /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_RX)) */ - } /* if (inuse) */ + SS7_DEBUG_CHAN(ftdmchan,"Current flags: 0x%X\n", sngss7_info->flags); - /* check if this is an outgoing RSC */ - if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) { - - /* make sure we aren't coming from hanging up a call */ - if (ftdmchan->last_state != FTDM_CHANNEL_STATE_HANGUP_COMPLETE) { - /* send a reset request */ - ft_to_sngss7_rsc(ftdmchan); - } - - /* don't change to the DOWN state as we need to wait for the RSCa */ - } /* if (sngss7_test_flag(sngss7_info, FLAG_RESET_TX)) */ - - /* send a sig event to the core to disable the channel */ - status = FTDM_SIG_STATE_DOWN; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); + /**********************************************************************/ + if (sngss7_test_flag (sngss7_info, FLAG_INFID_PAUSED)) { + SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE flag %s\n", ""); + + /* bring the channel signaling status to down */ + sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sigev.sigstatus = FTDM_SIG_STATE_DOWN; + ftdm_span_send_signal (ftdmchan->span, &sigev); - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_SUSPENDED: /* circuit has been blocked */ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + /* check the last state and return to it to allow the call to finish */ + goto suspend_goto_last; + } - /**********************************************************************/ - if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { - SS7_DEBUG("processing pause for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - /* bring the channel signaling status to down */ - status = FTDM_SIG_STATE_DOWN; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); + if (sngss7_test_flag (sngss7_info, FLAG_INFID_RESUME)) { + SS7_DEBUG_CHAN(ftdmchan, "Processing RESUME flag %s\n", ""); - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) { - SS7_DEBUG("processing resume for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - /* we just resumed...throw the channel into reset */ - sngss7_set_flag(sngss7_info, FLAG_RESET_TX); + /* the reset flag is set for the first channel in the span at handle_resume */ - /* clear the resume flag */ - sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME); + /* clear the resume flag */ + sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME); - /* go to restart state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); - } - /**********************************************************************/ - if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { - SS7_DEBUG("processing rx Mn ckt block for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - /* bring the channel signaling status to down */ - status = FTDM_SIG_STATE_DOWN; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); + /* go to restart state */ + goto suspend_goto_last; + } - /* send a BLA */ - ft_to_sngss7_bla(ftdmchan); + /**********************************************************************/ + if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { + SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", ""); - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX)) { - SS7_DEBUG("processing rx Mn ckt unblock for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - /* bring the channel signaling status to up */ - status = FTDM_SIG_STATE_UP; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); + /* send a BLA */ + ft_to_sngss7_bla (ftdmchan); - /* clear the unblock flag */ - sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_UNBLK_RX); + /* check the last state and return to it to allow the call to finish */ + goto suspend_goto_last; + } - /* send a uba */ - ft_to_sngss7_uba(ftdmchan); + if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX)){ + SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_RX flag %s\n", ""); - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - /**********************************************************************/ - if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) { - SS7_DEBUG("processing tx Mn ckt block for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - /* bring the channel signaling status to down */ - status = FTDM_SIG_STATE_DOWN; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); + /* clear the unblock flag */ + sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX); - /* send a blo */ - ft_to_sngss7_blo(ftdmchan); + /* send a uba */ + ft_to_sngss7_uba (ftdmchan); - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - if (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX)) { - SS7_DEBUG("processing tx Mn ckt unblock for span = %, chan = %d\n",ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - /* bring the channel signaling status to up */ - status = FTDM_SIG_STATE_UP; - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.raw_data = &status; - ftdm_span_send_signal(ftdmchan->span, &sigev); + /* check the last state and return to it to allow the call to finish */ + goto suspend_goto_last; + } - /* clear the unblock flag */ - sngss7_clear_flag(sngss7_info, FLAG_CKT_MN_UNBLK_TX); + /**********************************************************************/ + if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_TX)) { + SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_TX flag %s\n", ""); - /* send a ubl */ - ft_to_sngss7_ubl(ftdmchan); + /* send a blo */ + ft_to_sngss7_blo (ftdmchan); - /* check the last state and return to it to allow the call to finish */ - ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); - } - /**********************************************************************/ + /* check the last state and return to it to allow the call to finish */ + goto suspend_goto_last; + } - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_IN_LOOP: /* COT test */ - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 processing state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX)){ + SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_UNBLK_TX flag %s\n", ""); - /* send the lpa */ - ft_to_sngss7_lpa(ftdmchan); + /* clear the unblock flag */ + sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_TX); - break; - /**************************************************************************/ - case FTDM_CHANNEL_STATE_HOLD: - case FTDM_CHANNEL_STATE_DIALTONE: - case FTDM_CHANNEL_STATE_BUSY: - case FTDM_CHANNEL_STATE_ATTN: - case FTDM_CHANNEL_STATE_GENRING: - case FTDM_CHANNEL_STATE_GET_CALLERID: - case FTDM_CHANNEL_STATE_CALLWAITING: - case FTDM_CHANNEL_STATE_IDLE: - case FTDM_CHANNEL_STATE_INVALID: - ftdm_log(FTDM_LOG_DEBUG, "ftmod_sangoma_ss7 does not support state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - break; - /**************************************************************************/ - default: - /*this is bad...we're in an unknown state...should we kill this channel???*/ - ftdm_log(FTDM_LOG_ERROR, "ftmod_sangoma_ss7 in unknown state %s on span=%u,chan=%u\n", - ftdm_channel_state2str(ftdmchan->state),ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - break; - } /*switch (ftdmchan->state)*/ + /* send a ubl */ + ft_to_sngss7_ubl (ftdmchan); - /*unlock*/ - ftdm_mutex_unlock(ftdmchan->mutex); + /* check the last state and return to it to allow the call to finish */ + goto suspend_goto_last; + } - return; + /**********************************************************************/ + if (sngss7_test_flag (sngss7_info, FLAG_CKT_LC_BLOCK_RX)) { + SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_BLOCK_RX flag %s\n", ""); + + /* send a BLA */ + /*ft_to_sngss7_bla(ftdmchan);*/ + + /* check the last state and return to it to allow the call to finish */ + goto suspend_goto_last; + } + + if (sngss7_test_flag (sngss7_info, FLAG_CKT_LC_UNBLK_RX)) { + SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_LC_UNBLK_RX flag %s\n", ""); + + /* clear the unblock flag */ + sngss7_clear_flag (sngss7_info, FLAG_CKT_MN_UNBLK_RX); + + /* send a uba */ + /*ft_to_sngss7_uba(ftdmchan);*/ + + /* check the last state and return to it to allow the call to finish */ + goto suspend_goto_last; + } + /**********************************************************************/ + if (sngss7_test_flag (sngss7_info, FLAG_CKT_UCIC_BLOCK)) { + SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_BLOCK flag %s\n", ""); + + /* bring the channel signaling status to down */ + sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sigev.sigstatus = FTDM_SIG_STATE_DOWN; + ftdm_span_send_signal (ftdmchan->span, &sigev); + + /* remove any reset flags */ + sngss7_clear_flag (sngss7_info, FLAG_GRP_RESET_TX_RSP); + sngss7_clear_flag (sngss7_info, FLAG_GRP_RESET_TX); + sngss7_clear_flag (sngss7_info, FLAG_RESET_TX_RSP); + sngss7_clear_flag (sngss7_info, FLAG_RESET_TX); + sngss7_clear_flag (sngss7_info, FLAG_RESET_SENT); + sngss7_clear_flag (sngss7_info, FLAG_GRP_RESET_RX); + sngss7_clear_flag (sngss7_info, FLAG_RESET_RX); + sngss7_clear_flag (sngss7_info, FLAG_GRP_RESET_BASE); + + /* bring the channel down */ + goto suspend_goto_last; + } + + if (sngss7_test_flag (sngss7_info, FLAG_CKT_UCIC_UNBLK)) { + SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_UCIC_UNBLK flag %s\n", "");; + + /* throw the channel into reset from our side since it is already in reset from the remote side */ + sngss7_set_flag (sngss7_info, FLAG_RESET_TX); + + /* bring the channel into restart again */ + goto suspend_goto_restart; + } + +suspend_goto_last: + ftdm_set_state_locked (ftdmchan, ftdmchan->last_state); + break; + +suspend_goto_restart: + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + +/**************************************************************************/ + case FTDM_CHANNEL_STATE_IN_LOOP: /* COT test */ + + /* send the lpa */ + ft_to_sngss7_lpa (ftdmchan); + + break; + /**************************************************************************/ + case FTDM_CHANNEL_STATE_IDLE: + ftdm_set_state_locked(ftdmchan, ftdmchan->last_state); + break; + /**************************************************************************/ + default: + /* we don't handle any of the other states */ + SS7_ERROR_CHAN(ftdmchan, "ftmod_sangoma_ss7 does not support %s state\n", ftdm_channel_state2str (ftdmchan->state)); + + break; + /**************************************************************************/ + }/*switch (ftdmchan->state) */ + + return; } -/******************************************************************************/ /******************************************************************************/ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_ss7_outgoing_call) { - sngss7_chan_data_t *sngss7_info; - int c; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; - /* lock the channel while we check whether it is availble */ - ftdm_mutex_lock(ftdmchan->mutex); + /* lock the channel while we check whether it is availble */ + ftdm_mutex_lock (ftdmchan->mutex); - switch (ftdmchan->state) { - /**************************************************************************/ - case FTDM_CHANNEL_STATE_DOWN: - /* inform the monitor thread that we want to make a call */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DIALING); + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + SS7_ASSERT; + }; - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + /* check if the channel sig state is UP */ + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { + SS7_ERROR_CHAN(ftdmchan, "Requested channel sig state is down, cancelling call!%s\n", " "); + goto outgoing_fail; + } - /* now we have to wait for either the stack to reject the call because of - * glare or for the network to acknowledge the call - */ - c = 0; - while (c < 100) { + /* check if there is a remote block */ + if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { - /* lock the channel while we check whether it is availble */ - ftdm_mutex_lock(ftdmchan->mutex); + /* the channel is blocked...can't send any calls here */ + SS7_ERROR_CHAN(ftdmchan, "Requested channel is remotely blocked, re-hunt channel!%s\n", " "); + goto outgoing_break; + } - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - SS7_FUNC_TRACE_EXIT(__FUNCTION__); - return FTDM_FAIL; - }; + /* check if there is a local block */ + if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_HW_BLOCK_TX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX))) { - /* extract the sngss7_chan_data structure */ - sngss7_info = (sngss7_chan_data_t *)ftdmchan->call_data; + /* KONRAD FIX ME : we should check if this is a TEST call and allow it */ - if (sngss7_test_flag(sngss7_info, FLAG_GLARE)) { - SS7_ERROR("Glare flag on span=%d,chan=%d\n", - ftdmchan->physical_span_id,ftdmchan->physical_chan_id); + /* the channel is blocked...can't send any calls here */ + SS7_ERROR_CHAN(ftdmchan, "Requested channel is locally blocked, re-hunt channel!%s\n", " "); + goto outgoing_break; + } - /* kill the timer */ - if (sngss7_info->t35.heartbeat_timer) { - ftdm_sched_cancel_timer(sngss7_info->t35.sched, &sngss7_info->t35.heartbeat_timer); - } + /* check the state of the channel */ + switch (ftdmchan->state){ + /**************************************************************************/ + case FTDM_CHANNEL_STATE_DOWN: + /* inform the monitor thread that we want to make a call */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_DIALING); - goto outgoing_glare; - } + /* unlock the channel */ + ftdm_mutex_unlock (ftdmchan->mutex); + + goto outgoing_successful; + break; + /**************************************************************************/ + default: + /* the channel is already used...this can't be, end the request */ + SS7_ERROR("Outgoing call requested channel in already in use...indicating glare on span=%d,chan=%d\n", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id); - switch (ftdmchan->state) { - /******************************************************************/ - case FTDM_CHANNEL_STATE_DIALING: - break; - /******************************************************************/ - case FTDM_CHANNEL_STATE_PROGRESS: - case FTDM_CHANNEL_STATE_PROGRESS_MEDIA: - case FTDM_CHANNEL_STATE_UP: - goto outgoing_successful; - break; - /******************************************************************/ - default: - SS7_ERROR("Channel in invalid state (%s) on span=%d,chan=%d...fail\n", - ftdm_channel_state2str(ftdmchan->state), - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id); - goto outgoing_fail; - break; - /******************************************************************/ - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - - /* sleep for a bit to let the state change */ - ftdm_sleep(10); - - /* increment the timeout counter */ - c++; - - } /* while (c < 4) */ - - /* if we got here we have timed-out waiting for acknowledgment, kill the call */ - SS7_DEBUG("Timeout waiting for outgoing call to be accepted by network, ok'ing outgoing call on span=%d,chan=%d\n", - ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - - /* consider the call good .... for now */ - goto outgoing_successful; - - break; - /**************************************************************************/ - default: - /* the channel is already used...this can't be, end the request */ - SS7_ERROR("Outgoing call requested channel in already in use...indicating glare on span=%d,chan=%d\n", - ftdmchan->physical_span_id,ftdmchan->physical_chan_id); - goto outgoing_glare; - break; - /**************************************************************************/ - } + goto outgoing_break; + break; + /**************************************************************************/ + } /* switch (ftdmchan->state) (original call) */ outgoing_fail: - SS7_DEBUG("Call Request on span=%d, chan=%d failed\n"); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); + SS7_DEBUG_CHAN(ftdmchan, "Call Request failed%s\n", " "); + /* unlock the channel */ + ftdm_mutex_unlock (ftdmchan->mutex); + return FTDM_FAIL; - return FTDM_FAIL; - -outgoing_glare: - SS7_DEBUG("Indicating glare on span=%d, chan=%d\n"); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - return FTDM_BREAK; +outgoing_break: + SS7_DEBUG_CHAN(ftdmchan, "Call Request re-hunt%s\n", " "); + /* unlock the channel */ + ftdm_mutex_unlock (ftdmchan->mutex); + return FTDM_BREAK; outgoing_successful: - SS7_DEBUG("Call Request on span=%d, chan=%d successful\n"); - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - return FTDM_SUCCESS; + SS7_DEBUG_CHAN(ftdmchan, "Call Request successful%s\n", " "); + /* unlock the channel */ + ftdm_mutex_unlock (ftdmchan->mutex); + return FTDM_SUCCESS; } + /******************************************************************************/ #if 0 -static FIO_CHANNEL_REQUEST_FUNCTION(ftdm_sangoma_ss7_request_chan) -{ - SS7_INFO("KONRAD-> I got called %s\n",__FUNCTION__); - return FTDM_SUCCESS; -} + static FIO_CHANNEL_REQUEST_FUNCTION (ftdm_sangoma_ss7_request_chan) + { + SS7_INFO ("KONRAD-> I got called %s\n", __FUNCTION__); + return FTDM_SUCCESS; + } + #endif /******************************************************************************/ -/* FT-CORE SIG STATUS FUNCTIONS ***********************************************/ +/* FT-CORE SIG STATUS FUNCTIONS ********************************************** */ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_ss7_get_sig_status) { - - if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { - *status = FTDM_SIG_STATE_UP; - } else { - *status = FTDM_SIG_STATE_DOWN; - } + if (ftdm_test_flag (ftdmchan, FTDM_CHANNEL_SIG_UP)) { + *status = FTDM_SIG_STATE_UP; + } else { + *status = FTDM_SIG_STATE_DOWN; + } - return FTDM_SUCCESS; + return FTDM_SUCCESS; } +/******************************************************************************/ static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_ss7_set_sig_status) { - SS7_ERROR("Cannot set channel status in this module\n"); - - return FTDM_NOTIMPL; + SS7_ERROR ("Cannot set channel status in this module\n"); + return FTDM_NOTIMPL; } -/* FT-CORE SIG FUNCTIONS *******************************************************/ -static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t *span) +/* FT-CORE SIG FUNCTIONS ******************************************************/ +static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) { - SS7_INFO("Starting span %s:%u.\n",span->name,span->span_id); + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_span_data_t *sngss7_span = NULL; + int x; - /* clear the monitor thread stop flag */ - ftdm_clear_flag(span, FTDM_SPAN_STOP_THREAD); - ftdm_clear_flag(span, FTDM_SPAN_IN_THREAD); - /* activate all the configured ss7 links */ - if (ft_to_sngss7_activate_all()) { - SS7_CRITICAL("Failed to activate LibSngSS7!\n"); - return FTDM_FAIL; - } + SS7_INFO ("Starting span %s:%u.\n", span->name, span->span_id); - /*start the span monitor thread*/ - if(ftdm_thread_create_detached(ftdm_sangoma_ss7_run, span) != FTDM_SUCCESS) { - SS7_CRITICAL("Failed to start Span Monitor Thread!\n"); - return FTDM_FAIL; - } + /* throw the channels in pause */ + for (x = 1; x < (span->chan_count + 1); x++) { + /* extract the channel structure and sngss7 channel data */ + ftdmchan = span->channels[x]; + sngss7_info = ftdmchan->call_data; + sngss7_span = ftdmchan->span->mod_data; - SS7_DEBUG("Finished starting span %s:%u.\n",span->name,span->span_id); + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); - return FTDM_SUCCESS; + /* throw the pause flag */ + sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED); + + /* throw the grp reset flag */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); + if (x == 1) { + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_BASE); + sngss7_span->tx_grs.circuit = sngss7_info->circuit->id; + sngss7_span->tx_grs.range = span->chan_count -1; + } + + /* throw the channel to suspend */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + } + + /* clear the monitor thread stop flag */ + ftdm_clear_flag (span, FTDM_SPAN_STOP_THREAD); + ftdm_clear_flag (span, FTDM_SPAN_IN_THREAD); + + /* activate all the configured ss7 links */ + if (ft_to_sngss7_activate_all()) { + SS7_CRITICAL ("Failed to activate LibSngSS7!\n"); + return FTDM_FAIL; + } + + /*start the span monitor thread */ + if (ftdm_thread_create_detached (ftdm_sangoma_ss7_run, span) != FTDM_SUCCESS) { + SS7_CRITICAL ("Failed to start Span Monitor Thread!\n"); + return FTDM_FAIL; + } + + SS7_DEBUG ("Finished starting span %s:%u.\n", span->name, span->span_id); + + return FTDM_SUCCESS; } /******************************************************************************/ -static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t *span) +static ftdm_status_t ftdm_sangoma_ss7_stop(ftdm_span_t * span) { - /*this function is called by the FT-Core to stop this span*/ - - ftdm_log(FTDM_LOG_INFO, "Stopping span %s:%u.\n",span->name,span->span_id); - - /* throw the STOP_THREAD flag to signal monitor thread stop */ - ftdm_set_flag(span, FTDM_SPAN_STOP_THREAD); - - /* wait for the thread to stop */ - while(ftdm_test_flag(span, FTDM_SPAN_IN_THREAD)) { - ftdm_log(FTDM_LOG_DEBUG, "Waiting for monitor thread to end for %s:%u.\n",span->name,span->span_id); - ftdm_sleep(1); - } + /*this function is called by the FT-Core to stop this span */ - /* KONRAD FIX ME - deconfigure any circuits, links, attached to this span */ + ftdm_log (FTDM_LOG_INFO, "Stopping span %s:%u.\n", span->name,span->span_id); - ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s:%u.\n",span->name,span->span_id); + /* throw the STOP_THREAD flag to signal monitor thread stop */ + ftdm_set_flag (span, FTDM_SPAN_STOP_THREAD); - return FTDM_SUCCESS; + /* wait for the thread to stop */ + while (ftdm_test_flag (span, FTDM_SPAN_IN_THREAD)) { + ftdm_log (FTDM_LOG_DEBUG,"Waiting for monitor thread to end for %s:%u.\n", + span->name, + span->span_id); + ftdm_sleep (1); + } + + /* KONRAD FIX ME - deconfigure any circuits, links, attached to this span */ + + ftdm_log (FTDM_LOG_DEBUG, "Finished stopping span %s:%u.\n", span->name, span->span_id); + + return FTDM_SUCCESS; } -/******************************************************************************/ /* SIG_FUNCTIONS ***************************************************************/ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_ss7_span_config) { - ftdm_log(FTDM_LOG_INFO, "Configuring ftmod_sangoma_ss7 span = %s(%d)...\n", - span->name, - span->span_id); + sngss7_span_data_t *ss7_span_info; - /* parse the configuration and apply to the global config structure */ - if (ftmod_ss7_parse_xml(ftdm_parameters, span)) { - ftdm_log(FTDM_LOG_CRIT, "Failed to parse configuration!\n"); + ftdm_log (FTDM_LOG_INFO, "Configuring ftmod_sangoma_ss7 span = %s(%d)...\n", + span->name, + span->span_id); - return FTDM_FAIL; - } + /* initalize the span's data structure */ + ss7_span_info = ftdm_calloc (1, sizeof (sngss7_span_data_t)); - /* configure libsngss7 */ - if (ft_to_sngss7_cfg()) { - ftdm_log(FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n"); - return FTDM_FAIL; - } + /* create a timer schedule */ + if (ftdm_sched_create(&ss7_span_info->sched, "SngSS7_Schedule")) { + SS7_CRITICAL("Unable to create timer schedule!\n"); + return FTDM_FAIL; + } - /*setup the span structure with the info so far*/ - g_ftdm_sngss7_data.sig_cb = sig_cb; + /* start the free run thread for the schedule */ + if (ftdm_sched_free_run(ss7_span_info->sched)) { + SS7_CRITICAL("Unable to schedule free run!\n"); + return FTDM_FAIL; + } - span->start = ftdm_sangoma_ss7_start; - span->stop = ftdm_sangoma_ss7_stop; - span->signal_type = FTDM_SIGTYPE_SS7; - span->signal_data = NULL; - span->outgoing_call = ftdm_sangoma_ss7_outgoing_call; - span->channel_request = NULL; - span->signal_cb = sig_cb; - span->get_channel_sig_status = ftdm_sangoma_ss7_get_sig_status; - span->set_channel_sig_status = ftdm_sangoma_ss7_set_sig_status; - span->state_map = &sangoma_ss7_state_map; - ftdm_set_flag(span, FTDM_SPAN_USE_CHAN_QUEUE); + /* create an event queue for this span */ + if ((ftdm_queue_create(&(ss7_span_info)->event_queue, SNGSS7_EVENT_QUEUE_SIZE)) != FTDM_SUCCESS) { + SS7_CRITICAL("Unable to create event queue!\n"); + return FTDM_FAIL; + } - ftdm_log(FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_ss7 span = %s(%d)...\n", - span->name, - span->span_id); -#if 0 - /* start the span up */ - ftdm_sangoma_ss7_start(span); -#endif - return FTDM_SUCCESS; + /*setup the span structure with the info so far */ + g_ftdm_sngss7_data.sig_cb = sig_cb; + span->start = ftdm_sangoma_ss7_start; + span->stop = ftdm_sangoma_ss7_stop; + span->signal_type = FTDM_SIGTYPE_SS7; + span->signal_data = NULL; + span->outgoing_call = ftdm_sangoma_ss7_outgoing_call; + span->channel_request = NULL; + span->signal_cb = sig_cb; + span->get_channel_sig_status = ftdm_sangoma_ss7_get_sig_status; + span->set_channel_sig_status = ftdm_sangoma_ss7_set_sig_status; + span->state_map = &sangoma_ss7_state_map; + span->mod_data = ss7_span_info; + + /* set the flag to indicate that this span uses channel state change queues */ + ftdm_set_flag (span, FTDM_SPAN_USE_CHAN_QUEUE); + /* set the flag to indicate that this span uses sig event queues */ + ftdm_set_flag (span, FTDM_SPAN_USE_SIGNALS_QUEUE); + + /* parse the configuration and apply to the global config structure */ + if (ftmod_ss7_parse_xml(ftdm_parameters, span)) { + ftdm_log (FTDM_LOG_CRIT, "Failed to parse configuration!\n"); + return FTDM_FAIL; + } + + /* configure libsngss7 */ + if (ft_to_sngss7_cfg_all()) { + ftdm_log (FTDM_LOG_CRIT, "Failed to configure LibSngSS7!\n"); + return FTDM_FAIL; + } + + ftdm_log (FTDM_LOG_INFO, "Finished configuring ftmod_sangoma_ss7 span = %s(%d)...\n", + span->name, + span->span_id); + + return FTDM_SUCCESS; } /******************************************************************************/ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init) { - /*this function is called by the FT-core to load the signaling module*/ + /*this function is called by the FT-core to load the signaling module */ - ftdm_log(FTDM_LOG_INFO, "Loading ftmod_sangoma_ss7...\n"); + ftdm_log (FTDM_LOG_INFO, "Loading ftmod_sangoma_ss7...\n"); - /* default the global structure */ - memset(&g_ftdm_sngss7_data, 0x0, sizeof(ftdm_sngss7_data_t)); + /* default the global structure */ + memset (&g_ftdm_sngss7_data, 0x0, sizeof (ftdm_sngss7_data_t)); - sngss7_id = 0; + sngss7_id = 0; - /* global flag indicating that general configuration has been done */ - g_ftdm_sngss7_data.gen_config_done = 0; + /* initalize the global gen_config flag */ + g_ftdm_sngss7_data.gen_config = 0; - /* min. number of digitis to wait for */ - g_ftdm_sngss7_data.min_digits = 7; + /* min. number of digitis to wait for */ + g_ftdm_sngss7_data.min_digits = 7; - /* function trace initizalation */ - g_ftdm_sngss7_data.function_trace = 1; - g_ftdm_sngss7_data.function_trace_level = 7; + /* function trace initizalation */ + g_ftdm_sngss7_data.function_trace = 1; + g_ftdm_sngss7_data.function_trace_level = 7; - /* message (IAM, ACM, ANM, etc) trace initizalation */ - g_ftdm_sngss7_data.message_trace = 1; - g_ftdm_sngss7_data.message_trace_level = 7; + /* message (IAM, ACM, ANM, etc) trace initizalation */ + g_ftdm_sngss7_data.message_trace = 1; + g_ftdm_sngss7_data.message_trace_level = 6; - /* create a timer schedule */ - if (ftdm_sched_create(&sngss7_sched, "SngSS7_Schedule")) { - SS7_CRITICAL("Unable to create timer schedule!\n"); - return FTDM_FAIL; - } + /* setup the call backs needed by Sangoma_SS7 library */ + sng_event.cc.sng_con_ind = sngss7_con_ind; + sng_event.cc.sng_con_cfm = sngss7_con_cfm; + sng_event.cc.sng_con_sta = sngss7_con_sta; + sng_event.cc.sng_rel_ind = sngss7_rel_ind; + sng_event.cc.sng_rel_cfm = sngss7_rel_cfm; + sng_event.cc.sng_dat_ind = sngss7_dat_ind; + sng_event.cc.sng_fac_ind = sngss7_fac_ind; + sng_event.cc.sng_fac_cfm = sngss7_fac_cfm; + sng_event.cc.sng_sta_ind = sngss7_sta_ind; + sng_event.cc.sng_umsg_ind = sngss7_umsg_ind; + sng_event.cc.sng_susp_ind = NULL; + sng_event.cc.sng_resm_ind = NULL; + sng_event.cc.sng_ssp_sta_cfm = NULL; - /* setup the call backs needed by Sangoma_SS7 library */ - sng_event.cc.sng_con_ind = sngss7_con_ind; - sng_event.cc.sng_con_cfm = sngss7_con_cfm; - sng_event.cc.sng_con_sta = sngss7_con_sta; - sng_event.cc.sng_rel_ind = sngss7_rel_ind; - sng_event.cc.sng_rel_cfm = sngss7_rel_cfm; - sng_event.cc.sng_dat_ind = sngss7_dat_ind; - sng_event.cc.sng_fac_ind = sngss7_fac_ind; - sng_event.cc.sng_fac_cfm = sngss7_fac_cfm; - sng_event.cc.sng_sta_ind = sngss7_sta_ind; - sng_event.cc.sng_umsg_ind = sngss7_umsg_ind; - sng_event.cc.sng_susp_ind = NULL; - sng_event.cc.sng_resm_ind = NULL; - sng_event.cc.sng_ssp_sta_cfm = NULL; + sng_event.sm.sng_log = handle_sng_log; + sng_event.sm.sng_mtp1_alarm = handle_sng_mtp1_alarm; + sng_event.sm.sng_mtp2_alarm = handle_sng_mtp2_alarm; + sng_event.sm.sng_mtp3_alarm = handle_sng_mtp3_alarm; + sng_event.sm.sng_isup_alarm = handle_sng_isup_alarm; + sng_event.sm.sng_cc_alarm = handle_sng_cc_alarm; - sng_event.sm.sng_log = handle_sng_log; - sng_event.sm.sng_mtp1_alarm = handle_sng_alarm; - sng_event.sm.sng_mtp2_alarm = handle_sng_alarm; - sng_event.sm.sng_mtp3_alarm = handle_sng_alarm; - sng_event.sm.sng_isup_alarm = handle_sng_alarm; - sng_event.sm.sng_cc_alarm = handle_sng_alarm; + /* initalize sng_ss7 library */ + sng_isup_init (&sng_event); - /* initalize sng_ss7 library */ - sng_isup_init(&sng_event); + /* crash on assert fail */ + ftdm_global_set_crash_policy (FTDM_CRASH_ON_ASSERT); - /* crash on assert fail */ - ftdm_global_set_crash_policy(FTDM_CRASH_ON_ASSERT); - - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_ss7_unload) { - /*this function is called by the FT-core to unload the signaling module*/ + /*this function is called by the FT-core to unload the signaling module */ - ftdm_log(FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n"); + ftdm_log (FTDM_LOG_INFO, "Starting ftmod_sangoma_ss7 unload...\n"); - sng_isup_free(); + sng_isup_free(); - ftdm_log(FTDM_LOG_INFO, "Finished ftmod_sangoma_ss7 unload!\n"); - return FTDM_SUCCESS; + ftdm_log (FTDM_LOG_INFO, "Finished ftmod_sangoma_ss7 unload!\n"); + return FTDM_SUCCESS; } /******************************************************************************/ static FIO_API_FUNCTION(ftdm_sangoma_ss7_api) { - /* handle this in it's own file....so much to do */ - return (ftdm_sngss7_handle_cli_cmd(stream, data)); + /* handle this in it's own file....so much to do */ + return (ftdm_sngss7_handle_cli_cmd (stream, data)); } /******************************************************************************/ static FIO_IO_LOAD_FUNCTION(ftdm_sangoma_ss7_io_init) { - assert(fio != NULL); - memset(&g_ftdm_sngss7_interface, 0, sizeof(g_ftdm_sngss7_interface)); + assert (fio != NULL); + memset (&g_ftdm_sngss7_interface, 0, sizeof (g_ftdm_sngss7_interface)); - g_ftdm_sngss7_interface.name = "ss7"; - g_ftdm_sngss7_interface.api = ftdm_sangoma_ss7_api; + g_ftdm_sngss7_interface.name = "ss7"; + g_ftdm_sngss7_interface.api = ftdm_sangoma_ss7_api; - *fio = &g_ftdm_sngss7_interface; + *fio = &g_ftdm_sngss7_interface; - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ /* START **********************************************************************/ -ftdm_module_t ftdm_module = -{ - "sangoma_ss7", /*char name[256]; */ - ftdm_sangoma_ss7_io_init, /*fio_io_load_t */ - NULL, /*fio_io_unload_t */ - ftdm_sangoma_ss7_init, /*fio_sig_load_t */ - NULL, /*fio_sig_configure_t */ - ftdm_sangoma_ss7_unload, /*fio_sig_unload_t */ - ftdm_sangoma_ss7_span_config /*fio_configure_span_signaling_t */ +ftdm_module_t ftdm_module = { + "sangoma_ss7", /*char name[256]; */ + ftdm_sangoma_ss7_io_init, /*fio_io_load_t */ + NULL, /*fio_io_unload_t */ + ftdm_sangoma_ss7_init, /*fio_sig_load_t */ + NULL, /*fio_sig_configure_t */ + ftdm_sangoma_ss7_unload, /*fio_sig_unload_t */ + ftdm_sangoma_ss7_span_config /*fio_configure_span_signaling_t */ }; /******************************************************************************/ -/*****************************************************************************/ -/* 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: - */ - /******************************************************************************/ - - +/* For Emacs: +* Local Variables: +* mode:c +* indent-tabs-mode:t +* tab-width:4 +* c-basic-offset:4 +* End: +* For VIM: +* vim:set softtabstop=4 shiftwidth=4 tabstop=4: +*/ +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index 3f1eb37549..050f59e00e 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -44,58 +44,286 @@ #include #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 -#if 0 -#define SS7_HARDCODED -#endif -#define SNG_BASE 1 +#define MAX_CIC_LENGTH 5 +#define MAX_CIC_MAP_LENGTH 1000 + +#define SNGSS7_EVENT_QUEUE_SIZE 100 typedef enum { - SNG_IAM = 1, - SNG_ACM, - SNG_CPG, - SNG_ANM, - SNG_REL, - SNG_RLC -}sng_msg_type_t; + SNGSS7_CON_IND_EVENT = 0, + SNGSS7_CON_CFM_EVENT, + SNGSS7_CON_STA_EVENT, + SNGSS7_REL_IND_EVENT, + SNGSS7_REL_CFM_EVENT, + SNGSS7_DAT_IND_EVENT, + SNGSS7_FAC_IND_EVENT, + SNGSS7_FAC_CFM_EVENT, + SNGSS7_UMSG_IND_EVENT, + SNGSS7_STA_IND_EVENT +} sng_event_type_t; + +typedef enum { + VOICE = 0, + 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 spInstId; + uint32_t circuit; + SiConEvnt iam; }sngss7_glare_data_t; typedef struct sngss7_group_data { @@ -104,56 +332,123 @@ 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 rx_grs; + sngss7_group_data_t tx_grs; + ftdm_queue_t *event_queue; +}sngss7_span_data_t; + +typedef struct sngss7_event_data +{ + uint32_t event_id; + uint32_t spId; + uint32_t suId; + uint32_t spInstId; + uint32_t suInstId; + uint32_t circuit; + uint8_t globalFlg; + uint8_t evntType; + union + { + SiConEvnt siConEvnt; + SiCnStEvnt siCnStEvnt; + SiRelEvnt siRelEvnt; + SiInfoEvnt siInfoEvnt; + SiFacEvnt siFacEvnt; + SiStaEvnt siStaEvnt; + } event; +} sngss7_event_data_t; + + typedef enum { - 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 +464,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); @@ -182,12 +478,44 @@ void sngss7_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); void sngss7_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); +ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); +ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiCnStEvnt *siCnStEvnt, uint8_t evntType); +ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); +ftdm_status_t handle_rel_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); +ftdm_status_t handle_rel_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiRelEvnt *siRelEvnt); +ftdm_status_t handle_dat_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiInfoEvnt *siInfoEvnt); +ftdm_status_t handle_fac_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); +ftdm_status_t handle_fac_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t evntType, SiFacEvnt *siFacEvnt); +ftdm_status_t handle_umsg_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit); +ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); + +ftdm_status_t handle_reattempt(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot_start(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot_stop(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cot(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_rsc_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_rsc_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_grs_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_blo_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_blo_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ubl_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); + uint8_t copy_cgPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum); uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum); uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum); 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 +527,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 +546,130 @@ 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][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ + break; \ + case 1: \ + ftdm_log_chan(fchan, FTDM_LOG_ALERT, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ + break; \ + case 2: \ + ftdm_log_chan(fchan, FTDM_LOG_CRIT, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ + break; \ + case 3: \ + ftdm_log_chan(fchan, FTDM_LOG_ERROR, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ + break; \ + case 4: \ + ftdm_log_chan(fchan, FTDM_LOG_WARNING, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ + break; \ + case 5: \ + ftdm_log_chan(fchan, FTDM_LOG_NOTICE, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ + break; \ + case 6: \ + ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ + break; \ + case 7: \ + ftdm_log_chan(fchan, FTDM_LOG_DEBUG, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, msg); \ + break; \ + default: \ + ftdm_log_chan(fchan, FTDM_LOG_INFO, "[CIC:%d][SPINSTID:%d][SUINSTID:%d]%s", \ + sngss7info->circuit->cic,sngss7info->spInstId,sngss7info->suInstId, 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: + */ +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index edaf36d644..4fac251c17 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -42,393 +42,449 @@ /******************************************************************************/ /* 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_grs (ftdm_channel_t * ftdmchan); +/******************************************************************************/ -void ft_to_sngss7_gra(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__); - - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; - SiConEvnt iam; - - sngss7_info->suInstId = get_unique_id(); - sngss7_info->spInstId = 0; - sngss7_info->spId = 1; - - memset(&iam, 0x0, sizeof(iam)); - - /* copy down the nature of connection indicators */ - iam.natConInd.eh.pres = PRSNT_NODEF; - iam.natConInd.satInd.pres = PRSNT_NODEF; - iam.natConInd.satInd.val = 0; - iam.natConInd.contChkInd.pres = PRSNT_NODEF; - iam.natConInd.contChkInd.val = 0x00; - iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF; - iam.natConInd.echoCntrlDevInd.val = 0x01; - - /* copy down the forward call indicators */ - iam.fwdCallInd.eh.pres = PRSNT_NODEF; - iam.fwdCallInd.natIntCallInd.pres = PRSNT_NODEF; - iam.fwdCallInd.natIntCallInd.val = 0x00; - iam.fwdCallInd.end2EndMethInd.pres = PRSNT_NODEF; - iam.fwdCallInd.end2EndMethInd.val = 0x00; - iam.fwdCallInd.intInd.pres = PRSNT_NODEF; - iam.fwdCallInd.intInd.val = 0x01; - iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF; - iam.fwdCallInd.end2EndInfoInd.val = 0x00; - iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtInd.val = 0x01; - iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtPrfInd.val = 0x02; - iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnAccInd.val = 0x01; - iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF; - iam.fwdCallInd.sccpMethInd.val = 0x00; - - /* copy down the calling number information */ - iam.cgPtyCat.eh.pres = PRSNT_NODEF; - iam.cgPtyCat.cgPtyCat.pres = PRSNT_NODEF; - iam.cgPtyCat.cgPtyCat.val = 0x0a; - - /* copy down the transmission medium requirements */ - iam.txMedReq.eh.pres = PRSNT_NODEF; - iam.txMedReq.trMedReq.pres = PRSNT_NODEF; - iam.txMedReq.trMedReq.val = 0; /* SPEECH = 0, 3.1Khz = 3, 64k unres = 2 */ - - /* copy down the called number information */ - copy_cdPtyNum_to_sngss7(&ftdmchan->caller_data, &iam.cdPtyNum); - - /* copy down the calling number information */ - copy_cgPtyNum_to_sngss7(&ftdmchan->caller_data, &iam.cgPtyNum); - - sng_cc_con_request(sngss7_info->spId, - sngss7_info->suInstId, - sngss7_info->spInstId, - sngss7_info->circuit->id, - &iam, - 0); - - SS7_MSG_TRACE("Transmitted IAM on CIC # %d\n", sngss7_info->circuit->cic); - - 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_ENTER (__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; + SiConEvnt iam; + + sngss7_info->suInstId = get_unique_id (); + sngss7_info->spInstId = 0; + sngss7_info->spId = 1; + + memset (&iam, 0x0, sizeof (iam)); + + /* copy down the nature of connection indicators */ + iam.natConInd.eh.pres = PRSNT_NODEF; + iam.natConInd.satInd.pres = PRSNT_NODEF; + iam.natConInd.satInd.val = 0; /* no satellite circuit */ + iam.natConInd.contChkInd.pres = PRSNT_NODEF; + iam.natConInd.contChkInd.val = CONTCHK_NOTREQ; + iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF; + iam.natConInd.echoCntrlDevInd.val = ECHOCDEV_INCL; + + /* copy down the forward call indicators */ + iam.fwdCallInd.eh.pres = PRSNT_NODEF; + iam.fwdCallInd.natIntCallInd.pres = PRSNT_NODEF; + iam.fwdCallInd.natIntCallInd.val = 0x00; + iam.fwdCallInd.end2EndMethInd.pres = PRSNT_NODEF; + iam.fwdCallInd.end2EndMethInd.val = E2EMTH_NOMETH; + iam.fwdCallInd.intInd.pres = PRSNT_NODEF; + iam.fwdCallInd.intInd.val = INTIND_NOINTW; + iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF; + iam.fwdCallInd.end2EndInfoInd.val = E2EINF_NOINFO; + iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; + iam.fwdCallInd.isdnUsrPrtInd.val = ISUP_USED; + iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF; + iam.fwdCallInd.isdnUsrPrtPrfInd.val = PREF_REQAW; + iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF; + iam.fwdCallInd.isdnAccInd.val = ISDNACC_ISDN; + iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF; + iam.fwdCallInd.sccpMethInd.val = SCCPMTH_NOIND; + + /* copy down the calling number information */ + iam.cgPtyCat.eh.pres = PRSNT_NODEF; + iam.cgPtyCat.cgPtyCat.pres = PRSNT_NODEF; + iam.cgPtyCat.cgPtyCat.val = CAT_ORD; /* ordinary suscriber */ + + /* copy down the transmission medium requirements */ + iam.txMedReq.eh.pres = PRSNT_NODEF; + iam.txMedReq.trMedReq.pres = PRSNT_NODEF; + iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability; + + /* copy down the called number information */ + copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum); + + /* copy down the calling number information */ + copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum); + + sng_cc_con_request (sngss7_info->spId, + sngss7_info->suInstId, + sngss7_info->spInstId, + sngss7_info->circuit->id, + &iam, + 0); + + SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx IAM\n"); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); + return; } /******************************************************************************/ -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 *sngss7_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 = sngss7_span->rx_grs.range; + + /* fill in the status */ + gra.rangStat.status.pres = PRSNT_NODEF; + gra.rangStat.status.len = ((sngss7_span->rx_grs.range + 1) >> 3) + (((sngss7_span->rx_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, + sngss7_span->rx_grs.circuit, + 0, + SIT_STA_GRSRSP, + &gra); + + SS7_INFO_CHAN(ftdmchan, "Tx GRA (%d:%d)\n", + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + sngss7_span->rx_grs.range)); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); + return; +} + +/******************************************************************************/ +void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan) +{ + SS7_FUNC_TRACE_ENTER (__FUNCTION__); + + sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + + SiStaEvnt grs; + + memset (&grs, 0x0, sizeof (grs)); + + grs.rangStat.eh.pres = PRSNT_NODEF; + grs.rangStat.range.pres = PRSNT_NODEF; + grs.rangStat.range.val = sngss7_span->tx_grs.range; + + sng_cc_sta_request (1, + 0, + 0, + sngss7_span->tx_grs.circuit, + 0, + SIT_STA_GRSREQ, + &grs); + + SS7_INFO_CHAN(ftdmchan, "Tx GRS (%d:%d)\n", + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + sngss7_span->tx_grs.range)); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); +return; +} + /******************************************************************************/ /* For Emacs: * Local Variables: @@ -441,4 +497,3 @@ void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan) * vim:set softtabstop=4 shiftwidth=4 tabstop=4: */ /******************************************************************************/ - diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c new file mode 100644 index 0000000000..305e1a50f5 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2009 Konrad Hammel + * All rights reserved. + * + * Redistribution and use in source and binary forms|with or without + * modification|are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice|this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice|this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT + * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, + * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* INCLUDE ********************************************************************/ +#include "ftmod_sangoma_ss7_main.h" +/******************************************************************************/ + +/* DEFINES ********************************************************************/ +/******************************************************************************/ + +/* GLOBALS ********************************************************************/ +/******************************************************************************/ + +/* PROTOTYPES *****************************************************************/ +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: + */ +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c new file mode 100644 index 0000000000..f760ac4a20 --- /dev/null +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sts.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2009 Konrad Hammel + * All rights reserved. + * + * Redistribution and use in source and binary forms|with or without + * modification|are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above copyright + * notice|this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice|this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * * Neither the name of the original author; nor the names of any contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT + * LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL, + * EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* INCLUDE ********************************************************************/ +#include "ftmod_sangoma_ss7_main.h" +/******************************************************************************/ + +/* DEFINES ********************************************************************/ +/******************************************************************************/ + +/* GLOBALS ********************************************************************/ +/******************************************************************************/ + +/* PROTOTYPES *****************************************************************/ +/******************************************************************************/ + +/* 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: + */ +/******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 7852829295..97957f3c82 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -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); } /******************************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c index 2d3aed66fb..aa639d1c3a 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c @@ -41,10 +41,10 @@ /* GLOBALS ********************************************************************/ typedef struct sng_timeslot { - int channel; - int siglink; - int gap; - int hole; + int channel; + int siglink; + int gap; + int hole; }sng_timeslot_t; /******************************************************************************/ @@ -55,8 +55,7 @@ static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup); static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets); static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset); -static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp1Link_t *mtp1_link, - sng_mtp2Link_t *mtp2_link, sng_mtp3Link_t *mtp3_link); +static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *mtpLink); static int ftmod_ss7_parse_mtp_routes(ftdm_conf_node_t *mtp_routes); static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route); @@ -64,14 +63,15 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route); static int ftmod_ss7_parse_isup_interfaces(ftdm_conf_node_t *isup_interfaces); static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface); -static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1Link_t *mtp1_link); -static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2Link_t *mtp2_link); -static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3Link_t *mtp3_link); -static int ftmod_ss7_fill_in_mtp3_linkset(sng_mtp3LinkSet_t *mtp3_linkset); -static int ftmod_ss7_fill_in_mtp3_route(sng_mtp3Route_t *mtp3_route); -static int ftmod_ss7_fill_in_mtp3_isup_interface(sng_mtp3Route_t *mtp3_route); -static int ftmod_ss7_fill_in_isup_interface(sng_isupInterface_t *sng_isup); -static int ftmod_ss7_fill_in_isup_cc_interface(sng_isup_cc_t *sng_cc); +static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink); + +static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet); + +static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route); +static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route); + +static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup); +static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap); static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf); @@ -83,736 +83,750 @@ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot); /* FUNCTIONS ******************************************************************/ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *span) { - int i = 0; - int x = 0; - const char *var = NULL; - const char *val = NULL; - ftdm_conf_node_t *ptr = NULL; - sng_mtp3Route_t self_route; - char ch_map[MAX_CIC_MAP_LENGTH]; - int typeCntrl = 0; - int cicbase = 0; + int i = 0; + int x = 0; + const char *var = NULL; + const char *val = NULL; + ftdm_conf_node_t *ptr = NULL; + sng_route_t self_route; + char ch_map[MAX_CIC_MAP_LENGTH]; + int typeCntrl = 0; + int cicbase = 0; - /* clean out the self route */ - memset(&self_route, 0x0, sizeof(sng_mtp3Route_t)); + /* clean out the self route */ + memset(&self_route, 0x0, sizeof(sng_route_t)); - var = ftdm_parameters[i].var; - val = ftdm_parameters[i].val; - ptr = (ftdm_conf_node_t *)ftdm_parameters[i].ptr; + var = ftdm_parameters[i].var; + val = ftdm_parameters[i].val; + ptr = (ftdm_conf_node_t *)ftdm_parameters[i].ptr; - /* confirm that the first parameter is the "confnode" */ - if (!strcasecmp(var, "confnode")) { - /* parse the confnode and fill in the global libsng_ss7 config structure */ - if (ftmod_ss7_parse_sng_isup(ptr)) { - SS7_ERROR("Failed to parse the \"confnode\"!\n"); - goto ftmod_ss7_parse_xml_error; - } - } else { - /* ERROR...exit */ - SS7_ERROR("The \"confnode\" configuration was not the first parameter!\n"); - SS7_ERROR("\tFound \"%s\" in the first slot\n", var); - goto ftmod_ss7_parse_xml_error; - } + /* confirm that the first parameter is the "confnode" */ + if (!strcasecmp(var, "confnode")) { + /* parse the confnode and fill in the global libsng_ss7 config structure */ + if (ftmod_ss7_parse_sng_isup(ptr)) { + SS7_ERROR("Failed to parse the \"confnode\"!\n"); + goto ftmod_ss7_parse_xml_error; + } + } else { + /* ERROR...exit */ + SS7_ERROR("The \"confnode\" configuration was not the first parameter!\n"); + SS7_ERROR("\tFound \"%s\" in the first slot\n", var); + goto ftmod_ss7_parse_xml_error; + } - i++; - while (ftdm_parameters[i].var != NULL) { + i++; + while (ftdm_parameters[i].var != NULL) { - var = ftdm_parameters[i].var; - val = ftdm_parameters[i].val; + var = ftdm_parameters[i].var; + val = ftdm_parameters[i].val; - if (!strcasecmp(var, "ch_map")) { - /**********************************************************************/ - strcpy(ch_map, val); - SS7_DEBUG("\tFound channel map \"%s\"\n", ch_map); - /**********************************************************************/ - } else if (!strcasecmp(var, "typeCntrl")) { - if (!strcasecmp(val, "bothway")) { - typeCntrl = SNG_BOTHWAY; - SS7_DEBUG("\tFound control type \"bothway\"\n"); - } else if (!strcasecmp(val, "incoming")) { - typeCntrl = SNG_INCOMING; - SS7_DEBUG("\tFound control type \"incoming\"\n"); - } else if (!strcasecmp(val, "outgoing")) { - typeCntrl = SNG_OUTGOING; - SS7_DEBUG("\tFound control type \"outgoing\"\n"); - } else if (!strcasecmp(val, "controlled")) { - typeCntrl = SNG_CONTROLLED; - SS7_DEBUG("\tFound control type \"controlled\"\n"); - } else if (!strcasecmp(val, "controlling")) { - typeCntrl = SNG_CONTROLLING; - SS7_DEBUG("\tFound control type \"controlling\"\n"); - } else { - SS7_ERROR("Found invalid circuit control type \"%s\"!", val); - goto ftmod_ss7_parse_xml_error; - } - /**********************************************************************/ - } else if (!strcasecmp(var, "cicbase")) { - cicbase = atoi(val); - SS7_DEBUG("\tFound cicbase = %d\n", cicbase); - /**********************************************************************/ - } else if (!strcasecmp(var, "dialplan")) { - /* do i give a shit about this??? */ - /**********************************************************************/ - } else if (!strcasecmp(var, "context")) { - /* do i give a shit about this??? */ - /**********************************************************************/ - } else if (!strcasecmp(var, "isup_interface")) { - /* go through all the existing interfaces and see if we find a match */ - x = 1; - while (g_ftdm_sngss7_data.cfg.isupInterface[x].id != 0) { - if (!strcasecmp(g_ftdm_sngss7_data.cfg.isupInterface[x].name, val)) { - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - x++; - } - SS7_DEBUG("\tFound isup_interface = %s\n",g_ftdm_sngss7_data.cfg.isupInterface[x].name ); - /**********************************************************************/ - } else { - SS7_ERROR("Unknown parameter found =\"%s\"...ignoring it!\n", var); - /**********************************************************************/ - } + if (!strcasecmp(var, "ch_map")) { + /**********************************************************************/ + strcpy(ch_map, val); + SS7_DEBUG("\tFound channel map \"%s\"\n", ch_map); + /**********************************************************************/ + } else if (!strcasecmp(var, "typeCntrl")) { + if (!strcasecmp(val, "bothway")) { + typeCntrl = BOTHWAY; + SS7_DEBUG("\tFound control type \"bothway\"\n"); + } else if (!strcasecmp(val, "incoming")) { + typeCntrl = INCOMING; + SS7_DEBUG("\tFound control type \"incoming\"\n"); + } else if (!strcasecmp(val, "outgoing")) { + typeCntrl = OUTGOING; + SS7_DEBUG("\tFound control type \"outgoing\"\n"); + } else if (!strcasecmp(val, "controlled")) { + typeCntrl = CONTROLLED; + SS7_DEBUG("\tFound control type \"controlled\"\n"); + } else if (!strcasecmp(val, "controlling")) { + typeCntrl = CONTROLLING; + SS7_DEBUG("\tFound control type \"controlling\"\n"); + } else { + SS7_ERROR("Found invalid circuit control type \"%s\"!", val); + goto ftmod_ss7_parse_xml_error; + } + /**********************************************************************/ + } else if (!strcasecmp(var, "cicbase")) { + cicbase = atoi(val); + SS7_DEBUG("\tFound cicbase = %d\n", cicbase); + /**********************************************************************/ + } else if (!strcasecmp(var, "dialplan")) { + /* do i give a shit about this??? */ + /**********************************************************************/ + } else if (!strcasecmp(var, "context")) { + /* do i give a shit about this??? */ + /**********************************************************************/ + } else if (!strcasecmp(var, "isup_interface")) { + /* go through all the existing interfaces and see if we find a match */ + x = 1; + while (g_ftdm_sngss7_data.cfg.isupIntf[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.isupIntf[x].name, val)) { + /* we have a match so break out of this loop */ + break; + } + /* move on to the next one */ + x++; + } + SS7_DEBUG("\tFound isup_interface = %s\n",g_ftdm_sngss7_data.cfg.isupIntf[x].name ); + /**********************************************************************/ + } else { + SS7_ERROR("Unknown parameter found =\"%s\"...ignoring it!\n", var); + /**********************************************************************/ + } - i++; - } /* while (ftdm_parameters[i].var != NULL) */ + i++; + } /* while (ftdm_parameters[i].var != NULL) */ - /* setup the self mtp3 route */ - i = g_ftdm_sngss7_data.cfg.isupInterface[x].mtp3RouteId; + /* setup the self mtp3 route */ + i = g_ftdm_sngss7_data.cfg.isupIntf[x].mtpRouteId; - if(ftmod_ss7_fill_in_self_route(atoi(g_ftdm_sngss7_data.cfg.spc), - g_ftdm_sngss7_data.cfg.mtp3Route[i].linkType, - g_ftdm_sngss7_data.cfg.isupInterface[x].switchType, - g_ftdm_sngss7_data.cfg.mtp3Route[i].ssf)) { - SS7_ERROR("Failed to fill in self route structure!\n"); - goto ftmod_ss7_parse_xml_error; - } + if(ftmod_ss7_fill_in_self_route(g_ftdm_sngss7_data.cfg.isupIntf[x].spc, + g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType, + g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType, + g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf)) { + + SS7_ERROR("Failed to fill in self route structure!\n"); + goto ftmod_ss7_parse_xml_error; + + } - /* setup the circuits structure */ - if(ftmod_ss7_fill_in_circuits(ch_map, - cicbase, - typeCntrl, - g_ftdm_sngss7_data.cfg.isupInterface[x].id, - span)) { - SS7_ERROR("Failed to fill in circuits structure!\n"); - goto ftmod_ss7_parse_xml_error; - } + /* setup the circuits structure */ + if(ftmod_ss7_fill_in_circuits(ch_map, cicbase, typeCntrl, + g_ftdm_sngss7_data.cfg.isupIntf[x].id, span)) { + SS7_ERROR("Failed to fill in circuits structure!\n"); + goto ftmod_ss7_parse_xml_error; + } - return FTDM_SUCCESS; + return FTDM_SUCCESS; ftmod_ss7_parse_xml_error: - return FTDM_FAIL; + return FTDM_FAIL; } /******************************************************************************/ static int ftmod_ss7_parse_sng_isup(ftdm_conf_node_t *sng_isup) { - ftdm_conf_node_t *mtp_linksets = NULL; - ftdm_conf_node_t *mtp_routes = NULL; - ftdm_conf_node_t *isup_interfaces = NULL; - ftdm_conf_node_t *tmp_node = NULL; + ftdm_conf_node_t *mtp_linksets = NULL; + ftdm_conf_node_t *mtp_routes = NULL; + ftdm_conf_node_t *isup_interfaces = NULL; + ftdm_conf_node_t *tmp_node = NULL; - /* confirm that we are looking at sng_isup */ - if (strcasecmp(sng_isup->name, "sng_isup")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_isup\"!\n",sng_isup->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"sng_isup\"...\n"); - } + /* confirm that we are looking at sng_isup */ + if (strcasecmp(sng_isup->name, "sng_isup")) { + SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"sng_isup\"!\n",sng_isup->name); + return FTDM_FAIL; + } else { + SS7_DEBUG("Parsing \"sng_isup\"...\n"); + } - /* extract the 3 main sections of the sng_isup block */ - tmp_node = sng_isup->child; - while (tmp_node != NULL) { + /* extract the 3 main sections of the sng_isup block */ + tmp_node = sng_isup->child; + while (tmp_node != NULL) { - if (!strcasecmp(tmp_node->name, "mtp_linksets")) { - if (mtp_linksets == NULL) { - mtp_linksets = tmp_node; - SS7_DEBUG("\tFound a \"mtp_linksets section!\n"); - } else { - SS7_ERROR("\tFound a second \"mtp_linksets\" section!\n"); - return FTDM_FAIL; - } - } else if (!strcasecmp(tmp_node->name, "mtp_routes")) { - if (mtp_routes == NULL) { - mtp_routes = tmp_node; - SS7_DEBUG("\tFound a \"mtp_routes\" section!\n"); - } else { - SS7_ERROR("\tFound a second \"mtp_routes\" section!\n"); - return FTDM_FAIL; - } - } else if (!strcasecmp(tmp_node->name, "isup_interfaces")) { - if (isup_interfaces == NULL) { - isup_interfaces = tmp_node; - SS7_DEBUG("\tFound a \"isup_interfaces\" section!\n"); - } else { - SS7_ERROR("\tFound a second \"isup_interfaces\" section\n!"); - return FTDM_FAIL; - } - } else { - SS7_ERROR("\tFound an unknown section \"%s\"!\n", tmp_node->name); - return FTDM_FAIL; - } + if (!strcasecmp(tmp_node->name, "mtp_linksets")) { + if (mtp_linksets == NULL) { + mtp_linksets = tmp_node; + SS7_DEBUG("\tFound a \"mtp_linksets section!\n"); + } else { + SS7_ERROR("\tFound a second \"mtp_linksets\" section!\n"); + return FTDM_FAIL; + } + } else if (!strcasecmp(tmp_node->name, "mtp_routes")) { + if (mtp_routes == NULL) { + mtp_routes = tmp_node; + SS7_DEBUG("\tFound a \"mtp_routes\" section!\n"); + } else { + SS7_ERROR("\tFound a second \"mtp_routes\" section!\n"); + return FTDM_FAIL; + } + } else if (!strcasecmp(tmp_node->name, "isup_interfaces")) { + if (isup_interfaces == NULL) { + isup_interfaces = tmp_node; + SS7_DEBUG("\tFound a \"isup_interfaces\" section!\n"); + } else { + SS7_ERROR("\tFound a second \"isup_interfaces\" section\n!"); + return FTDM_FAIL; + } + } else { + SS7_ERROR("\tFound an unknown section \"%s\"!\n", tmp_node->name); + return FTDM_FAIL; + } - /* go to the next sibling */ - tmp_node = tmp_node->next; + /* go to the next sibling */ + tmp_node = tmp_node->next; - } /* while (tmp_node != NULL) */ + } /* while (tmp_node != NULL) */ - /* now try to parse the sections */ - if (ftmod_ss7_parse_mtp_linksets(mtp_linksets)) { - SS7_ERROR("Failed to parse \"mtp_linksets\"!\n"); - return FTDM_FAIL; - } + /* now try to parse the sections */ + if (ftmod_ss7_parse_mtp_linksets(mtp_linksets)) { + SS7_ERROR("Failed to parse \"mtp_linksets\"!\n"); + return FTDM_FAIL; + } - if (ftmod_ss7_parse_mtp_routes(mtp_routes)) { - SS7_ERROR("Failed to parse \"mtp_routes\"!\n"); - return FTDM_FAIL; - } + if (ftmod_ss7_parse_mtp_routes(mtp_routes)) { + SS7_ERROR("Failed to parse \"mtp_routes\"!\n"); + return FTDM_FAIL; + } - if (ftmod_ss7_parse_isup_interfaces(isup_interfaces)) { - SS7_ERROR("Failed to parse \"isup_interfaces\"!\n"); - return FTDM_FAIL; - } + if (ftmod_ss7_parse_isup_interfaces(isup_interfaces)) { + SS7_ERROR("Failed to parse \"isup_interfaces\"!\n"); + return FTDM_FAIL; + } - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static int ftmod_ss7_parse_mtp_linksets(ftdm_conf_node_t *mtp_linksets) { - ftdm_conf_node_t *mtp_linkset = NULL; + ftdm_conf_node_t *mtp_linkset = NULL; - /* confirm that we are looking at mtp_linksets */ - if (strcasecmp(mtp_linksets->name, "mtp_linksets")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linksets\"!\n",mtp_linksets->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_linksets\"...\n"); - } + /* confirm that we are looking at mtp_linksets */ + if (strcasecmp(mtp_linksets->name, "mtp_linksets")) { + SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linksets\"!\n",mtp_linksets->name); + return FTDM_FAIL; + } else { + SS7_DEBUG("Parsing \"mtp_linksets\"...\n"); + } - /* extract the mtp_links */ - mtp_linkset = mtp_linksets->child; + /* extract the mtp_links */ + mtp_linkset = mtp_linksets->child; - /* run through all of the mtp_linksets found */ - while (mtp_linkset != NULL) { - /* try to the parse mtp_linkset */ - if (ftmod_ss7_parse_mtp_linkset(mtp_linkset)) { - SS7_ERROR("Failed to parse \"mtp_linkset\"!\n"); - return FTDM_FAIL; - } + /* run through all of the mtp_linksets found */ + while (mtp_linkset != NULL) { + /* try to the parse mtp_linkset */ + if (ftmod_ss7_parse_mtp_linkset(mtp_linkset)) { + SS7_ERROR("Failed to parse \"mtp_linkset\"!\n"); + return FTDM_FAIL; + } - /* move on to the next linkset */ - mtp_linkset = mtp_linkset->next; + /* move on to the next linkset */ + mtp_linkset = mtp_linkset->next; - } /* while (mtp_linkset != NULL) */ + } /* while (mtp_linkset != NULL) */ - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset) { - ftdm_conf_parameter_t *parm = mtp_linkset->parameters; - int num_parms = mtp_linkset->n_parameters; - ftdm_conf_node_t *mtp_link = NULL; - sng_mtp1Link_t mtp1_link[MAX_MTP_LINKS]; - sng_mtp2Link_t mtp2_link[MAX_MTP_LINKS]; - sng_mtp3Link_t mtp3_link[MAX_MTP_LINKS]; - sng_mtp3LinkSet_t mtp3_linkset; - int count; - int i; + ftdm_conf_parameter_t *parm = mtp_linkset->parameters; + int num_parms = mtp_linkset->n_parameters; + ftdm_conf_node_t *mtp_link = NULL; + sng_mtp_link_t mtpLink[MAX_MTP_LINKS+1]; + sng_link_set_t mtpLinkSet; + int count; + int i; - /* initialize the mtp_link structures */ - for (i = 0; i < MAX_MTP_LINKS; i++) { - memset(&mtp1_link[i], 0x0, sizeof(mtp1_link[i])); - memset(&mtp2_link[i], 0x0, sizeof(mtp2_link[i])); - memset(&mtp3_link[i], 0x0, sizeof(mtp3_link[i])); - } - memset(&mtp3_linkset, 0x0, sizeof(mtp3_linkset)); + /* initialize the mtp_link structures */ + for (i = 0; i < (MAX_MTP_LINKS + 1); i++) { + memset(&mtpLink[i], 0x0, sizeof(mtpLink[i])); + } + memset(&mtpLinkSet, 0x0, sizeof(mtpLinkSet)); - /* confirm that we are looking at mtp_linkset */ - if (strcasecmp(mtp_linkset->name, "mtp_linkset")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linkset\"!\n",mtp_linkset->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_linkset\"...\n"); - } + /* confirm that we are looking at mtp_linkset */ + if (strcasecmp(mtp_linkset->name, "mtp_linkset")) { + SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_linkset\"!\n",mtp_linkset->name); + return FTDM_FAIL; + } else { + SS7_DEBUG("Parsing \"mtp_linkset\"...\n"); + } - /* extract all the information from the parameters */ - for (i = 0; i < num_parms; i++) { - /**********************************************************************/ - if (!strcasecmp(parm->var, "name")) { - strcpy((char *)mtp3_linkset.name, parm->val); - SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtp3_linkset.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "apc")) { - mtp3_linkset.apc = atoi(parm->val); - SS7_DEBUG("\tFound mtp3_linkSet->apc = %d\n", mtp3_linkset.apc); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "minActive")) { - mtp3_linkset.minActive = atoi(parm->val); - SS7_DEBUG("\tFound mtp3_linkSet->minActive = %d\n", mtp3_linkset.minActive); - /**********************************************************************/ - } else { - SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; - } + /* extract all the information from the parameters */ + for (i = 0; i < num_parms; i++) { + /**********************************************************************/ + if (!strcasecmp(parm->var, "name")) { + strcpy((char *)mtpLinkSet.name, parm->val); + SS7_DEBUG("\tFound an \"mtp_linkset\" named = %s\n", mtpLinkSet.name); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "apc")) { + mtpLinkSet.apc = atoi(parm->val); + SS7_DEBUG("\tFoundmtpLinkSet->apc = %d\n", mtpLinkSet.apc); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "minActive")) { + mtpLinkSet.minActive = atoi(parm->val); + SS7_DEBUG("\tFoundmtpLinkSet->minActive = %d\n", mtpLinkSet.minActive); + /**********************************************************************/ + } else { + SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); + return FTDM_FAIL; + } - /* move to the next parmeter */ - parm = parm + 1; + /* move to the next parmeter */ + parm = parm + 1; - } /* for (i = 0; i < num_parms; i++) */ + } /* for (i = 0; i < num_parms; i++) */ - /* grab the first mtp-link (which sits below the mtp_links section) */ - mtp_link = mtp_linkset->child->child; + /* grab the first mtp-link (which sits below the mtp_links section) */ + mtp_link = mtp_linkset->child->child; - /* initalize the link counter */ - count = 0; + /* initalize the link counter */ + count = 0; - /* run through all of the mtp_links found */ - while (mtp_link != NULL) { - /* try to the parse mtp_linkset */ - if (ftmod_ss7_parse_mtp_link(mtp_link, &mtp1_link[count], &mtp2_link[count], &mtp3_link[count] )) { - SS7_ERROR("Failed to parse \"mtp_link\"!\n"); - return FTDM_FAIL; - } + /* run through all of the mtp_links found */ + while (mtp_link != NULL) { + /* try to the parse mtp_linkset */ + if (ftmod_ss7_parse_mtp_link(mtp_link, &mtpLink[count] )) { + SS7_ERROR("Failed to parse \"mtp_link\"!\n"); + return FTDM_FAIL; + } - /* incremenet the link counter */ - count++; + /* incremenet the link counter */ + count++; - /* move on to the next link */ - mtp_link = mtp_link->next; + /* move on to the next link */ + mtp_link = mtp_link->next; - } /* while (mtp_link != NULL) */ + } /* while (mtp_link != NULL) */ - /* confirm we have the right number of links */ - if (count < 1 || count > 15 ) { - SS7_ERROR("Invalid number of mtp_links found (%d)\n", count); - return FTDM_FAIL; - } else { - mtp3_linkset.numLinks = count; - } + /* confirm we have the right number of links */ + if (count < 1 || count > 15 ) { + SS7_ERROR("Invalid number of mtp_links found (%d)\n", count); + return FTDM_FAIL; + } else { + mtpLinkSet.numLinks = count; + } - /* now we need to see if this linkset exists already or not and grab an Id */ - i = 1; - while (g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].id != 0) { - if (!strcasecmp((const char *)g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].name, (const char *)mtp3_linkset.name)) { - /* we've found the linkset...so it has already been configured */ - break; - } - i++; - /* add in error check to make sure we don't go out-of-bounds */ - } + /* now we need to see if this linkset exists already or not and grab an Id */ + i = 1; + while (g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id != 0) { + if (!strcasecmp((const char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (const char *)mtpLinkSet.name)) { + /* we've found the linkset...so it has already been configured */ + break; + } + i++; + /* add in error check to make sure we don't go out-of-bounds */ + } - /* if the id value is 0 that means we didn't find the linkset */ - if (g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].id == 0) { - mtp3_linkset.id = i; - SS7_DEBUG("found new mtp3_linkset, id is = %d\n", mtp3_linkset.id); - } else { - mtp3_linkset.id = i; - SS7_DEBUG("found existing mtp3_linkset, id is = %d\n", mtp3_linkset.id); - } + /* if the id value is 0 that means we didn't find the linkset */ + if (g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id == 0) { + mtpLinkSet.id = i; + SS7_DEBUG("found new mtpLinkSet, id is = %d\n", mtpLinkSet.id); + } else { + mtpLinkSet.id = i; + SS7_DEBUG("found existing mtpLinkSet, id is = %d\n", mtpLinkSet.id); + } - /* we now have all the information to fill in the Libsng_ss7 structures */ - i = 0; - count = 0; - while (mtp1_link[i].span != 0 ){ - /* fill in the mtp1 link structure */ - mtp2_link[i].spId = ftmod_ss7_fill_in_mtp1_link(&mtp1_link[i]); - /* fill in the mtp2 link structure */ - mtp3_link[i].mtp2LinkId = ftmod_ss7_fill_in_mtp2_link(&mtp2_link[i]); - /* have to grab a couple of values from the linkset */ - mtp3_link[i].apc = mtp3_linkset.apc; - mtp3_link[i].linkSetId = mtp3_linkset.id; - /* fill in the mtp3 link structure */ - mtp3_linkset.links[count] = ftmod_ss7_fill_in_mtp3_link(&mtp3_link[i]); - /* increment the links counter */ - count++; - /* increment the index value */ - i++; - } + /* we now have all the information to fill in the Libsng_ss7 structures */ + i = 0; + count = 0; + while (mtpLink[i].mtp1.span != 0 ){ - ftmod_ss7_fill_in_mtp3_linkset(&mtp3_linkset); + /* have to grab a couple of values from the linkset */ + mtpLink[i].mtp3.apc = mtpLinkSet.apc; + mtpLink[i].mtp3.linkSetId = mtpLinkSet.id; - return FTDM_SUCCESS; + /* fill in the mtplink structure */ + mtpLinkSet.links[count] = ftmod_ss7_fill_in_mtpLink(&mtpLink[i]); + + /* increment the links counter */ + count++; + + /* increment the index value */ + i++; + } + + ftmod_ss7_fill_in_mtpLinkSet(&mtpLinkSet); + + return FTDM_SUCCESS; } /******************************************************************************/ -static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp1Link_t *mtp1_link, - sng_mtp2Link_t *mtp2_link, sng_mtp3Link_t *mtp3_link) +static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t *mtpLink) { - ftdm_conf_parameter_t *parm = mtp_link->parameters; - int num_parms = mtp_link->n_parameters; - int i; - - /* confirm that we are looking at an mtp_link */ - if (strcasecmp(mtp_link->name, "mtp_link")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_link\"!\n",mtp_link->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_link\"...\n"); - } - - for (i = 0; i < num_parms; i++) { - /* try to match the parameter to what we expect */ - /**********************************************************************/ - if (!strcasecmp(parm->var, "name")) { - strcpy((char *)mtp1_link->name, parm->val); - strcpy((char *)mtp2_link->name, parm->val); - strcpy((char *)mtp3_link->name, parm->val); - SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtp1_link->name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "span")) { - mtp1_link->span = atoi(parm->val); - SS7_DEBUG("\tFound mtp1_link->span = %d\n", mtp1_link->span); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "chan")) { - mtp1_link->chan = atoi(parm->val); - SS7_DEBUG("\tFound mtp1_link->chan = %d\n", mtp1_link->chan); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "span")) { - mtp1_link->span = atoi(parm->val); - SS7_DEBUG("\tFound mtp1_link->span = %d\n", mtp1_link->span); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "errorType")) { - if (!strcasecmp(parm->val, "basic")) { - mtp2_link->errorType = SNG_BASIC_ERR; - } else if (!strcasecmp(parm->val, "pcr")) { - mtp2_link->errorType = SNG_PCR_ERR; - } else { - SS7_ERROR("\tFound an invalid \"errorType\" = %s\n", parm->var); - return FTDM_FAIL; - } - SS7_DEBUG("\tFound mtp2_link->errorType=%s\n", parm->val); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "lssuLength")) { - mtp2_link->lssuLength = atoi(parm->val); - if ((mtp2_link->lssuLength != 1) && (mtp2_link->lssuLength != 2)) { - SS7_ERROR("\tFound an invalid \"lssuLength\" = %d\n", mtp2_link->lssuLength); - return FTDM_FAIL; - } else { - SS7_DEBUG("\tFound mtp2_link->lssuLength=%d\n", mtp2_link->lssuLength); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "priority")) { - mtp3_link->priority = atoi(parm->val); - if ((mtp3_link->priority == 0) || (mtp3_link->priority == 1) || - (mtp3_link->priority == 2) || (mtp3_link->priority == 3)) { - SS7_DEBUG("\tFound mtp3_link->priority = %d\n",mtp3_link->priority); - } else { - SS7_ERROR("\tFound an invalid \"priority\"=%d\n", mtp3_link->priority); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "linkType")) { - if (!strcasecmp(parm->val, "itu92")) { - mtp2_link->linkType = SNG_MTP2_ITU92; - mtp3_link->linkType = SNG_MTP3_ITU92; - SS7_DEBUG("\tFound mtp3_link->linkType = \"ITU92\"\n"); - } else if (!strcasecmp(parm->val, "itu88")) { - mtp2_link->linkType = SNG_MTP2_ITU88; - mtp3_link->linkType = SNG_MTP3_ITU88; - SS7_DEBUG("\tFound mtp3_link->linkType = \"ITU88\"\n"); - } else { - SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "switchType")) { - if (!strcasecmp(parm->val, "itu97")) { - mtp3_link->switchType = SNG_ISUP_ITU97; - SS7_DEBUG("\tFound mtp3_link->switchType = \"ITU97\"\n"); - } else if (!strcasecmp(parm->val, "itu88")) { - mtp3_link->switchType = SNG_ISUP_ITU88; - SS7_DEBUG("\tFound mtp3_link->switchType = \"ITU88\"\n"); - } else if (!strcasecmp(parm->val, "itu92")) { - mtp3_link->switchType = SNG_ISUP_ITU92; - SS7_DEBUG("\tFound mtp3_link->switchType = \"ITU92\"\n"); - } else if (!strcasecmp(parm->val, "itu00")) { - mtp3_link->switchType = SNG_ISUP_ITU00; - SS7_DEBUG("\tFound mtp3_link->switchType = \"ITU00\"\n"); - } else if (!strcasecmp(parm->val, "ETSIV2")) { - mtp3_link->switchType = SNG_ISUP_ETSIV2; - SS7_DEBUG("\tFound mtp3_link->switchType = \"ETSIV2\"\n"); - } else if (!strcasecmp(parm->val, "ETSIV3")) { - mtp3_link->switchType = SNG_ISUP_ETSIV3; - SS7_DEBUG("\tFound mtp3_link->switchType = \"ETSIV3\"\n"); - } else if (!strcasecmp(parm->val, "UK")) { - mtp3_link->switchType = SNG_ISUP_UK; - SS7_DEBUG("\tFound mtp3_link->switchType = \"UK\"\n"); - } else if (!strcasecmp(parm->val, "RUSSIA")) { - mtp3_link->switchType = SNG_ISUP_RUSSIA; - SS7_DEBUG("\tFound mtp3_link->switchType = \"RUSSIA\"\n"); - } else if (!strcasecmp(parm->val, "INDIA")) { - mtp3_link->switchType = SNG_ISUP_INDIA; - SS7_DEBUG("\tFound mtp3_link->switchType = \"INDIA\"\n"); - } else { - SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "ssf")) { - if (!strcasecmp(parm->val, "nat")) { - mtp3_link->ssf = SNG_SSF_NAT; - } else if (!strcasecmp(parm->val, "int")) { - mtp3_link->ssf = SNG_SSF_INTER; - } else { - SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val); - return FTDM_FAIL; - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "slc")) { - mtp3_link->lnkTstSLC = atoi(parm->val); - SS7_DEBUG("\tFound mtp3_link->slc = \"%d\"\n",mtp3_link->lnkTstSLC); - /**********************************************************************/ - } else { - SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; - } - - /* move to the next parameter */ - parm = parm + 1; - } - - return FTDM_SUCCESS; + ftdm_conf_parameter_t *parm = mtp_link->parameters; + int num_parms = mtp_link->n_parameters; + int i; + + /* confirm that we are looking at an mtp_link */ + if (strcasecmp(mtp_link->name, "mtp_link")) { + SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_link\"!\n",mtp_link->name); + return FTDM_FAIL; + } else { + SS7_DEBUG("Parsing \"mtp_link\"...\n"); + } + + for (i = 0; i < num_parms; i++) { + /* try to match the parameter to what we expect */ + /**********************************************************************/ + if (!strcasecmp(parm->var, "name")) { + strcpy((char *)mtpLink->name, parm->val); + SS7_DEBUG("\tFound an \"mtp_link\" named = %s\n", mtpLink->name); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "span")) { + mtpLink->mtp1.span = atoi(parm->val); + SS7_DEBUG("\tFound mtpLink->span = %d\n", mtpLink->mtp1.span); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "chan")) { + mtpLink->mtp1.chan = atoi(parm->val); + SS7_DEBUG("\tFound mtpLink->chan = %d\n", mtpLink->mtp1.chan); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "errorType")) { + if (!strcasecmp(parm->val, "basic")) { + mtpLink->mtp2.errorType = SD_ERR_NRM; + } else if (!strcasecmp(parm->val, "pcr")) { + mtpLink->mtp2.errorType = SD_ERR_CYC; + } else { + SS7_ERROR("\tFound an invalid \"errorType\" = %s\n", parm->var); + return FTDM_FAIL; + } + SS7_DEBUG("\tFound mtpLink->errorType=%s\n", parm->val); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "lssuLength")) { + mtpLink->mtp2.lssuLength = atoi(parm->val); + if ((mtpLink->mtp2.lssuLength != 1) && (mtpLink->mtp2.lssuLength != 2)) { + SS7_ERROR("\tFound an invalid \"lssuLength\" = %d\n", mtpLink->mtp2.lssuLength); + return FTDM_FAIL; + } else { + SS7_DEBUG("\tFound mtpLink->lssuLength=%d\n", mtpLink->mtp2.lssuLength); + } + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "priority")) { + mtpLink->mtp3.priority = atoi(parm->val); + if ((mtpLink->mtp3.priority == 0) || (mtpLink->mtp3.priority == 1) || + (mtpLink->mtp3.priority == 2) || (mtpLink->mtp3.priority == 3)) { + SS7_DEBUG("\tFound mtpLink->priority = %d\n",mtpLink->mtp3.priority); + } else { + SS7_ERROR("\tFound an invalid \"priority\"=%d\n",mtpLink->mtp3.priority); + return FTDM_FAIL; + } + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "linkType")) { + if (!strcasecmp(parm->val, "itu92")) { + mtpLink->mtp2.linkType = LSD_SW_ITU92; + mtpLink->mtp3.linkType = LSN_SW_ITU; + SS7_DEBUG("\tFoundmtpLink->linkType = \"ITU92\"\n"); + } else if (!strcasecmp(parm->val, "itu88")) { + mtpLink->mtp2.linkType = LSD_SW_ITU88; + mtpLink->mtp3.linkType = LSN_SW_ITU; + SS7_DEBUG("\tFoundmtpLink->linkType = \"ITU88\"\n"); + } else if (!strcasecmp(parm->val, "ansi96")) { + mtpLink->mtp2.linkType = LSD_SW_ANSI92; + mtpLink->mtp3.linkType = LSN_SW_ANS96; + SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI96\"\n"); + } else if (!strcasecmp(parm->val, "ansi92")) { + mtpLink->mtp2.linkType = LSD_SW_ANSI92; + mtpLink->mtp3.linkType = LSN_SW_ANS; + SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI92\"\n"); + } else if (!strcasecmp(parm->val, "ansi88")) { + mtpLink->mtp2.linkType = LSD_SW_ANSI88; + mtpLink->mtp3.linkType = LSN_SW_ANS; + SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI88\"\n"); + } else if (!strcasecmp(parm->val, "etsi")) { + mtpLink->mtp2.linkType = LSD_SW_ITU92; + mtpLink->mtp3.linkType = LSN_SW_ITU; + SS7_DEBUG("\tFoundmtpLink->linkType = \"ETSI\"\n"); + } else { + SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val); + return FTDM_FAIL; + } + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "switchType")) { + if (!strcasecmp(parm->val, "itu97")) { + mtpLink->mtp3.switchType = LSI_SW_ITU97; + SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU97\"\n"); + } else if (!strcasecmp(parm->val, "itu88")) { + mtpLink->mtp3.switchType = LSI_SW_ITU; + SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU88\"\n"); + } else if (!strcasecmp(parm->val, "itu92")) { + mtpLink->mtp3.switchType = LSI_SW_ITU; + SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU92\"\n"); + } else if (!strcasecmp(parm->val, "itu00")) { + mtpLink->mtp3.switchType = LSI_SW_ITU2000; + SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU00\"\n"); + } else if (!strcasecmp(parm->val, "ETSIV2")) { + mtpLink->mtp3.switchType = LSI_SW_ETSI; + SS7_DEBUG("\tFoundmtpLink->switchType = \"ETSIV2\"\n"); + } else if (!strcasecmp(parm->val, "ETSIV3")) { + mtpLink->mtp3.switchType = LSI_SW_ETSIV3; + SS7_DEBUG("\tFoundmtpLink->switchType = \"ETSIV3\"\n"); + } else if (!strcasecmp(parm->val, "UK")) { + mtpLink->mtp3.switchType = LSI_SW_UK; + SS7_DEBUG("\tFoundmtpLink->switchType = \"UK\"\n"); + } else if (!strcasecmp(parm->val, "RUSSIA")) { + mtpLink->mtp3.switchType = LSI_SW_RUSSIA; + SS7_DEBUG("\tFoundmtpLink->switchType = \"RUSSIA\"\n"); + } else if (!strcasecmp(parm->val, "INDIA")) { + mtpLink->mtp3.switchType = LSI_SW_INDIA; + SS7_DEBUG("\tFoundmtpLink->switchType = \"INDIA\"\n"); + } else { + SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val); + return FTDM_FAIL; + } + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "ssf")) { + if (!strcasecmp(parm->val, "nat")) { + mtpLink->mtp3.ssf = SSF_NAT; + } else if (!strcasecmp(parm->val, "int")) { + mtpLink->mtp3.ssf = SSF_INTL; + } else { + SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val); + return FTDM_FAIL; + } + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "slc")) { + mtpLink->mtp3.slc = atoi(parm->val); + SS7_DEBUG("\tFoundmtpLink->slc = \"%d\"\n",mtpLink->mtp3.slc); + /**********************************************************************/ + } else { + SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); + return FTDM_FAIL; + } + + /* move to the next parameter */ + parm = parm + 1; + } + + return FTDM_SUCCESS; } /******************************************************************************/ static int ftmod_ss7_parse_mtp_routes(ftdm_conf_node_t *mtp_routes) { - ftdm_conf_node_t *mtp_route = NULL; + ftdm_conf_node_t *mtp_route = NULL; - /* confirm that we are looking at an mtp_routes */ - if (strcasecmp(mtp_routes->name, "mtp_routes")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_routes\"!\n",mtp_routes->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_routes\"...\n"); - } + /* confirm that we are looking at an mtp_routes */ + if (strcasecmp(mtp_routes->name, "mtp_routes")) { + SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_routes\"!\n",mtp_routes->name); + return FTDM_FAIL; + } else { + SS7_DEBUG("Parsing \"mtp_routes\"...\n"); + } - /* extract the mtp_routes */ - mtp_route = mtp_routes->child; + /* extract the mtp_routes */ + mtp_route = mtp_routes->child; - while (mtp_route != NULL) { - /* parse the found mtp_route */ - if (ftmod_ss7_parse_mtp_route(mtp_route)) { - SS7_ERROR("Failed to parse \"mtp_route\"\n"); - return FTDM_FAIL; - } + while (mtp_route != NULL) { + /* parse the found mtp_route */ + if (ftmod_ss7_parse_mtp_route(mtp_route)) { + SS7_ERROR("Failed to parse \"mtp_route\"\n"); + return FTDM_FAIL; + } - /* go to the next mtp_route */ - mtp_route = mtp_route->next; - } + /* go to the next mtp_route */ + mtp_route = mtp_route->next; + } - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route) { - sng_mtp3Route_t mtp3_route; - ftdm_conf_parameter_t *parm = mtp_route->parameters; - int num_parms = mtp_route->n_parameters; - int i; + sng_route_t mtpRoute; + ftdm_conf_parameter_t *parm = mtp_route->parameters; + int num_parms = mtp_route->n_parameters; + int i; - memset(&mtp3_route, 0x0, sizeof(sng_mtp3Route_t)); + memset(&mtpRoute, 0x0, sizeof(mtpRoute)); - /* confirm that we are looking at an mtp_link */ - if (strcasecmp(mtp_route->name, "mtp_route")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_route\"!\n",mtp_route->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"mtp_route\"...\n"); - } + /* confirm that we are looking at an mtp_link */ + if (strcasecmp(mtp_route->name, "mtp_route")) { + SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"mtp_route\"!\n",mtp_route->name); + return FTDM_FAIL; + } else { + SS7_DEBUG("Parsing \"mtp_route\"...\n"); + } - for (i = 0; i < num_parms; i++) { - /* try to match the parameter to what we expect */ - /**********************************************************************/ - if (!strcasecmp(parm->var, "name")) { - strcpy((char *)mtp3_route.name, parm->val); - SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtp3_route.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "dpc")) { - mtp3_route.dpc = atoi(parm->val); - SS7_DEBUG("\tFound mtp3_route->dpc = %d\n", mtp3_route.dpc); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp_linkset")) { - /* find the linkset by it's name */ - int x = 1; - while (g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].id != 0) { - /* check if the name matches */ - if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].name, parm->val)) { - /* grab the mtp3_link id value first*/ - int id = g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].links[0]; - /* now, harvest the required infomormation from the global structure */ - mtp3_route.linkType = g_ftdm_sngss7_data.cfg.mtp3Link[id].linkType; - mtp3_route.switchType = g_ftdm_sngss7_data.cfg.mtp3Link[id].switchType; - mtp3_route.ssf = g_ftdm_sngss7_data.cfg.mtp3Link[id].ssf; - mtp3_route.cmbLinkSetId = g_ftdm_sngss7_data.cfg.mtp3LinkSet[x].id; - break; - } - x++; - } + for (i = 0; i < num_parms; i++) { + /* try to match the parameter to what we expect */ + /**********************************************************************/ + if (!strcasecmp(parm->var, "name")) { + strcpy((char *)mtpRoute.name, parm->val); + SS7_DEBUG("\tFound an \"mtp_route\" named = %s\n", mtpRoute.name); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "dpc")) { + mtpRoute.dpc = atoi(parm->val); + SS7_DEBUG("\tFound mtpRoute->dpc = %d\n", mtpRoute.dpc); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "mtp_linkset")) { - /* check why we exited the wile loop ... and react accordingly */ - if (mtp3_route.cmbLinkSetId == 0) { - SS7_ERROR("\tFailed to find the linkset = \"%s\"!\n", parm->val); - return FTDM_FAIL; - } else { - SS7_DEBUG("\tFound mtp3_route->linkset = %s\n", parm->val); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "isSTP")) { - if (!strcasecmp(parm->val, "no")) { - mtp3_route.isSTP = 0; - SS7_DEBUG("\tFound mtp3_route->isSTP = no\n"); - } else if (!strcasecmp(parm->val, "yes")) { - mtp3_route.isSTP = 1; - SS7_DEBUG("\tFound mtp3_route->isSTP = yes\n"); - } else { - SS7_ERROR("\tFound an invalid parameter for isSTP \"%s\"!\n", parm->val); - return FTDM_FAIL; - } - /**********************************************************************/ - } else { - SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; + /* find the linkset by it's name */ + int x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) { + /* check if the name matches */ + if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, parm->val)) { - } + /* grab the mtpLink id value first*/ + int id = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].links[0]; - /* move to the next parameter */ - parm = parm + 1; - } + /* now, harvest the required infomormation from the global structure */ + mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.linkType; + mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.switchType; + mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.ssf; + mtpRoute.cmbLinkSetId = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id; + break; + } + x++; + } - ftmod_ss7_fill_in_mtp3_route(&mtp3_route); + /* check why we exited the wile loop ... and react accordingly */ + if (mtpRoute.cmbLinkSetId == 0) { + SS7_ERROR("\tFailed to find the linkset = \"%s\"!\n", parm->val); + return FTDM_FAIL; + } else { + SS7_DEBUG("\tFound mtp3_route->linkset = %s\n", parm->val); + } + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "isSTP")) { + if (!strcasecmp(parm->val, "no")) { + mtpRoute.isSTP = 0; + SS7_DEBUG("\tFound mtpRoute->isSTP = no\n"); + } else if (!strcasecmp(parm->val, "yes")) { + mtpRoute.isSTP = 1; + SS7_DEBUG("\tFound mtpRoute->isSTP = yes\n"); + } else { + SS7_ERROR("\tFound an invalid parameter for isSTP \"%s\"!\n", parm->val); + return FTDM_FAIL; + } + /**********************************************************************/ + } else { + SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); + return FTDM_FAIL; - ftmod_ss7_fill_in_mtp3_isup_interface(&mtp3_route); + } - return FTDM_SUCCESS; + /* move to the next parameter */ + parm = parm + 1; + } + + ftmod_ss7_fill_in_mtp3_route(&mtpRoute); + + ftmod_ss7_fill_in_nsap(&mtpRoute); + + return FTDM_SUCCESS; } /******************************************************************************/ static int ftmod_ss7_parse_isup_interfaces(ftdm_conf_node_t *isup_interfaces) { - ftdm_conf_node_t *isup_interface = NULL; + ftdm_conf_node_t *isup_interface = NULL; - /* confirm that we are looking at isup_interfaces */ - if (strcasecmp(isup_interfaces->name, "isup_interfaces")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interfaces\"!\n",isup_interfaces->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"isup_interfaces\"...\n"); - } + /* confirm that we are looking at isup_interfaces */ + if (strcasecmp(isup_interfaces->name, "isup_interfaces")) { + SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interfaces\"!\n",isup_interfaces->name); + return FTDM_FAIL; + } else { + SS7_DEBUG("Parsing \"isup_interfaces\"...\n"); + } - /* extract the isup_interfaces */ - isup_interface = isup_interfaces->child; + /* extract the isup_interfaces */ + isup_interface = isup_interfaces->child; - while (isup_interface != NULL) { - /* parse the found mtp_route */ - if (ftmod_ss7_parse_isup_interface(isup_interface)) { - SS7_ERROR("Failed to parse \"isup_interface\"\n"); - return FTDM_FAIL; - } + while (isup_interface != NULL) { + /* parse the found mtp_route */ + if (ftmod_ss7_parse_isup_interface(isup_interface)) { + SS7_ERROR("Failed to parse \"isup_interface\"\n"); + return FTDM_FAIL; + } - /* go to the next mtp_route */ - isup_interface = isup_interface->next; - } + /* go to the next mtp_route */ + isup_interface = isup_interface->next; + } - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) { - sng_isupInterface_t sng_isup; - sng_isup_cc_t sng_cc; - ftdm_conf_parameter_t *parm = isup_interface->parameters; - int num_parms = isup_interface->n_parameters; - int i; + sng_isup_inf_t sng_isup; + sng_isap_t sng_isap; + ftdm_conf_parameter_t *parm = isup_interface->parameters; + int num_parms = isup_interface->n_parameters; + int i; + int linkSetId; + int linkId; - memset(&sng_isup, 0x0, sizeof(sng_isupInterface_t)); - memset(&sng_cc, 0x0, sizeof(sng_isup_cc_t)); + memset(&sng_isup, 0x0, sizeof(sng_isup)); + memset(&sng_isap, 0x0, sizeof(sng_isap)); - /* confirm that we are looking at an mtp_link */ - if (strcasecmp(isup_interface->name, "isup_interface")) { - SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interface\"!\n",isup_interface->name); - return FTDM_FAIL; - } else { - SS7_DEBUG("Parsing \"isup_interface\"...\n"); - } + /* confirm that we are looking at an mtp_link */ + if (strcasecmp(isup_interface->name, "isup_interface")) { + SS7_ERROR("We're looking at \"%s\"...but we're supposed to be looking at \"isup_interface\"!\n",isup_interface->name); + return FTDM_FAIL; + } else { + SS7_DEBUG("Parsing \"isup_interface\"...\n"); + } - for (i = 0; i < num_parms; i++) { - /* try to match the parameter to what we expect */ - /**********************************************************************/ - if (!strcasecmp(parm->var, "name")) { - strcpy((char *)sng_isup.name, parm->val); - SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "spc")) { - strcpy(g_ftdm_sngss7_data.cfg.spc, parm->val); - SS7_DEBUG("\tFound SPC = %s\n", g_ftdm_sngss7_data.cfg.spc); - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "mtp_route")) { - /* find the route by it's name */ - int x = 1; - while (g_ftdm_sngss7_data.cfg.mtp3Route[x].id != 0) { - /* check if the name matches */ - if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtp3Route[x].name, parm->val)) { - /* now, harvest the required information from the global structure */ - sng_isup.mtp3RouteId = g_ftdm_sngss7_data.cfg.mtp3Route[x].id; - sng_isup.dpc = g_ftdm_sngss7_data.cfg.mtp3Route[x].dpc; - sng_isup.switchType = g_ftdm_sngss7_data.cfg.mtp3Route[x].switchType; - sng_cc.switchType = g_ftdm_sngss7_data.cfg.mtp3Route[x].switchType; + for (i = 0; i < num_parms; i++) { + /* try to match the parameter to what we expect */ + /**********************************************************************/ + if (!strcasecmp(parm->var, "name")) { + strcpy((char *)sng_isup.name, parm->val); + SS7_DEBUG("\tFound an \"isup_interface\" named = %s\n", sng_isup.name); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "spc")) { + sng_isup.spc = atoi(parm->val); + g_ftdm_sngss7_data.cfg.spc = sng_isup.spc; + SS7_DEBUG("\tFound SPC = %d\n", sng_isup.spc); + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "mtp_route")) { + /* find the route by it's name */ + int x = 1; - /* find the nwID from the mtp3_isup_interface */ - int y = 1; - while (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id != 0) { - if (g_ftdm_sngss7_data.cfg.mtp3_isup[y].linkType == g_ftdm_sngss7_data.cfg.mtp3Route[x].linkType && - g_ftdm_sngss7_data.cfg.mtp3_isup[y].switchType == g_ftdm_sngss7_data.cfg.mtp3Route[x].switchType && - g_ftdm_sngss7_data.cfg.mtp3_isup[y].ssf == g_ftdm_sngss7_data.cfg.mtp3Route[x].ssf) { + while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) { - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - y++; - } /* while (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id != 0) */ + /* check if the name matches */ + if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtpRoute[x].name, parm->val)) { - /* check how we exited the last while loop */ - if (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id == 0) { - SS7_ERROR("\tFailed to find the nwID for = \"%s\"!\n", parm->val); - return FTDM_FAIL; - } else { - sng_isup.nwId = g_ftdm_sngss7_data.cfg.mtp3_isup[y].nwId; - } + /* now, harvest the required information from the global structure */ + sng_isup.mtpRouteId = g_ftdm_sngss7_data.cfg.mtpRoute[x].id; + sng_isup.dpc = g_ftdm_sngss7_data.cfg.mtpRoute[x].dpc; + sng_isup.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType; + sng_isap.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType; - break; - } - x++; - } /* while (g_ftdm_sngss7_data.cfg.mtp3Route[x].id != 0) */ + /* find the nwID from the nsap */ + int y = 1; + while (g_ftdm_sngss7_data.cfg.nsap[y].id != 0) { - /* check why we exited the while loop ... and react accordingly */ - if (sng_isup.mtp3RouteId == 0) { - SS7_ERROR("\tFailed to find the MTP3 Route = \"%s\"!\n", parm->val); - return FTDM_FAIL; - } else { - SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val); - } - /**********************************************************************/ - } else if (!strcasecmp(parm->var, "ssf")) { - if (!strcasecmp(parm->val, "nat")) { - sng_isup.ssf = SNG_SSF_NAT; - sng_cc.ssf = SNG_SSF_NAT; - } else if (!strcasecmp(parm->val, "int")) { - sng_isup.ssf = SNG_SSF_INTER; - sng_cc.ssf = SNG_SSF_INTER; - } else { - SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val); - return FTDM_FAIL; - } - /**********************************************************************/ + if ((g_ftdm_sngss7_data.cfg.nsap[y].linkType == g_ftdm_sngss7_data.cfg.mtpRoute[x].linkType) && + (g_ftdm_sngss7_data.cfg.nsap[y].switchType == g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType) && + (g_ftdm_sngss7_data.cfg.nsap[y].ssf == g_ftdm_sngss7_data.cfg.mtpRoute[x].ssf)) { + + /* we have a match so break out of this loop */ + break; + } + /* move on to the next one */ + y++; + } /* while (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id != 0) */ + + /* check how we exited the last while loop */ + if (g_ftdm_sngss7_data.cfg.nsap[y].id == 0) { + SS7_ERROR("\tFailed to find the nwID for = \"%s\"!\n", parm->val); + return FTDM_FAIL; + } else { + sng_isup.nwId = g_ftdm_sngss7_data.cfg.nsap[y].nwId; + } + + break; + } + x++; + } /* while (g_ftdm_sngss7_data.cfg.mtpRoute[x].id != 0) */ + + /* check why we exited the while loop ... and react accordingly */ + if (sng_isup.mtpRouteId == 0) { + SS7_ERROR("\tFailed to find the MTP3 Route = \"%s\"!\n", parm->val); + return FTDM_FAIL; + } else { + SS7_DEBUG("\tFound MTP3 Route = %s\n", parm->val); + } + /**********************************************************************/ + } else if (!strcasecmp(parm->var, "ssf")) { + if (!strcasecmp(parm->val, "nat")) { + sng_isup.ssf = SSF_NAT; + sng_isap.ssf = SSF_NAT; + } else if (!strcasecmp(parm->val, "int")) { + sng_isup.ssf = SSF_INTL; + sng_isap.ssf = SSF_INTL; + } else { + SS7_ERROR("\tFound an invalid ssf of \"%s\"!\n", parm->val); + return FTDM_FAIL; + } + /**********************************************************************/ } else if (!strcasecmp(parm->var, "license")) { /**********************************************************************/ strcpy(g_ftdm_sngss7_data.cfg.license, parm->val); @@ -821,1055 +835,1047 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) SS7_DEBUG("\tFound license file = %s\n", g_ftdm_sngss7_data.cfg.license); SS7_DEBUG("\tFound signature file = %s\n", g_ftdm_sngss7_data.cfg.signature); /**********************************************************************/ - } else { - SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); - return FTDM_FAIL; + } else { + SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); + return FTDM_FAIL; - } + } - /* move to the next parameter */ - parm = parm + 1; - } + /* move to the next parameter */ + parm = parm + 1; + } - ftmod_ss7_fill_in_isup_interface(&sng_isup); + /* trickle down the SPC to all sub entities */ + linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].cmbLinkSetId; + for (i = 0; i < g_ftdm_sngss7_data.cfg.mtpLinkSet[linkSetId].numLinks; i ++) { + linkId = g_ftdm_sngss7_data.cfg.mtpLinkSet[linkSetId].links[i]; + g_ftdm_sngss7_data.cfg.mtpLink[linkId].mtp3.spc = g_ftdm_sngss7_data.cfg.spc; + } - ftmod_ss7_fill_in_isup_cc_interface(&sng_cc); + ftmod_ss7_fill_in_isap(&sng_isap); - return FTDM_SUCCESS; + sng_isup.isap = sng_isap.id; + + ftmod_ss7_fill_in_isup_interface(&sng_isup); + + g_ftdm_sngss7_data.cfg.isap[sng_isap.id].spId = sng_isup.id; + + return FTDM_SUCCESS; } /******************************************************************************/ -static int ftmod_ss7_fill_in_mtp1_link(sng_mtp1Link_t *mtp1_link) +static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink) { - int i; + int i; - /* go through all the existing links and see if we find a match */ - i = 1; - while (g_ftdm_sngss7_data.cfg.mtp1Link[i].id != 0) { - if (g_ftdm_sngss7_data.cfg.mtp1Link[i].span == mtp1_link->span && - g_ftdm_sngss7_data.cfg.mtp1Link[i].chan == mtp1_link->chan) { + /* go through all the existing links and see if we find a match */ + i = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[i].id != 0) { + if ((g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.span == mtpLink->mtp1.span) && + (g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.chan == mtpLink->mtp1.chan)) { - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } + /* we have a match so break out of this loop */ + break; + } + /* move on to the next one */ + i++; + } - /* if the id value is 0 that means we didn't find the link */ - if (g_ftdm_sngss7_data.cfg.mtp1Link[i].id == 0) { - mtp1_link->id = i; - SS7_DEBUG("found new mtp1_link on span=%d, chan=%d, id = %d\n", - mtp1_link->span, - mtp1_link->chan, - mtp1_link->id); - } else { - mtp1_link->id = i; - SS7_DEBUG("found existing mtp1_link on span=%d, chan=%d, id = %d\n", - mtp1_link->span, - mtp1_link->chan, - mtp1_link->id); - } + /* if the id value is 0 that means we didn't find the link */ + if (g_ftdm_sngss7_data.cfg.mtpLink[i].id == 0) { + mtpLink->id = i; + SS7_DEBUG("found new mtpLink on span=%d, chan=%d, id = %d\n", + mtpLink->mtp1.span, + mtpLink->mtp1.chan, + mtpLink->id); + } else { + mtpLink->id = i; + SS7_DEBUG("found existing mtpLink on span=%d, chan=%d, id = %d\n", + mtpLink->mtp1.span, + mtpLink->mtp1.chan, + mtpLink->id); + } - /* fill in the information */ + /* fill in the information */ + strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLink[i].name, (char *)mtpLink->name); - strcpy((char *)g_ftdm_sngss7_data.cfg.mtp1Link[i].name, (char *)mtp1_link->name); + g_ftdm_sngss7_data.cfg.mtpLink[i].id = mtpLink->id; - g_ftdm_sngss7_data.cfg.mtp1Link[i].id = mtp1_link->id; - g_ftdm_sngss7_data.cfg.mtp1Link[i].span = mtp1_link->span; - g_ftdm_sngss7_data.cfg.mtp1Link[i].chan = mtp1_link->chan; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.span = mtpLink->mtp1.span; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp1.chan = mtpLink->mtp1.chan; - return (mtp1_link->id); + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.linkType = mtpLink->mtp2.linkType; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.errorType = mtpLink->mtp2.errorType; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.lssuLength = mtpLink->mtp2.lssuLength; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.mtp1Id = mtpLink->id; + + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.priority = mtpLink->mtp3.priority; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.linkType = mtpLink->mtp3.linkType; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.switchType = mtpLink->mtp3.switchType; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.apc = mtpLink->mtp3.apc; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.spc = g_ftdm_sngss7_data.cfg.spc; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.ssf = mtpLink->mtp3.ssf; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.slc = mtpLink->mtp3.slc; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.linkSetId = mtpLink->mtp3.linkSetId; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.mtp2Id = mtpLink->id; + + if ( mtpLink->mtp2.t1 != 0 ) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t1 = mtpLink->mtp2.t1; + }else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t1 = 500; + } + if ( mtpLink->mtp2.t2 != 0 ) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t2 = mtpLink->mtp2.t2; + }else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t2 = 250; + } + if ( mtpLink->mtp2.t3 != 0 ) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t3 = mtpLink->mtp2.t3; + }else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t3 = 20; + } + if ( mtpLink->mtp2.t4n != 0 ) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4n = mtpLink->mtp2.t4n; + }else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4n = 80; + } + if ( mtpLink->mtp2.t4e != 0 ) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4e = mtpLink->mtp2.t4e; + }else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t4e = 5; + } + if ( mtpLink->mtp2.t5 != 0 ) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t5 = mtpLink->mtp2.t5; + }else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t5 = 1; + } + if ( mtpLink->mtp2.t6 != 0 ) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t6 = mtpLink->mtp2.t6; + }else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t6 = 60; + } + if ( mtpLink->mtp2.t7 != 0 ) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7 = mtpLink->mtp2.t7; + }else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7 = 20; + } + + if (mtpLink->mtp3.t1 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t1 = mtpLink->mtp3.t1; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t1 = 8; + } + if (mtpLink->mtp3.t2 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t2 = mtpLink->mtp3.t2; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t2 = 14; + } + if (mtpLink->mtp3.t3 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t3 = mtpLink->mtp3.t3; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t3 = 8; + } + if (mtpLink->mtp3.t4 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t4 = mtpLink->mtp3.t4; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t4 = 8; + } + if (mtpLink->mtp3.t5 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t5 = mtpLink->mtp3.t5; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t5 = 8; + } + if (mtpLink->mtp3.t7 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t7 = mtpLink->mtp3.t7; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t7 = 15; + } + if (mtpLink->mtp3.t12 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t12 = mtpLink->mtp3.t12; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t12 = 15; + } + if (mtpLink->mtp3.t13 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t13 = mtpLink->mtp3.t13; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t13 = 15; + } + if (mtpLink->mtp3.t14 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t14 = mtpLink->mtp3.t14; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t14 = 30; + } + if (mtpLink->mtp3.t17 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t17 = mtpLink->mtp3.t17; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t17 = 15; + } + if (mtpLink->mtp3.t22 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t22 = mtpLink->mtp3.t22; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t22 = 1800; + } + if (mtpLink->mtp3.t23 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t23 = mtpLink->mtp3.t23; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t23 = 1800; + } + if (mtpLink->mtp3.t24 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t24 = mtpLink->mtp3.t24; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t24 = 5; + } + if (mtpLink->mtp3.t31 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t31 = mtpLink->mtp3.t31; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t31 = 50; + } + if (mtpLink->mtp3.t32 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t32 = mtpLink->mtp3.t32; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t32 = 120; + } + if (mtpLink->mtp3.t33 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t33 = mtpLink->mtp3.t33; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t33 = 3000; + } + if (mtpLink->mtp3.t34 != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t34 = mtpLink->mtp3.t34; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.t34 = 600; + } + if (mtpLink->mtp3.tflc != 0) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.tflc = mtpLink->mtp3.tflc; + } else { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.tflc = 300; + } + return (mtpLink->id); +} + + +/******************************************************************************/ +static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet) +{ + int count; + int i = mtpLinkSet->id; + + strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name); + + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id = mtpLinkSet->id; + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc = mtpLinkSet->apc; + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].linkType = g_ftdm_sngss7_data.cfg.mtpLink[1].mtp3.linkType; /* KONRAD FIX ME */ + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].minActive = mtpLinkSet->minActive; + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].numLinks = mtpLinkSet->numLinks; + + for (count = 0; count < mtpLinkSet->numLinks; count++) { + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].links[count] = mtpLinkSet->links[count]; + } + + return 0; } /******************************************************************************/ -static int ftmod_ss7_fill_in_mtp2_link(sng_mtp2Link_t *mtp2_link) +static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route) { - /* the mtp2link->spId is also the index value */ + int i; - int i = mtp2_link->spId; + /* go through all the existing routes and see if we find a match */ + i = 1; + while (g_ftdm_sngss7_data.cfg.mtpRoute[i].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc == mtp3_route->dpc) { - mtp2_link->id = i; + /* we have a match so break out of this loop */ + break; + } + /* move on to the next one */ + i++; + } - if (g_ftdm_sngss7_data.cfg.mtp2Link[i].id == 0) { - SS7_DEBUG("found new mtp2_link, id is = %d\n", mtp2_link->id); - } else { - SS7_DEBUG("found existing mtp2_link, id is = %d\n", mtp2_link->id); - } + if (g_ftdm_sngss7_data.cfg.mtpRoute[i].id == 0) { + mtp3_route->id = i; + SS7_DEBUG("found new mtp3_route, id is = %d\n", mtp3_route->id); + } else { + mtp3_route->id = i; + SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id); + } - strcpy((char *)g_ftdm_sngss7_data.cfg.mtp2Link[i].name, (char *)mtp2_link->name); + strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[i].name, (char *)mtp3_route->name); - g_ftdm_sngss7_data.cfg.mtp2Link[i].id = mtp2_link->id; - g_ftdm_sngss7_data.cfg.mtp2Link[i].spId = mtp2_link->spId; - g_ftdm_sngss7_data.cfg.mtp2Link[i].linkType = mtp2_link->linkType; - g_ftdm_sngss7_data.cfg.mtp2Link[i].errorType = mtp2_link->errorType; - g_ftdm_sngss7_data.cfg.mtp2Link[i].lssuLength = mtp2_link->lssuLength; + g_ftdm_sngss7_data.cfg.mtpRoute[i].id = mtp3_route->id; + g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = mtp3_route->dpc; + g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType = mtp3_route->linkType; + g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType = mtp3_route->switchType; + g_ftdm_sngss7_data.cfg.mtpRoute[i].cmbLinkSetId = 1; /* mtp3_route->cmbLinkSetId;*/ + g_ftdm_sngss7_data.cfg.mtpRoute[i].isSTP = mtp3_route->isSTP; + g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf = mtp3_route->ssf; + if (mtp3_route->t6 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t6 = mtp3_route->t6; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t6 = 8; + } + if (mtp3_route->t8 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t8 = mtp3_route->t8; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t8 = 12; + } + if (mtp3_route->t10 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t10 = mtp3_route->t10; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t10 = 300; + } + if (mtp3_route->t11 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t11 = mtp3_route->t11; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t11 = 300; + } + if (mtp3_route->t15 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t15 = mtp3_route->t15; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t15 = 30; + } + if (mtp3_route->t16 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t16 = mtp3_route->t16; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t16 = 20; + } + if (mtp3_route->t18 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t18 = mtp3_route->t18; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t18 = 200; + } + if (mtp3_route->t19 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t19 = mtp3_route->t19; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t19 = 690; + } + if (mtp3_route->t21 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t21 = mtp3_route->t21; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t21 = 650; + } + if (mtp3_route->t25 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t25 = mtp3_route->t25; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t25 = 100; + } - if ( mtp2_link->t1 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t1 = mtp2_link->t1; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t1 = 500; - } - if ( mtp2_link->t2 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t2 = mtp2_link->t2; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t2 = 250; - } - if ( mtp2_link->t3 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t3 = mtp2_link->t3; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t3 = 20; - } - if ( mtp2_link->t4n != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t4n = mtp2_link->t4n; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t4n = 80; - } - if ( mtp2_link->t4e != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t4e = mtp2_link->t4e; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t4e = 5; - } - if ( mtp2_link->t5 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t5 = mtp2_link->t5; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t5 = 1; - } - if ( mtp2_link->t6 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t6 = mtp2_link->t6; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t6 = 60; - } - if ( mtp2_link->t7 != 0 ) { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t7 = mtp2_link->t7; - }else { - g_ftdm_sngss7_data.cfg.mtp2Link[i].t7 = 20; - } - - return(mtp2_link->id); + return 0; } /******************************************************************************/ -static int ftmod_ss7_fill_in_mtp3_link(sng_mtp3Link_t *mtp3_link) +static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route) { - int i = mtp3_link->mtp2LinkId; + int i; - mtp3_link->id = i; + /* go through all the existing interfaces and see if we find a match */ + i = 1; + while (g_ftdm_sngss7_data.cfg.nsap[i].id != 0) { + if ((g_ftdm_sngss7_data.cfg.nsap[i].linkType == mtp3_route->linkType) && + (g_ftdm_sngss7_data.cfg.nsap[i].switchType == mtp3_route->switchType) && + (g_ftdm_sngss7_data.cfg.nsap[i].ssf == mtp3_route->ssf)) { - if (g_ftdm_sngss7_data.cfg.mtp3Link[i].id == 0) { - SS7_DEBUG("found new mtp3_link, id is = %d\n", mtp3_link->id); - } else { - SS7_DEBUG("found existing mtp3_link, id is = %d\n", mtp3_link->id); - } + /* we have a match so break out of this loop */ + break; + } + /* move on to the next one */ + i++; + } - strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3Link[i].name, (char *)mtp3_link->name); + if (g_ftdm_sngss7_data.cfg.nsap[i].id == 0) { + g_ftdm_sngss7_data.cfg.nsap[i].id = i; + SS7_DEBUG("found new mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id); + } else { + g_ftdm_sngss7_data.cfg.nsap[i].id = i; + SS7_DEBUG("found existing mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id); + } + + g_ftdm_sngss7_data.cfg.nsap[i].spId = g_ftdm_sngss7_data.cfg.nsap[i].id; + g_ftdm_sngss7_data.cfg.nsap[i].suId = g_ftdm_sngss7_data.cfg.nsap[i].id; + g_ftdm_sngss7_data.cfg.nsap[i].nwId = g_ftdm_sngss7_data.cfg.nsap[i].id; + g_ftdm_sngss7_data.cfg.nsap[i].linkType = mtp3_route->linkType; + g_ftdm_sngss7_data.cfg.nsap[i].switchType = mtp3_route->switchType; + g_ftdm_sngss7_data.cfg.nsap[i].ssf = mtp3_route->ssf; - g_ftdm_sngss7_data.cfg.mtp3Link[i].id = mtp3_link->id; - g_ftdm_sngss7_data.cfg.mtp3Link[i].mtp2LinkId = mtp3_link->mtp2LinkId; - g_ftdm_sngss7_data.cfg.mtp3Link[i].linkSetId = mtp3_link->linkSetId; - g_ftdm_sngss7_data.cfg.mtp3Link[i].priority = mtp3_link->priority; - g_ftdm_sngss7_data.cfg.mtp3Link[i].linkType = mtp3_link->linkType; - g_ftdm_sngss7_data.cfg.mtp3Link[i].switchType = mtp3_link->switchType; - g_ftdm_sngss7_data.cfg.mtp3Link[i].apc = mtp3_link->apc; - g_ftdm_sngss7_data.cfg.mtp3Link[i].ssf = mtp3_link->ssf; - g_ftdm_sngss7_data.cfg.mtp3Link[i].lnkTstSLC = mtp3_link->lnkTstSLC; - if (mtp3_link->t1 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t1 = mtp3_link->t1; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t1 = 8; - } - if (mtp3_link->t2 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t2 = mtp3_link->t2; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t2 = 14; - } - if (mtp3_link->t3 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t3 = mtp3_link->t3; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t3 = 8; - } - if (mtp3_link->t4 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t4 = mtp3_link->t4; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t4 = 8; - } - if (mtp3_link->t5 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t5 = mtp3_link->t5; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t5 = 8; - } - if (mtp3_link->t7 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t7 = mtp3_link->t7; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t7 = 15; - } - if (mtp3_link->t12 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t12 = mtp3_link->t12; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t12 = 15; - } - if (mtp3_link->t13 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t13 = mtp3_link->t13; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t13 = 15; - } - if (mtp3_link->t14 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t14 = mtp3_link->t14; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t14 = 30; - } - if (mtp3_link->t17 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t17 = mtp3_link->t17; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t17 = 15; - } - if (mtp3_link->t22 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t22 = mtp3_link->t22; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t22 = 1800; - } - if (mtp3_link->t23 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t23 = mtp3_link->t23; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t23 = 1800; - } - if (mtp3_link->t24 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t24 = mtp3_link->t24; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t24 = 5; - } - if (mtp3_link->t31 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t31 = mtp3_link->t31; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t31 = 50; - } - if (mtp3_link->t32 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t32 = mtp3_link->t32; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t32 = 120; - } - if (mtp3_link->t33 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t33 = mtp3_link->t33; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t33 = 3000; - } - if (mtp3_link->t34 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t34 = mtp3_link->t34; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].t34 = 600; - } - if (mtp3_link->tflc != 0) { - g_ftdm_sngss7_data.cfg.mtp3Link[i].tflc = mtp3_link->tflc; - } else { - g_ftdm_sngss7_data.cfg.mtp3Link[i].tflc = 300; - } - - return(mtp3_link->id); + return 0; } /******************************************************************************/ -static int ftmod_ss7_fill_in_mtp3_linkset(sng_mtp3LinkSet_t *mtp3_linkset) +static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup) { - int count; - int i = mtp3_linkset->id; + int i; - strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].name, (char *)mtp3_linkset->name); + /* go through all the existing interfaces and see if we find a match */ + i = 1; + while (g_ftdm_sngss7_data.cfg.isupIntf[i].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupIntf[i].nwId == sng_isup->nwId) { - g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].id = mtp3_linkset->id; - g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].apc = mtp3_linkset->apc; - g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].minActive = mtp3_linkset->minActive; - g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].numLinks = mtp3_linkset->numLinks; + /* we have a match so break out of this loop */ + break; + } + /* move on to the next one */ + i++; + } - for (count = 0; count < mtp3_linkset->numLinks; count++) { - g_ftdm_sngss7_data.cfg.mtp3LinkSet[i].links[count] = mtp3_linkset->links[count]; - } + if (g_ftdm_sngss7_data.cfg.isupIntf[i].id == 0) { + sng_isup->id = i; + SS7_DEBUG("found new isup interface, id is = %d\n", sng_isup->id); + } else { + sng_isup->id = i; + SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id); + } - return 0; + strcpy((char *)g_ftdm_sngss7_data.cfg.isupIntf[i].name, (char *)sng_isup->name); + + g_ftdm_sngss7_data.cfg.isupIntf[i].id = sng_isup->id; + g_ftdm_sngss7_data.cfg.isupIntf[i].mtpRouteId = sng_isup->mtpRouteId; + g_ftdm_sngss7_data.cfg.isupIntf[i].nwId = sng_isup->nwId; + g_ftdm_sngss7_data.cfg.isupIntf[i].dpc = sng_isup->dpc; + g_ftdm_sngss7_data.cfg.isupIntf[i].spc = sng_isup->spc; + g_ftdm_sngss7_data.cfg.isupIntf[i].switchType = sng_isup->switchType; + g_ftdm_sngss7_data.cfg.isupIntf[i].ssf = sng_isup->ssf; + g_ftdm_sngss7_data.cfg.isupIntf[i].isap = sng_isup->isap; + + if (sng_isup->t4 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = sng_isup->t4; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t4 = 3000; + } + if (sng_isup->t10 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t10 = sng_isup->t10; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t10 = 50; + } + if (sng_isup->t11 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t11 = sng_isup->t11; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t11 = 170; + } + if (sng_isup->t18 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t18 = sng_isup->t18; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t18 = 300; + } + if (sng_isup->t19 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t19 = sng_isup->t19; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t19 = 3000; + } + if (sng_isup->t20 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t20 = sng_isup->t20; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t20 = 300; + } + if (sng_isup->t21 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t21 = sng_isup->t21; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t21 = 3000; + } + if (sng_isup->t22 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t22 = sng_isup->t22; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t22 = 300; + } + if (sng_isup->t23 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t23 = sng_isup->t23; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t23 = 3000; + } + if (sng_isup->t24 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t24 = sng_isup->t24; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t24 = 10; + } + if (sng_isup->t25 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t25 = sng_isup->t25; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t25 = 20; + } + if (sng_isup->t26 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t26 = sng_isup->t26; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t26 = 600; + } + if (sng_isup->t28 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t28 = sng_isup->t28; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t28 = 100; + } + if (sng_isup->t29 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t29 = sng_isup->t29; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t29 = 6; + } + if (sng_isup->t30 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t30 = sng_isup->t30; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t30 = 50; + } + if (sng_isup->t32 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t32 = sng_isup->t32; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t32 = 30; + } + if (sng_isup->t35 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t35 = sng_isup->t35; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t35 = 170; + } + if (sng_isup->t37 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t37 = sng_isup->t37; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t37 = 20; + } + if (sng_isup->t38 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t38 = sng_isup->t38; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t38 = 1200; + } + if (sng_isup->t39 != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].t39 = sng_isup->t39; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].t39 = 300; + } + if (sng_isup->tfgr != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].tfgr = sng_isup->tfgr; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].tfgr = 50; + } + if (sng_isup->tpause != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].tpause = sng_isup->tpause; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].tpause = 150; + } + if (sng_isup->tstaenq != 0) { + g_ftdm_sngss7_data.cfg.isupIntf[i].tstaenq = sng_isup->tstaenq; + } else { + g_ftdm_sngss7_data.cfg.isupIntf[i].tstaenq = 5000; + } + + return 0; } /******************************************************************************/ -static int ftmod_ss7_fill_in_mtp3_route(sng_mtp3Route_t *mtp3_route) +static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap) { - int i; + int i; - /* go through all the existing routes and see if we find a match */ - i = 1; - while (g_ftdm_sngss7_data.cfg.mtp3Route[i].id != 0) { - if (g_ftdm_sngss7_data.cfg.mtp3Route[i].dpc == mtp3_route->dpc) { + /* go through all the existing interfaces and see if we find a match */ + i = 1; + while (g_ftdm_sngss7_data.cfg.isap[i].id != 0) { + if (g_ftdm_sngss7_data.cfg.isap[i].switchType == sng_isap->switchType) { - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } + /* we have a match so break out of this loop */ + break; + } + /* move on to the next one */ + i++; + } - if (g_ftdm_sngss7_data.cfg.mtp3Route[i].id == 0) { - mtp3_route->id = i; - SS7_DEBUG("found new mtp3_route, id is = %d\n", mtp3_route->id); - } else { - mtp3_route->id = i; - SS7_DEBUG("found existing mtp3_route, id is = %d\n", mtp3_route->id); - } + if (g_ftdm_sngss7_data.cfg.isap[i].id == 0) { + sng_isap->id = i; + SS7_DEBUG("found new isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isap[i].id); + } else { + sng_isap->id = i; + SS7_DEBUG("found existing isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isap[i].id); + } - strcpy((char *)g_ftdm_sngss7_data.cfg.mtp3Route[i].name, (char *)mtp3_route->name); + g_ftdm_sngss7_data.cfg.isap[i].id = sng_isap->id; + g_ftdm_sngss7_data.cfg.isap[i].suId = 1; /*KONRAD FIX ME */ + g_ftdm_sngss7_data.cfg.isap[i].switchType = sng_isap->switchType; + g_ftdm_sngss7_data.cfg.isap[i].ssf = sng_isap->ssf; - g_ftdm_sngss7_data.cfg.mtp3Route[i].id = mtp3_route->id; - g_ftdm_sngss7_data.cfg.mtp3Route[i].dpc = mtp3_route->dpc; - g_ftdm_sngss7_data.cfg.mtp3Route[i].linkType = mtp3_route->linkType; - g_ftdm_sngss7_data.cfg.mtp3Route[i].switchType = mtp3_route->switchType; - g_ftdm_sngss7_data.cfg.mtp3Route[i].cmbLinkSetId = 1; /* mtp3_route->cmbLinkSetId;*/ - g_ftdm_sngss7_data.cfg.mtp3Route[i].isSTP = mtp3_route->isSTP; - g_ftdm_sngss7_data.cfg.mtp3Route[i].ssf = mtp3_route->ssf; - if (mtp3_route->t6 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t6 = mtp3_route->t6; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t6 = 8; - } - if (mtp3_route->t8 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t8 = mtp3_route->t8; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t8 = 12; - } - if (mtp3_route->t10 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t10 = mtp3_route->t10; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t10 = 300; - } - if (mtp3_route->t11 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t11 = mtp3_route->t11; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t11 = 300; - } - if (mtp3_route->t15 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t15 = mtp3_route->t15; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t15 = 30; - } - if (mtp3_route->t16 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t16 = mtp3_route->t16; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t16 = 20; - } - if (mtp3_route->t18 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t18 = mtp3_route->t18; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t18 = 200; - } - if (mtp3_route->t19 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t19 = mtp3_route->t19; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t19 = 690; - } - if (mtp3_route->t21 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t21 = mtp3_route->t21; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t21 = 650; - } - if (mtp3_route->t25 != 0) { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t25 = mtp3_route->t25; - } else { - g_ftdm_sngss7_data.cfg.mtp3Route[i].t25 = 100; - } + if (sng_isap->t1 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t1 = sng_isap->t1; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t1 = 200; + } + if (sng_isap->t2 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t2 = sng_isap->t2; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t2 = 1800; + } + if (sng_isap->t5 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t5 = sng_isap->t5; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t5 = 3000; + } + if (sng_isap->t6 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t6 = sng_isap->t6; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t6 = 200; + } + if (sng_isap->t7 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t7 = sng_isap->t7; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t7 = 250; + } + if (sng_isap->t8 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t8 = sng_isap->t8; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t8 = 120; + } + if (sng_isap->t9 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t9 = sng_isap->t9; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t9 = 1800; + } + if (sng_isap->t27 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t27 = sng_isap->t27; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t27 = 2400; + } + if (sng_isap->t31 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t31 = sng_isap->t31; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t31 = 3650; + } + if (sng_isap->t33 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t33 = sng_isap->t33; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t33 = 120; + } + if (sng_isap->t34 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t34 = sng_isap->t34; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t34 = 40; + } + if (sng_isap->t36 != 0) { + g_ftdm_sngss7_data.cfg.isap[i].t36 = sng_isap->t36; + } else { + g_ftdm_sngss7_data.cfg.isap[i].t36 = 120; + } + if (sng_isap->tccr != 0) { + g_ftdm_sngss7_data.cfg.isap[i].tccr = sng_isap->tccr; + } else { + g_ftdm_sngss7_data.cfg.isap[i].tccr = 200; + } + if (sng_isap->tccrt != 0) { + g_ftdm_sngss7_data.cfg.isap[i].tccrt = sng_isap->tccrt; + } else { + g_ftdm_sngss7_data.cfg.isap[i].tccrt = 20; + } + if (sng_isap->tex != 0) { + g_ftdm_sngss7_data.cfg.isap[i].tex = sng_isap->tex; + } else { + g_ftdm_sngss7_data.cfg.isap[i].tex = 10; + } + if (sng_isap->tcrm != 0) { + g_ftdm_sngss7_data.cfg.isap[i].tcrm = sng_isap->tcrm; + } else { + g_ftdm_sngss7_data.cfg.isap[i].tcrm = 30; + } + if (sng_isap->tcra != 0) { + g_ftdm_sngss7_data.cfg.isap[i].tcra = sng_isap->tcra; + } else { + g_ftdm_sngss7_data.cfg.isap[i].tcra = 100; + } + if (sng_isap->tect != 0) { + g_ftdm_sngss7_data.cfg.isap[i].tect = sng_isap->tect; + } else { + g_ftdm_sngss7_data.cfg.isap[i].tect = 10; + } + if (sng_isap->trelrsp != 0) { + g_ftdm_sngss7_data.cfg.isap[i].trelrsp = sng_isap->trelrsp; + } else { + g_ftdm_sngss7_data.cfg.isap[i].trelrsp = 10; + } + if (sng_isap->tfnlrelrsp != 0) { + g_ftdm_sngss7_data.cfg.isap[i].tfnlrelrsp = sng_isap->tfnlrelrsp; + } else { + g_ftdm_sngss7_data.cfg.isap[i].tfnlrelrsp = 10; + } - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_mtp3_isup_interface(sng_mtp3Route_t *mtp3_route) -{ - - int i; - - /* go through all the existing interfaces and see if we find a match */ - i = 1; - while (g_ftdm_sngss7_data.cfg.mtp3_isup[i].id != 0) { - if (g_ftdm_sngss7_data.cfg.mtp3_isup[i].linkType == mtp3_route->linkType && - g_ftdm_sngss7_data.cfg.mtp3_isup[i].switchType == mtp3_route->switchType && - g_ftdm_sngss7_data.cfg.mtp3_isup[i].ssf == mtp3_route->ssf) { - - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } - - if (g_ftdm_sngss7_data.cfg.mtp3_isup[i].id == 0) { - g_ftdm_sngss7_data.cfg.mtp3_isup[i].id = i; - SS7_DEBUG("found new mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.mtp3_isup[i].id); - } else { - g_ftdm_sngss7_data.cfg.mtp3_isup[i].id = i; - SS7_DEBUG("found existing mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.mtp3_isup[i].id); - } - - g_ftdm_sngss7_data.cfg.mtp3_isup[i].nwId = g_ftdm_sngss7_data.cfg.mtp3_isup[i].id; - g_ftdm_sngss7_data.cfg.mtp3_isup[i].linkType = mtp3_route->linkType; - g_ftdm_sngss7_data.cfg.mtp3_isup[i].switchType = mtp3_route->switchType; - g_ftdm_sngss7_data.cfg.mtp3_isup[i].ssf = mtp3_route->ssf; - - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_isup_interface(sng_isupInterface_t *sng_isup) -{ - - int i; - - /* go through all the existing interfaces and see if we find a match */ - i = 1; - while (g_ftdm_sngss7_data.cfg.isupInterface[i].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupInterface[i].nwId == sng_isup->nwId) { - - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } - - if (g_ftdm_sngss7_data.cfg.isupInterface[i].id == 0) { - sng_isup->id = i; - SS7_DEBUG("found new isup interface, id is = %d\n", sng_isup->id); - } else { - sng_isup->id = i; - SS7_DEBUG("found existing isup interface, id is = %d\n", sng_isup->id); - } - - strcpy((char *)g_ftdm_sngss7_data.cfg.isupInterface[i].name, (char *)sng_isup->name); - - g_ftdm_sngss7_data.cfg.isupInterface[i].id = sng_isup->id; - g_ftdm_sngss7_data.cfg.isupInterface[i].mtp3RouteId = sng_isup->mtp3RouteId; - g_ftdm_sngss7_data.cfg.isupInterface[i].nwId = sng_isup->nwId; - g_ftdm_sngss7_data.cfg.isupInterface[i].dpc = sng_isup->dpc; - g_ftdm_sngss7_data.cfg.isupInterface[i].switchType = sng_isup->switchType; - g_ftdm_sngss7_data.cfg.isupInterface[i].ssf = sng_isup->ssf; - if (sng_isup->t4 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t4 = sng_isup->t4; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t4 = 3000; - } - if (sng_isup->t10 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t10 = sng_isup->t10; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t10 = 50; - } - if (sng_isup->t11 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t11 = sng_isup->t11; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t11 = 170; - } - if (sng_isup->t18 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t18 = sng_isup->t18; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t18 = 300; - } - if (sng_isup->t19 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t19 = sng_isup->t19; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t19 = 3000; - } - if (sng_isup->t20 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t20 = sng_isup->t20; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t20 = 300; - } - if (sng_isup->t21 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t21 = sng_isup->t21; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t21 = 3000; - } - if (sng_isup->t22 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t22 = sng_isup->t22; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t22 = 300; - } - if (sng_isup->t23 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t23 = sng_isup->t23; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t23 = 3000; - } - if (sng_isup->t24 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t24 = sng_isup->t24; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t24 = 10; - } - if (sng_isup->t25 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t25 = sng_isup->t25; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t25 = 20; - } - if (sng_isup->t26 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t26 = sng_isup->t26; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t26 = 600; - } - if (sng_isup->t28 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t28 = sng_isup->t28; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t28 = 100; - } - if (sng_isup->t29 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t29 = sng_isup->t29; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t29 = 6; - } - if (sng_isup->t30 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t30 = sng_isup->t30; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t30 = 50; - } - if (sng_isup->t32 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t32 = sng_isup->t32; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t32 = 30; - } - if (sng_isup->t35 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t35 = sng_isup->t35; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t35 = 170; - } - if (sng_isup->t37 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t37 = sng_isup->t37; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t37 = 20; - } - if (sng_isup->t38 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t38 = sng_isup->t38; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t38 = 1200; - } - if (sng_isup->t39 != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].t39 = sng_isup->t39; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].t39 = 300; - } - if (sng_isup->tfgr != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].tfgr = sng_isup->tfgr; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].tfgr = 50; - } - if (sng_isup->tpause != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].tpause = sng_isup->tpause; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].tpause = 150; - } - if (sng_isup->tstaenq != 0) { - g_ftdm_sngss7_data.cfg.isupInterface[i].tstaenq = sng_isup->tstaenq; - } else { - g_ftdm_sngss7_data.cfg.isupInterface[i].tstaenq = 5000; - } - - return 0; -} - -/******************************************************************************/ -static int ftmod_ss7_fill_in_isup_cc_interface(sng_isup_cc_t *sng_cc) -{ - - int i; - - /* go through all the existing interfaces and see if we find a match */ - i = 1; - while (g_ftdm_sngss7_data.cfg.isup_cc[i].id != 0) { - if (g_ftdm_sngss7_data.cfg.isup_cc[i].switchType == sng_cc->switchType) { - - /* we have a match so break out of this loop */ - break; - } - /* move on to the next one */ - i++; - } - - if (g_ftdm_sngss7_data.cfg.isup_cc[i].id == 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].id = i; - SS7_DEBUG("found new isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isup_cc[i].id); - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].id = i; - SS7_DEBUG("found existing isup to cc interface, id is = %d\n", g_ftdm_sngss7_data.cfg.isup_cc[i].id); - } - - SS7_ERROR("KONRAD -> you're hard coding the CC id....fix me!!!!\n"); - g_ftdm_sngss7_data.cfg.isup_cc[i].ccId = 1; /*KONRAD FIX ME */ - g_ftdm_sngss7_data.cfg.isup_cc[i].switchType = sng_cc->switchType; - g_ftdm_sngss7_data.cfg.isup_cc[i].ssf = sng_cc->ssf; - if (sng_cc->t1 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t1 = sng_cc->t1; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t1 = 200; - } - if (sng_cc->t2 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t2 = sng_cc->t2; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t2 = 1800; - } - if (sng_cc->t5 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t5 = sng_cc->t5; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t5 = 3000; - } - if (sng_cc->t6 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t6 = sng_cc->t6; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t6 = 200; - } - if (sng_cc->t7 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t7 = sng_cc->t7; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t7 = 250; - } - if (sng_cc->t8 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t8 = sng_cc->t8; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t8 = 120; - } - if (sng_cc->t9 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t9 = sng_cc->t9; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t9 = 1800; - } - if (sng_cc->t27 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t27 = sng_cc->t27; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t27 = 2400; - } - if (sng_cc->t31 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t31 = sng_cc->t31; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t31 = 3650; - } - if (sng_cc->t33 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t33 = sng_cc->t33; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t33 = 120; - } - if (sng_cc->t34 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t34 = sng_cc->t34; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t34 = 40; - } - if (sng_cc->t36 != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].t36 = sng_cc->t36; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].t36 = 120; - } - if (sng_cc->tccr != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].tccr = sng_cc->tccr; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].tccr = 200; - } - if (sng_cc->tccrt != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].tccrt = sng_cc->tccrt; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].tccrt = 20; - } - if (sng_cc->tex != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].tex = sng_cc->tex; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].tex = 10; - } - if (sng_cc->tcrm != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].tcrm = sng_cc->tcrm; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].tcrm = 30; - } - if (sng_cc->tcra != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].tcra = sng_cc->tcra; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].tcra = 100; - } - if (sng_cc->tect != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].tect = sng_cc->tect; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].tect = 10; - } - if (sng_cc->trelrsp != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].trelrsp = sng_cc->trelrsp; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].trelrsp = 10; - } - if (sng_cc->tfnlrelrsp != 0) { - g_ftdm_sngss7_data.cfg.isup_cc[i].tfnlrelrsp= sng_cc->tfnlrelrsp; - } else { - g_ftdm_sngss7_data.cfg.isup_cc[i].tfnlrelrsp= 10; - } - - return 0; + return 0; } /******************************************************************************/ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, int ssf) { - if (g_ftdm_sngss7_data.cfg.mtp3Route[0].dpc == 0){ - SS7_DEBUG("found new mtp3 self route\n"); - } else if (g_ftdm_sngss7_data.cfg.mtp3Route[0].dpc == spc) { - SS7_DEBUG("found existing mtp3 self route\n"); - return FTDM_SUCCESS; - } else { - SS7_ERROR("found new mtp3 self route but it does not much the route already configured\n"); - return FTDM_FAIL; - } + if (g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc == 0){ + SS7_DEBUG("found new mtp3 self route\n"); + } else if (g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc == spc) { + SS7_DEBUG("found existing mtp3 self route\n"); + return FTDM_SUCCESS; + } else { + SS7_ERROR("found new mtp3 self route but it does not much the route already configured\n"); + return FTDM_FAIL; + } - g_ftdm_sngss7_data.cfg.mtp3Route[0].id = 0; - g_ftdm_sngss7_data.cfg.mtp3Route[0].dpc = spc; - g_ftdm_sngss7_data.cfg.mtp3Route[0].linkType = linkType; - g_ftdm_sngss7_data.cfg.mtp3Route[0].switchType = switchType; - g_ftdm_sngss7_data.cfg.mtp3Route[0].cmbLinkSetId = 0; - g_ftdm_sngss7_data.cfg.mtp3Route[0].isSTP = 0; - g_ftdm_sngss7_data.cfg.mtp3Route[0].ssf = 0; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t6 = 8; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t8 = 12; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t10 = 300; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t11 = 300; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t15 = 30; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t16 = 20; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t18 = 200; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t19 = 690; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t21 = 650; - g_ftdm_sngss7_data.cfg.mtp3Route[0].t25 = 100; + strcpy((char *)g_ftdm_sngss7_data.cfg.mtpRoute[0].name, "self-route"); + g_ftdm_sngss7_data.cfg.mtpRoute[0].id = 0; + g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc = spc; + g_ftdm_sngss7_data.cfg.mtpRoute[0].linkType = linkType; + g_ftdm_sngss7_data.cfg.mtpRoute[0].switchType = switchType; + g_ftdm_sngss7_data.cfg.mtpRoute[0].cmbLinkSetId = 0; + g_ftdm_sngss7_data.cfg.mtpRoute[0].isSTP = 0; + g_ftdm_sngss7_data.cfg.mtpRoute[0].ssf = ssf; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t6 = 8; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t8 = 12; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t10 = 300; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t11 = 300; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t15 = 30; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t16 = 20; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t18 = 200; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t19 = 690; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t21 = 650; + g_ftdm_sngss7_data.cfg.mtpRoute[0].t25 = 100; - return 0; + return 0; } /******************************************************************************/ static int ftmod_ss7_fill_in_circuits(char *ch_map, int cicbase, int typeCntrl, int isup_id, ftdm_span_t *span) { - sngss7_chan_data_t *ss7_info = NULL; - ftdm_channel_t *ftdmchan = NULL; - sng_timeslot_t timeslot; - int count; - int i; - int x; + sngss7_chan_data_t *ss7_info = NULL; + ftdm_channel_t *ftdmchan = NULL; + sng_timeslot_t timeslot; + int count; + int i; + int x; - count = 1; + count = 1; - while (ch_map[0] != '\0') { + while (ch_map[0] != '\0') { - /* pull out the next timeslot */ - if (ftmod_ss7_next_timeslot(ch_map, ×lot)) { - SS7_ERROR("Failed to parse the channel map!\n"); - return FTDM_FAIL; - } + /* pull out the next timeslot */ + if (ftmod_ss7_next_timeslot(ch_map, ×lot)) { + SS7_ERROR("Failed to parse the channel map!\n"); + return FTDM_FAIL; + } - if ((timeslot.siglink) || (timeslot.gap)) { - /* try to find the channel in the circuits structure*/ - x = 1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if ((g_ftdm_sngss7_data.cfg.isupCircuit[x].chan == count) && - (g_ftdm_sngss7_data.cfg.isupCircuit[x].span == span->channels[1]->physical_span_id)) { + if ((timeslot.siglink) || (timeslot.gap)) { + /* try to find the channel in the circuits structure*/ + x = 1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if ((g_ftdm_sngss7_data.cfg.isupCkt[x].chan == count) && + (g_ftdm_sngss7_data.cfg.isupCkt[x].span == span->channels[1]->physical_span_id)) { - SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is already exists...id=%d\n", - span->channels[1]->physical_span_id, - count, - x); + SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is already exists...id=%d\n", + span->channels[1]->physical_span_id, + count, + x); - /* we have a match so this circuit already exists in the structure */ - break; - } - /* move to the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) */ + /* we have a match so this circuit already exists in the structure */ + break; + } + /* move to the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - /* check why we exited the while loop */ - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) { - SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n", - span->channels[1]->physical_span_id, - count, - x); + /* check why we exited the while loop */ + if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) { + SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n", + span->channels[1]->physical_span_id, + count, + x); - /* prepare the global info sturcture */ - ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t)); - ss7_info->ftdmchan = NULL; - ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCircuit[x]; + /* prepare the global info sturcture */ + ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t)); + ss7_info->ftdmchan = NULL; + ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x]; - /* circuit is new so fill in the needed information */ - g_ftdm_sngss7_data.cfg.isupCircuit[x].id = x; - g_ftdm_sngss7_data.cfg.isupCircuit[x].span = span->channels[1]->physical_span_id; - g_ftdm_sngss7_data.cfg.isupCircuit[x].chan = count; - if (timeslot.siglink) { - g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink = 1; - } else { - g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink = 0; - } - if (timeslot.channel) { - g_ftdm_sngss7_data.cfg.isupCircuit[x].hole = 0; - g_ftdm_sngss7_data.cfg.isupCircuit[x].cic = cicbase; - cicbase++; - } else { - g_ftdm_sngss7_data.cfg.isupCircuit[x].hole = 1; - g_ftdm_sngss7_data.cfg.isupCircuit[x].cic = 0; - } - g_ftdm_sngss7_data.cfg.isupCircuit[x].infId = isup_id; - g_ftdm_sngss7_data.cfg.isupCircuit[x].typeCntrl = typeCntrl; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t3 = 1200; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t12 = 300; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t13 = 3000; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t14 = 300; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t15 = 3000; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t16 = 300; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t17 = 3000; - g_ftdm_sngss7_data.cfg.isupCircuit[x].tval = 10; - g_ftdm_sngss7_data.cfg.isupCircuit[x].obj = ss7_info; + /* circuit is new so fill in the needed information */ + g_ftdm_sngss7_data.cfg.isupCkt[x].id = x; + g_ftdm_sngss7_data.cfg.isupCkt[x].span = span->channels[1]->physical_span_id; + g_ftdm_sngss7_data.cfg.isupCkt[x].chan = count; + if (timeslot.siglink) { + g_ftdm_sngss7_data.cfg.isupCkt[x].type = SIG; + } else if (timeslot.hole) { + g_ftdm_sngss7_data.cfg.isupCkt[x].type = HOLE; + } else { + g_ftdm_sngss7_data.cfg.isupCkt[x].type = VOICE; + } + if (timeslot.channel) { + g_ftdm_sngss7_data.cfg.isupCkt[x].cic = cicbase; + cicbase++; + } else { + g_ftdm_sngss7_data.cfg.isupCkt[x].cic = 0; + } + g_ftdm_sngss7_data.cfg.isupCkt[x].infId = isup_id; + g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = typeCntrl; + g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = 1200; + g_ftdm_sngss7_data.cfg.isupCkt[x].t12 = 300; + g_ftdm_sngss7_data.cfg.isupCkt[x].t13 = 3000; + g_ftdm_sngss7_data.cfg.isupCkt[x].t14 = 300; + g_ftdm_sngss7_data.cfg.isupCkt[x].t15 = 3000; + g_ftdm_sngss7_data.cfg.isupCkt[x].t16 = 300; + g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = 3000; + g_ftdm_sngss7_data.cfg.isupCkt[x].tval = 10; + g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = g_ftdm_sngss7_data.cfg.isupIntf[isup_id].ssf; + g_ftdm_sngss7_data.cfg.isupCkt[x].obj = ss7_info; - } /* if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) */ - } else { /* if ((timeslot.siglink) || (timeslot.gap)) */ - /* find the ftdm the channel structure for this channel*/ - i = 1; - while (span->channels[i] != NULL) { - if (span->channels[i]->physical_chan_id == timeslot.channel) { - break; - } - i++; - } /* while (span->channels[i] != NULL) */ + } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */ + } else { /* if ((timeslot.siglink) || (timeslot.gap)) */ + /* find the ftdm the channel structure for this channel*/ + i = 1; + while (span->channels[i] != NULL) { + if (span->channels[i]->physical_chan_id == timeslot.channel) { + break; + } + i++; + } /* while (span->channels[i] != NULL) */ - if (span->channels[i] == NULL) { - /* we weren't able to find the channel in the ftdm channels */ - SS7_ERROR("Unable to find the requested channel %d in the FreeTDM channels!\n", timeslot.channel); - return FTDM_FAIL; - } else { - ftdmchan = span->channels[i]; - } + if (span->channels[i] == NULL) { + /* we weren't able to find the channel in the ftdm channels */ + SS7_ERROR("Unable to find the requested channel %d in the FreeTDM channels!\n", timeslot.channel); + return FTDM_FAIL; + } else { + ftdmchan = span->channels[i]; + } - /* try to find a match for the physical span and chan */ - x = 1; - while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) { - if ((g_ftdm_sngss7_data.cfg.isupCircuit[x].chan == ftdmchan->physical_chan_id) - && (g_ftdm_sngss7_data.cfg.isupCircuit[x].span == ftdmchan->physical_span_id)) { + /* try to find a match for the physical span and chan */ + x = 1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if ((g_ftdm_sngss7_data.cfg.isupCkt[x].chan == ftdmchan->physical_chan_id) + && (g_ftdm_sngss7_data.cfg.isupCkt[x].span == ftdmchan->physical_span_id)) { - /* we have a match so this circuit already exists in the structure */ - break; - } - /* move to the next circuit */ - x++; - } /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x].id != 0) */ + /* we have a match so this circuit already exists in the structure */ + break; + } + /* move to the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) */ - /* check why we exited the while loop */ - if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) { - SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - x); + /* check why we exited the while loop */ + if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) { + SS7_DEVEL_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id, + x); - /* prepare the global info sturcture */ - ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t)); - ss7_info->ftdmchan = ftdmchan; - ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCircuit[x]; - ftdmchan->call_data = ss7_info; + /* prepare the global info sturcture */ + ss7_info = ftdm_calloc(1, sizeof(sngss7_chan_data_t)); + ss7_info->ftdmchan = ftdmchan; + ss7_info->circuit = &g_ftdm_sngss7_data.cfg.isupCkt[x]; + ftdmchan->call_data = ss7_info; - /* prepare the timer structures */ - ss7_info->t35.sched = sngss7_sched; - ss7_info->t35.counter = 1; - ss7_info->t35.beat = g_ftdm_sngss7_data.cfg.isupInterface[isup_id].t35*100; /* beat is in ms, t35 is in 100ms */ - ss7_info->t35.callback = handle_isup_t35; - ss7_info->t35.sngss7_info = ss7_info; + /* prepare the timer structures */ + ss7_info->t35.sched = ((sngss7_span_data_t *)span->mod_data)->sched; + ss7_info->t35.counter = 1; + ss7_info->t35.beat = g_ftdm_sngss7_data.cfg.isupIntf[isup_id].t35*100; /* beat is in ms, t35 is in 100ms */ + ss7_info->t35.callback = handle_isup_t35; + ss7_info->t35.sngss7_info = ss7_info; - /* circuit is new so fill in the needed information */ - g_ftdm_sngss7_data.cfg.isupCircuit[x].id = x; - g_ftdm_sngss7_data.cfg.isupCircuit[x].span = ftdmchan->physical_span_id; - g_ftdm_sngss7_data.cfg.isupCircuit[x].chan = ftdmchan->physical_chan_id; - g_ftdm_sngss7_data.cfg.isupCircuit[x].siglink = 0; - g_ftdm_sngss7_data.cfg.isupCircuit[x].hole = 0; - g_ftdm_sngss7_data.cfg.isupCircuit[x].cic = cicbase; - g_ftdm_sngss7_data.cfg.isupCircuit[x].infId = isup_id; - g_ftdm_sngss7_data.cfg.isupCircuit[x].typeCntrl = typeCntrl; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t3 = 1200; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t12 = 300; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t13 = 3000; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t14 = 300; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t15 = 3000; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t16 = 300; - g_ftdm_sngss7_data.cfg.isupCircuit[x].t17 = 3000; - g_ftdm_sngss7_data.cfg.isupCircuit[x].tval = 10; - g_ftdm_sngss7_data.cfg.isupCircuit[x].obj = ss7_info; + /* circuit is new so fill in the needed information */ + g_ftdm_sngss7_data.cfg.isupCkt[x].id = x; + g_ftdm_sngss7_data.cfg.isupCkt[x].span = ftdmchan->physical_span_id; + g_ftdm_sngss7_data.cfg.isupCkt[x].chan = ftdmchan->physical_chan_id; + g_ftdm_sngss7_data.cfg.isupCkt[x].type = VOICE; + g_ftdm_sngss7_data.cfg.isupCkt[x].cic = cicbase; + g_ftdm_sngss7_data.cfg.isupCkt[x].infId = isup_id; + g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = typeCntrl; + g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = 1200; + g_ftdm_sngss7_data.cfg.isupCkt[x].t12 = 300; + g_ftdm_sngss7_data.cfg.isupCkt[x].t13 = 3000; + g_ftdm_sngss7_data.cfg.isupCkt[x].t14 = 300; + g_ftdm_sngss7_data.cfg.isupCkt[x].t15 = 3000; + g_ftdm_sngss7_data.cfg.isupCkt[x].t16 = 300; + g_ftdm_sngss7_data.cfg.isupCkt[x].t17 = 3000; + g_ftdm_sngss7_data.cfg.isupCkt[x].tval = 10; + g_ftdm_sngss7_data.cfg.isupCkt[x].obj = ss7_info; + g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = g_ftdm_sngss7_data.cfg.isupIntf[isup_id].ssf; - /* increment the cicbase */ - cicbase++; - } else { /* if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) */ - SS7_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - x); + /* increment the cicbase */ + cicbase++; + } else { /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */ + SS7_DEBUG("Circuit for span=%d, chan=%d is new...id=%d\n", + ftdmchan->physical_span_id, + ftdmchan->physical_chan_id, + x); - /* for now make sure ss7_info is set to null */ - ss7_info = NULL; + /* for now make sure ss7_info is set to null */ + ss7_info = NULL; - /* KONRAD FIX ME -> confirm that it is the same circuit */ - } /* if (g_ftdm_sngss7_data.cfg.isupCircuit[x].id == 0) */ + /* KONRAD FIX ME -> confirm that it is the same circuit */ + } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */ - /* increment the span channel count */ - count++; - } /* if ((timeslot.siglink) || (timeslot.gap)) */ + /* increment the span channel count */ + count++; + } /* if ((timeslot.siglink) || (timeslot.gap)) */ - if (ss7_info == NULL) { - SS7_ERROR("KONRAD -> circuit was not configured !\n"); - return FTDM_FAIL; - } + if (ss7_info == NULL) { + SS7_ERROR("KONRAD -> circuit was not configured !\n"); + return FTDM_FAIL; + } - if (ss7_info->ftdmchan == NULL) { - SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n", - g_ftdm_sngss7_data.cfg.isupCircuit[x].span, - g_ftdm_sngss7_data.cfg.isupCircuit[x].chan, - g_ftdm_sngss7_data.cfg.isupCircuit[x].cic, - 0, - g_ftdm_sngss7_data.cfg.isupCircuit[x].id); - } else { - SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n", - g_ftdm_sngss7_data.cfg.isupCircuit[x].span, - g_ftdm_sngss7_data.cfg.isupCircuit[x].chan, - g_ftdm_sngss7_data.cfg.isupCircuit[x].cic, - ss7_info->ftdmchan->chan_id, - g_ftdm_sngss7_data.cfg.isupCircuit[x].id); - } + if (ss7_info->ftdmchan == NULL) { + SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n", + g_ftdm_sngss7_data.cfg.isupCkt[x].span, + g_ftdm_sngss7_data.cfg.isupCkt[x].chan, + g_ftdm_sngss7_data.cfg.isupCkt[x].cic, + 0, + g_ftdm_sngss7_data.cfg.isupCkt[x].id); + } else { + SS7_INFO("Added span = %d, chan = %d, cic = %d, FTDM chan = %d, ISUP cirId = %d\n", + g_ftdm_sngss7_data.cfg.isupCkt[x].span, + g_ftdm_sngss7_data.cfg.isupCkt[x].chan, + g_ftdm_sngss7_data.cfg.isupCkt[x].cic, + ss7_info->ftdmchan->chan_id, + g_ftdm_sngss7_data.cfg.isupCkt[x].id); + } - } /* while (ch_map[0] != '\0') */ + } /* while (ch_map[0] != '\0') */ - return 0; + return 0; } /******************************************************************************/ static int ftmod_ss7_next_timeslot(char *ch_map, sng_timeslot_t *timeslot) { - int i; - int x; - int lower; - int upper; - char tmp[5]; /*KONRAD FIX ME*/ - char new_ch_map[MAX_CIC_LENGTH]; + int i; + int x; + int lower; + int upper; + char tmp[5]; /*KONRAD FIX ME*/ + char new_ch_map[MAX_CIC_LENGTH]; - memset(&tmp[0], '\0', sizeof(tmp)); - memset(&new_ch_map[0], '\0', sizeof(new_ch_map)); - memset(timeslot, 0x0, sizeof(sng_timeslot_t)); + memset(&tmp[0], '\0', sizeof(tmp)); + memset(&new_ch_map[0], '\0', sizeof(new_ch_map)); + memset(timeslot, 0x0, sizeof(sng_timeslot_t)); - SS7_DEVEL_DEBUG("Old channel map = \"%s\"\n", ch_map); + SS7_DEVEL_DEBUG("Old channel map = \"%s\"\n", ch_map); - /* start at the beginning of the ch_map */ - x = 0; + /* start at the beginning of the ch_map */ + x = 0; - switch (ch_map[x]) { - /**************************************************************************/ - case 'S': - case 's': /* we have a sig link */ - timeslot->siglink = 1; + switch (ch_map[x]) { + /**************************************************************************/ + case 'S': + case 's': /* we have a sig link */ + timeslot->siglink = 1; - /* check what comes next either a comma or a number */ - x++; - if (ch_map[x] == ',') { - timeslot->hole = 1; - SS7_DEVEL_DEBUG(" Found a siglink in the channel map with a hole in the cic map\n"); - } else if (isdigit(ch_map[x])) { - /* consume all digits until a comma as this is the channel */ - SS7_DEVEL_DEBUG(" Found a siglink in the channel map with out a hole in the cic map\n"); - } else { - SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]); - return FTDM_FAIL; - } - break; - /**************************************************************************/ - case 'G': - case 'g': /* we have a channel gap */ - timeslot->gap = 1; + /* check what comes next either a comma or a number */ + x++; + if (ch_map[x] == ',') { + timeslot->hole = 1; + SS7_DEVEL_DEBUG(" Found a siglink in the channel map with a hole in the cic map\n"); + } else if (isdigit(ch_map[x])) { + /* consume all digits until a comma as this is the channel */ + SS7_DEVEL_DEBUG(" Found a siglink in the channel map with out a hole in the cic map\n"); + } else { + SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]); + return FTDM_FAIL; + } + break; + /**************************************************************************/ + case 'G': + case 'g': /* we have a channel gap */ + timeslot->gap = 1; - /* check what comes next either a comma or a number */ - x++; - if (ch_map[x] == ',') { - timeslot->hole = 1; - SS7_DEVEL_DEBUG(" Found a gap in the channel map with a hole in the cic map\n"); - } else if (isdigit(ch_map[x])) { - SS7_DEVEL_DEBUG(" Found a gap in the channel map with out a hole in the cic map\n"); - /* consume all digits until a comma as this is the channel */ - } else { - SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]); - return FTDM_FAIL; - } - break; - /**************************************************************************/ - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': /* we have a channel */ - /* consume all digits until a comma or a dash */ - SS7_DEVEL_DEBUG("Found a starting channel in the channel map\n"); - break; - /**************************************************************************/ - default: - SS7_ERROR("Found an illegal channel map character = \"%c\"!\n", ch_map[x]); - return FTDM_FAIL; - /**************************************************************************/ - } /* switch (ch_map[x]) */ + /* check what comes next either a comma or a number */ + x++; + if (ch_map[x] == ',') { + timeslot->hole = 1; + SS7_DEVEL_DEBUG(" Found a gap in the channel map with a hole in the cic map\n"); + } else if (isdigit(ch_map[x])) { + SS7_DEVEL_DEBUG(" Found a gap in the channel map with out a hole in the cic map\n"); + /* consume all digits until a comma as this is the channel */ + } else { + SS7_ERROR("Found an illegal channel map character after signal link flag = \"%c\"!\n", ch_map[x]); + return FTDM_FAIL; + } + break; + /**************************************************************************/ + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': /* we have a channel */ + /* consume all digits until a comma or a dash */ + SS7_DEVEL_DEBUG("Found a starting channel in the channel map\n"); + break; + /**************************************************************************/ + default: + SS7_ERROR("Found an illegal channel map character = \"%c\"!\n", ch_map[x]); + return FTDM_FAIL; + /**************************************************************************/ + } /* switch (ch_map[x]) */ - /* grab the first number in the string */ - i = 0; - while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) { - tmp[i] = ch_map[x]; - i++; - x++; - } - tmp[i] = '\0'; - timeslot->channel = atoi(tmp); - lower = timeslot->channel + 1; + /* grab the first number in the string */ + i = 0; + while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) { + tmp[i] = ch_map[x]; + i++; + x++; + } + tmp[i] = '\0'; + timeslot->channel = atoi(tmp); + lower = timeslot->channel + 1; - /* check the next value in the list */ - if (ch_map[x] == '-') { - /* consume the number after the dash */ - x++; - i = 0; - while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) { - tmp[i] = ch_map[x]; - i++; - x++; - } - tmp[i] = '\0'; - upper = atoi(tmp); + /* check the next value in the list */ + if (ch_map[x] == '-') { + /* consume the number after the dash */ + x++; + i = 0; + while ((ch_map[x] != '\0') && (ch_map[x] != '-') && (ch_map[x] != ',')) { + tmp[i] = ch_map[x]; + i++; + x++; + } + tmp[i] = '\0'; + upper = atoi(tmp); - /* check if the upper end of the range is the same as the lower end of the range */ - if (upper == lower) { - /* the range is completed, eat the next comma or \0 and write it */ - sprintf(new_ch_map, "%d", lower); - } else if ( upper > lower) { - /* the list continues, add 1 from the channel map value and re-insert it to the list */ - sprintf(new_ch_map, "%d-%d", lower, upper); - } else { - SS7_ERROR("The upper is less then the lower end of the range...should not happen!\n"); - return FTDM_FAIL; - } + /* check if the upper end of the range is the same as the lower end of the range */ + if (upper == lower) { + /* the range is completed, eat the next comma or \0 and write it */ + sprintf(new_ch_map, "%d", lower); + } else if ( upper > lower) { + /* the list continues, add 1 from the channel map value and re-insert it to the list */ + sprintf(new_ch_map, "%d-%d", lower, upper); + } else { + SS7_ERROR("The upper is less then the lower end of the range...should not happen!\n"); + return FTDM_FAIL; + } - /* the the rest of ch_map to new_ch_map */ - strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x])); + /* the the rest of ch_map to new_ch_map */ + strncat(new_ch_map, &ch_map[x], strlen(&ch_map[x])); - /* set the new cic map to ch_map*/ - strcpy(ch_map, new_ch_map); + /* set the new cic map to ch_map*/ + strcpy(ch_map, new_ch_map); - } else if (ch_map[x] == ',') { - /* move past the comma */ - x++; + } else if (ch_map[x] == ',') { + /* move past the comma */ + x++; - /* copy the rest of the list to new_ch_map */ - strcpy(new_ch_map, &ch_map[x]); + /* copy the rest of the list to new_ch_map */ + strcpy(new_ch_map, &ch_map[x]); - /* copy the new_ch_map over the old one */ - strcpy(ch_map, new_ch_map); + /* copy the new_ch_map over the old one */ + strcpy(ch_map, new_ch_map); - } else if (ch_map[x] == '\0') { - /* we're at the end of the string...copy the rest of the list to new_ch_map */ - strcpy(new_ch_map, &ch_map[x]); + } else if (ch_map[x] == '\0') { + /* we're at the end of the string...copy the rest of the list to new_ch_map */ + strcpy(new_ch_map, &ch_map[x]); - /* set the new cic map to ch_map*/ - strcpy(ch_map, new_ch_map); - } else { - /* nothing to do */ - } + /* set the new cic map to ch_map*/ + strcpy(ch_map, new_ch_map); + } else { + /* nothing to do */ + } - SS7_DEVEL_DEBUG("New channel map = \"%s\"\n", ch_map); + SS7_DEVEL_DEBUG("New channel map = \"%s\"\n", ch_map); - return FTDM_SUCCESS; + return FTDM_SUCCESS; } /******************************************************************************/ + +/******************************************************************************/ +/* For Emacs: + * Local Variables: + * mode:c + * indent-tabs-mode:t + * tab-width:4 + * c-basic-offset:4 + * End: + * For VIM: + * vim:set softtabstop=4 shiftwidth=4 tabstop=4: + */ +/******************************************************************************/ diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index af55370338..0437e02e51 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -60,6 +60,8 @@ /*! \brief Max number of groups */ #define FTDM_MAX_GROUPS_INTERFACE FTDM_MAX_SPANS_INTERFACE +#define FTDM_INVALID_INT_PARM 0xFF + /*! \brief FreeTDM APIs possible return codes */ typedef enum { FTDM_SUCCESS, /*!< Success */ @@ -208,6 +210,7 @@ typedef struct ftdm_queue_handler { ftdm_queue_destroy_func_t destroy; } ftdm_queue_handler_t; + /*! \brief Type Of Number (TON) */ typedef enum { FTDM_TON_UNKNOWN = 0, @@ -239,6 +242,20 @@ typedef struct { uint8_t plan; } ftdm_number_t; +/*! \brief bearer capability */ +typedef enum { + FTDM_BEARER_CAP_SPEECH = 0x00, + FTDM_BEARER_CAP_64K_UNRESTRICTED = 0x02, + FTDM_BEARER_CAP_3_1KHZ_AUDIO = 0x03 +} ftdm_bearer_cap_t; + +/*! \brief user information layer 1 protocol */ +typedef enum { + FTDM_USER_LAYER1_PROT_V110 = 0x01, + FTDM_USER_LAYER1_PROT_ULAW = 0x02, + FTDM_USER_LAYER1_PROT_ALAW = 0x03, +} ftdm_user_layer1_prot_t; + /*! \brief Caller information */ typedef struct ftdm_caller_data { char cid_date[8]; /*!< Caller ID date */ @@ -256,9 +273,9 @@ typedef struct ftdm_caller_data { uint32_t raw_data_len; /* !< Raw data length */ /* these 2 are undocumented right now, only used by boost: */ /* bearer capability */ - uint8_t bearer_capability; + ftdm_bearer_cap_t bearer_capability; /* user information layer 1 protocol */ - uint8_t bearer_layer1; + ftdm_user_layer1_prot_t bearer_layer1; } ftdm_caller_data_t; /*! \brief Tone type */ @@ -317,23 +334,6 @@ typedef struct ftdm_channel_config { float txgain; } ftdm_channel_config_t; -/*! \brief Generic signaling message */ -struct ftdm_sigmsg { - ftdm_signal_event_t event_id; /*!< The type of message */ - ftdm_channel_t *channel; /*!< Related channel */ - uint32_t chan_id; /*!< easy access to chan id */ - uint32_t span_id; /*!< easy access to span_id */ - void *raw_data; /*!< Message specific data if any */ - uint32_t raw_data_len; /*!< Data len in case is needed */ -}; - -/*! \brief Crash policy - * Useful for debugging only, default policy is never, if you wish to crash on asserts then use ftdm_global_set_crash_policy */ -typedef enum { - FTDM_CRASH_NEVER = 0, - FTDM_CRASH_ON_ASSERT -} ftdm_crash_policy_t; - /*! \brief Signaling status on a given span or specific channel on protocols that support it */ @@ -352,6 +352,24 @@ typedef enum { /*! \brief Move from string to ftdm_signaling_status_t and viceversa */ FTDM_STR2ENUM_P(ftdm_str2ftdm_signaling_status, ftdm_signaling_status2str, ftdm_signaling_status_t) +/*! \brief Generic signaling message */ +struct ftdm_sigmsg { + ftdm_signal_event_t event_id; /*!< The type of message */ + ftdm_channel_t *channel; /*!< Related channel */ + uint32_t chan_id; /*!< easy access to chan id */ + uint32_t span_id; /*!< easy access to span_id */ + ftdm_signaling_status_t sigstatus; /*!< Signaling status (valid if event_id is FTDM_SIGEVENT_SIGSTATUS_CHANGED) */ + void *raw_data; /*!< Message specific data if any */ + uint32_t raw_data_len; /*!< Data len in case is needed */ +}; + +/*! \brief Crash policy + * Useful for debugging only, default policy is never, if you wish to crash on asserts then use ftdm_global_set_crash_policy */ +typedef enum { + FTDM_CRASH_NEVER = 0, + FTDM_CRASH_ON_ASSERT +} ftdm_crash_policy_t; + /*! \brief I/O waiting flags */ typedef enum { FTDM_NO_FLAGS = 0, @@ -367,6 +385,9 @@ typedef struct ftdm_conf_parameter { void *ptr; } ftdm_conf_parameter_t; +/*! \brief Opaque general purpose iterator */ +typedef void ftdm_iterator_t; + /*! \brief Channel commands that can be executed through ftdm_channel_command() */ typedef enum { FTDM_COMMAND_NOOP, @@ -1000,14 +1021,25 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_read(ftdm_channel_t *ftdmchan, void *data */ FT_DECLARE(ftdm_status_t) ftdm_channel_write(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t datasize, ftdm_size_t *datalen); -/*! \brief Add a custom variable to the channel */ +/*! \brief Add a custom variable to the channel + * \note This variables may be used by signaling modules to override signaling parameters + * \todo Document which signaling variables are available + * */ FT_DECLARE(ftdm_status_t) ftdm_channel_add_var(ftdm_channel_t *ftdmchan, const char *var_name, const char *value); -/*! \brief Get a custom variable from the channel */ +/*! \brief Get a custom variable from the channel. + * \note The variable pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. */ FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name); -/*! \brief Clear custom channel variables from the channel */ -FT_DECLARE(ftdm_status_t) ftdm_channel_clear_vars(ftdm_channel_t *ftdmchan); +/*! \brief Get an iterator to iterate over the channel variables + * \note The iterator pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. */ +FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan); + +/*! \brief Get variable name and value for the current iterator position */ +FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val); + +/*! \brief Advance iterator */ +FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter); /*! \brief Get the span pointer associated to the channel */ FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan); diff --git a/libs/freetdm/src/include/private/ftdm_call_utils.h b/libs/freetdm/src/include/private/ftdm_call_utils.h new file mode 100644 index 0000000000..782abde927 --- /dev/null +++ b/libs/freetdm/src/include/private/ftdm_call_utils.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010, Sangoma Technologies + * David Yat Sin + * 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. + */ + +#ifndef __FTDM_CALL_UTILS_H__ +#define __FTDM_CALL_UTILS_H__ + +#include "freetdm.h" + +FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target); +FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target); +FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_capability(const char *bc_string, ftdm_bearer_cap_t *target); +FT_DECLARE(ftdm_status_t) ftdm_span_set_bearer_layer1(const char *bc_string, ftdm_user_layer1_prot_t *target); +FT_DECLARE(ftdm_status_t) ftdm_is_number(char *number); + +#endif /* __FTDM_CALL_UTILS_H__ */ + diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 8f149318b3..74bea8148c 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -117,6 +117,7 @@ #include "ftdm_buffer.h" #include "ftdm_threadmutex.h" #include "ftdm_sched.h" +#include "ftdm_call_utils.h" #ifdef __cplusplus extern "C" { @@ -465,6 +466,7 @@ struct ftdm_span { ftdm_state_map_t *state_map; ftdm_caller_data_t default_caller_data; ftdm_queue_t *pendingchans; + ftdm_queue_t *pendingsignals; struct ftdm_span *next; }; @@ -578,6 +580,8 @@ FT_DECLARE(ftdm_status_t) ftdm_span_next_event(ftdm_span_t *span, ftdm_event_t * */ FT_DECLARE(ftdm_status_t) ftdm_channel_queue_dtmf(ftdm_channel_t *ftdmchan, const char *dtmf); +/* dequeue pending signals and notify the user via the span signal callback */ +FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span); /*! \brief Assert condition diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index 572e63299b..d8e8b5c2e6 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -176,6 +176,10 @@ typedef enum { FTDM_SPAN_USE_CHAN_QUEUE = (1 << 6), FTDM_SPAN_SUGGEST_CHAN_ID = (1 << 7), FTDM_SPAN_USE_AV_RATE = (1 << 8), + /* If you use this flag, you MUST call ftdm_span_trigger_signals to deliver the user signals + * after having called ftdm_send_span_signal(), which with this flag it will just enqueue the signal + * for later delivery */ + FTDM_SPAN_USE_SIGNALS_QUEUE = (1 << 9), } ftdm_span_flag_t; /*! \brief Channel supported features */