Merge remote branch 'smgfs/master'
This commit is contained in:
commit
7fd0f84cce
|
@ -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 \
|
||||
|
@ -266,12 +270,17 @@ 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_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_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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
@ -2107,9 +2118,9 @@ 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")) {
|
||||
|
@ -2620,6 +2633,32 @@ static switch_status_t load_config(void)
|
|||
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");
|
||||
char *val = (char *) switch_xml_attr_soft(param, "value");
|
||||
|
@ -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")) {
|
||||
|
@ -3358,6 +3419,10 @@ static switch_status_t load_config(void)
|
|||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <dyatsin@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "private/ftdm_core.h"
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
FT_DECLARE(ftdm_status_t) ftdm_span_set_npi(const char *npi_string, uint8_t *target)
|
||||
{
|
||||
if (!strcasecmp(npi_string, "isdn") || !strcasecmp(npi_string, "e164")) {
|
||||
*target = FTDM_NPI_ISDN;
|
||||
} else if (!strcasecmp(npi_string, "data")) {
|
||||
*target = FTDM_NPI_DATA;
|
||||
} else if (!strcasecmp(npi_string, "telex")) {
|
||||
*target = FTDM_NPI_TELEX;
|
||||
} else if (!strcasecmp(npi_string, "national")) {
|
||||
*target = FTDM_NPI_NATIONAL;
|
||||
} else if (!strcasecmp(npi_string, "private")) {
|
||||
*target = FTDM_NPI_PRIVATE;
|
||||
} else if (!strcasecmp(npi_string, "reserved")) {
|
||||
*target = FTDM_NPI_RESERVED;
|
||||
} else if (!strcasecmp(npi_string, "unknown")) {
|
||||
*target = FTDM_NPI_UNKNOWN;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Invalid NPI value (%s)\n", npi_string);
|
||||
*target = FTDM_NPI_UNKNOWN;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
FT_DECLARE(ftdm_status_t) ftdm_span_set_ton(const char *ton_string, uint8_t *target)
|
||||
{
|
||||
if (!strcasecmp(ton_string, "national")) {
|
||||
*target = FTDM_TON_NATIONAL;
|
||||
} else if (!strcasecmp(ton_string, "international")) {
|
||||
*target = FTDM_TON_INTERNATIONAL;
|
||||
} else if (!strcasecmp(ton_string, "local")) {
|
||||
*target = FTDM_TON_SUBSCRIBER_NUMBER;
|
||||
} else if (!strcasecmp(ton_string, "unknown")) {
|
||||
*target = FTDM_TON_UNKNOWN;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_WARNING, "Invalid TON value (%s)\n", ton_string);
|
||||
*target = FTDM_TON_UNKNOWN;
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
FT_DECLARE(ftdm_status_t) ftdm_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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
{
|
||||
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);
|
||||
|
||||
if(!ftdmchan->variable_hash)
|
||||
return FTDM_FAIL;
|
||||
ftdmchan->variable_hash = NULL;
|
||||
|
||||
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,11 +4508,14 @@ 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_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;
|
||||
|
||||
case FTDM_SIGEVENT_START:
|
||||
|
@ -4408,9 +4538,11 @@ FT_DECLARE(ftdm_status_t) ftdm_span_send_signal(ftdm_span_t *span, ftdm_sigmsg_t
|
|||
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
|
|
@ -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,13 +373,24 @@ 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;
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <sys/mman.h>
|
||||
#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,
|
||||
|
@ -136,7 +153,6 @@ ftdm_state_map_t sangoma_isdn_state_map = {
|
|||
{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,32 +253,40 @@ 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))) {
|
||||
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 */
|
||||
switch ((ftdm_interrupt_wait(ftdm_sangoma_isdn_int, 100))) {
|
||||
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 */
|
||||
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");
|
||||
}
|
||||
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;
|
||||
|
@ -259,9 +294,12 @@ static void *ftdm_sangoma_isdn_run(ftdm_thread_t *me, void *obj)
|
|||
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 */
|
||||
|
@ -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: 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 */
|
||||
}
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
/* 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 {
|
||||
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 */
|
||||
ftdm_channel_close(&close_chan);
|
||||
}
|
||||
if (glare) {
|
||||
|
||||
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:
|
||||
{
|
||||
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");
|
||||
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
|
||||
|
||||
status = FTDM_BREAK;
|
||||
} else {
|
||||
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DIALING);
|
||||
|
||||
/* unlock the channel */
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
|
||||
/* 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_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:
|
||||
{
|
||||
/* 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;
|
||||
|
@ -949,6 +840,8 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
|
|||
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_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;
|
||||
|
@ -957,13 +850,11 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
|
|||
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 <q921|q931> <span name>\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 <span name>\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;
|
||||
|
|
|
@ -46,116 +46,28 @@
|
|||
|
||||
#include <sng_isdn.h>
|
||||
|
||||
#define MAX_SPANS_PER_NFAS_LINK 8 /* TODO: Confirm this value */
|
||||
/* Theoretical limit for MAX_SPANS_PER_NFAS_LINK is 31,
|
||||
but set to 8 for now to save some memor */
|
||||
|
||||
#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
|
||||
|
||||
/* 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 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__ */
|
||||
|
||||
|
|
|
@ -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,9 +158,33 @@ 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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
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.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.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.t312.val = 35;
|
||||
}
|
||||
|
||||
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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,942 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <dyatsin@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
extern ftdm_status_t cpy_calling_num_from_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;
|
||||
}
|
|
@ -1,935 +0,0 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <davidy@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
extern ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
|
||||
extern ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
|
||||
extern ftdm_status_t cpy_called_name_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
|
||||
extern ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt);
|
||||
extern void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
|
||||
extern void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
|
||||
extern void get_memory_info(void);
|
||||
|
||||
extern ftdm_sngisdn_data_t g_sngisdn_data;
|
||||
|
||||
#define MAX_DECODE_STR_LEN 2000
|
||||
|
||||
/* Remote side transmit a SETUP */
|
||||
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
uint8_t bchan_no = 0;
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan;
|
||||
/*sngisdn_span_data_t *span_info;*/
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
|
||||
|
||||
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
|
||||
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
|
||||
ftdm_assert(g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] == NULL, "Con Ind on busy spInstId");
|
||||
|
||||
if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
|
||||
/* TODO: Implement me */
|
||||
ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n");
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conEvnt->chanId.chanNmbSlotMap.pres) {
|
||||
bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0];
|
||||
} else if (conEvnt->chanId.infoChanSel.pres) {
|
||||
bchan_no = conEvnt->chanId.infoChanSel.val;
|
||||
}
|
||||
|
||||
if (!bchan_no) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n");
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_sngisdn_data.dchans[dChan].channels[bchan_no] == NULL) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP\n");
|
||||
switch (ftdmchan->state){
|
||||
case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
|
||||
sngisdn_info->suInstId = get_unique_suInstId(suId);
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
|
||||
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
|
||||
|
||||
/* try to open the channel */
|
||||
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
|
||||
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
|
||||
} else {
|
||||
/* Fill in call information */
|
||||
cpy_calling_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
|
||||
cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
|
||||
cpy_calling_name_from_sngisdn(&ftdmchan->caller_data, conEvnt);
|
||||
|
||||
/* Get ani2 */
|
||||
#if 0
|
||||
/* TODO: confirm that this works in the field */
|
||||
if (conEvnt->niOperSysAcc.eh.pres) {
|
||||
if (conEvnt->niOperSysAcc.typeAcc.pres) {
|
||||
ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeAcc.val;
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of access:%x", conEvnt->niOperSysAcc.typeAcc.val);
|
||||
}
|
||||
if (conEvnt->niOperSysAcc.typeServ.pres) {
|
||||
ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeServ.val;
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of service:%x", conEvnt->niOperSysAcc.typeServ.val);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* set the state of the channel to collecting...the rest is done by the chan monitor */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
|
||||
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DIALING: /* glare */
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received SETUP in DIALING state, glare, queueing incoming call\n");
|
||||
/* the flag the channel as having a collision */
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
|
||||
|
||||
/* save the SETUP for processing once the channel has gone to DOWN */
|
||||
memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
|
||||
sngisdn_info->glare.suId = suId;
|
||||
sngisdn_info->glare.suInstId = suInstId;
|
||||
sngisdn_info->glare.spInstId = spInstId;
|
||||
sngisdn_info->glare.dChan = dChan;
|
||||
sngisdn_info->glare.ces = ces;
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
break;
|
||||
}
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remote side transmit a CONNECT or CONNECT ACK */
|
||||
void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan;
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
|
||||
|
||||
|
||||
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
|
||||
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
|
||||
|
||||
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
|
||||
|
||||
if (!sngisdn_info->spInstId) {
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK\n");
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
|
||||
((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
|
||||
|
||||
if(sngisdn_info->ces == CES_MNGMNT) {
|
||||
/* We assign the call to the first TE */
|
||||
sngisdn_info->ces = ces;
|
||||
} else {
|
||||
/* We already assigned this call, do nothing */
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n");
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
/* This is the only valid state we should get a CONNECT ACK on */
|
||||
/* do nothing */
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan;
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
|
||||
|
||||
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
|
||||
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
|
||||
|
||||
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sngisdn_info->spInstId) {
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
|
||||
}
|
||||
|
||||
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Received %s\n",
|
||||
(evntType == MI_ALERTING)?"ALERT":
|
||||
(evntType == MI_CALLPROC)?"PROCEED":
|
||||
(evntType == MI_PROGRESS)?"PROGRESS":"UNKNOWN");
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
if (evntType == MI_PROGRESS) {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
} else {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
if (evntType == MI_PROGRESS) {
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
|
||||
}
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
/* Do nothing */
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received ALERT/PROCEED/PROGRESS in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
|
||||
|
||||
ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
|
||||
|
||||
if (spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) {
|
||||
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
|
||||
} else if (suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS) {
|
||||
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
|
||||
} else {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!sngisdn_info->spInstId) {
|
||||
sngisdn_info->spInstId = spInstId;
|
||||
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT\n");
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_RING:
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
case FTDM_CHANNEL_STATE_COLLECT:
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
|
||||
ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
|
||||
} else {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n");
|
||||
ftdmchan->caller_data.hangup_cause = 0;
|
||||
}
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
/* start reset procedure */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info ;
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
|
||||
/* get the ftdmchan and ss7_chan_data from the circuit */
|
||||
if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
} else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
}
|
||||
|
||||
if (ftdmchan == NULL) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE\n");
|
||||
/* now that we have the right channel...put a lock on it so no-one else can use it */
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
};
|
||||
|
||||
/* check whether the ftdm channel is in a state to accept a call */
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
|
||||
/* go to DOWN */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DOWN:
|
||||
/* do nothing, just drop the message */
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_PROGRESS:
|
||||
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
|
||||
/* Remote side sent a SETUP, then a RELEASE COMPLETE to abort call - this is an abort */
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
/* Remote side rejected our SETUP message on outbound call */
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
default:
|
||||
/* Should just stop the call...but a reset is easier for now (since it does hangup the call) */
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
|
||||
ftdm_channel_state2str(ftdmchan->state));
|
||||
|
||||
/* go to RESTART */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
|
||||
break;
|
||||
/**************************************************************************/
|
||||
}
|
||||
|
||||
/* unlock the channel */
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received DATA IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received SSHL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received SSHL CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE ind suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received FLOW CONTROL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received FACILITY IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info ;
|
||||
ftdm_channel_t *ftdmchan = NULL;
|
||||
uint8_t call_state = 0;
|
||||
|
||||
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
|
||||
call_state = staEvnt->callSte.callGlblSte.val;
|
||||
}
|
||||
|
||||
/* get the ftdmchan and ss7_chan_data from the circuit */
|
||||
if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
} else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
|
||||
ftdmchan = sngisdn_info->ftdmchan;
|
||||
}
|
||||
|
||||
if (ftdmchan == NULL) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM\n");
|
||||
/* now that we have the right channel...put a lock on it so no-one else can use it */
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
|
||||
/* check if there is a pending state change, give it a bit to clear */
|
||||
if (check_for_state_change(ftdmchan)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
};
|
||||
|
||||
if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) {
|
||||
if (staEvnt->causeDgn[0].causeVal.val != 30) {
|
||||
|
||||
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
|
||||
call_state = staEvnt->callSte.callGlblSte.val;
|
||||
/* Section 4.3.30 from INT Interface - Service Definition */
|
||||
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
|
||||
|
||||
|
||||
/* There is incompatibility between local and remote side call states some Q931 msgs probably got lost - initiate disconnect */
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Incompatible call states detected, remote side indicated state:%d our state:%s cause:%d\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val);
|
||||
|
||||
switch(call_state) {
|
||||
/* Sere ITU-T Q931 for definition of call states */
|
||||
case 0: /* Remote switch thinks there are no calls on this channel */
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_COLLECT:
|
||||
case FTDM_CHANNEL_STATE_DIALING:
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_TERMINATING:
|
||||
/* We are in the process of clearing local states,
|
||||
just make sure we will not send any messages to remote switch */
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_HANGUP:
|
||||
/* This cannot happen, state_advance always sets
|
||||
ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
|
||||
and we called check_for_state_change earlier so something is very wrong here!!! */
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
|
||||
/* We were waiting for remote switch to send RELEASE COMPLETE
|
||||
but this will not happen, so just clear local state */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_DOWN:
|
||||
/* If our local state is down as well, then there is nothing to do */
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 8: /* Remote switch is in "Connect Request state" */
|
||||
switch (ftdmchan->state) {
|
||||
case FTDM_CHANNEL_STATE_UP:
|
||||
/* This is ok. We sent a Connect, and we are waiting for a connect ack */
|
||||
/* Do nothing */
|
||||
break;
|
||||
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
|
||||
/* We hung up locally, but remote switch doesn't know send disconnect again*/
|
||||
sngisdn_snd_disconnect(ftdmchan);
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
|
||||
/* We could not extract the call state */
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible call states detected, but could not determine call (cause:%d)\n", ftdmchan->caller_data.hangup_cause);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
}
|
||||
|
||||
}
|
||||
/**************************************************************************/
|
||||
}
|
||||
|
||||
/* unlock the channel */
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESTART IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_q921_ind(BdMngmt *status)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
|
||||
unsigned j,k;
|
||||
ftdm_span_t *ftdmspan = NULL;
|
||||
|
||||
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
|
||||
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
|
||||
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.lnkNmb) {
|
||||
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ftdmspan == NULL) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received q921 status on unconfigured span\n", status->t.usta.lnkNmb);
|
||||
#ifdef DEBUG_MODE
|
||||
FORCE_SEGFAULT
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status->t.usta.alarm.category) {
|
||||
case (LCM_CATEGORY_INTERFACE):
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
|
||||
ftdmspan->name,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
|
||||
ftdmspan->name,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
break;
|
||||
}
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__)
|
||||
return;
|
||||
}
|
||||
void sngisdn_rcv_q931_ind(InMngmt *status)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
|
||||
|
||||
|
||||
ftdm_span_t *ftdmspan = NULL;
|
||||
|
||||
if (status->t.usta.alarm.cause == 287) {
|
||||
get_memory_info();
|
||||
return;
|
||||
}
|
||||
|
||||
switch (status->t.usta.alarm.category) {
|
||||
case (LCM_CATEGORY_INTERFACE):
|
||||
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
|
||||
status->t.usta.suId,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
|
||||
/* clean this up later */
|
||||
|
||||
switch (status->t.usta.alarm.event) {
|
||||
case LCM_EVENT_UP:
|
||||
case LCM_EVENT_DOWN:
|
||||
{
|
||||
unsigned j,k;
|
||||
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
|
||||
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
|
||||
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.suId) {
|
||||
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ftdmspan == NULL) {
|
||||
ftdm_log(FTDM_LOG_CRIT, "Received q931 LCM EVENT on unconfigured span (suId:%d)\n", status->t.usta.suId);
|
||||
return;
|
||||
}
|
||||
|
||||
sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP)?FTDM_SIG_STATE_UP:FTDM_SIG_STATE_DOWN);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
|
||||
status->t.usta.suId,
|
||||
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
|
||||
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
|
||||
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_cc_ind(CcMngmt *status)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
ftdm_log(FTDM_LOG_INFO, "RECEIVED %s\n", __FUNCTION__);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
|
||||
(event == TL3PKTRX)?"RX":"UNKNOWN"
|
||||
|
||||
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
|
||||
{
|
||||
MsgLen mlen;
|
||||
MsgLen i;
|
||||
int16_t j;
|
||||
Buffer *tmp;
|
||||
Data *cptr;
|
||||
uint8_t data;
|
||||
uint8_t tdata[1000];
|
||||
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
|
||||
|
||||
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
|
||||
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
|
||||
|
||||
if (mlen != 0) {
|
||||
tmp = mBuf->b_cont;
|
||||
cptr = tmp->b_rptr;
|
||||
data = *cptr++;
|
||||
i = 0;
|
||||
|
||||
for(j=0;j<mlen;j++) {
|
||||
tdata[j]= data;
|
||||
|
||||
if (cptr == tmp->b_wptr) {
|
||||
tmp = tmp->b_cont;
|
||||
if (tmp) cptr = tmp->b_rptr;
|
||||
}
|
||||
data = *cptr++;
|
||||
}
|
||||
|
||||
sngisdn_trace_q931(data_str, tdata, mlen);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] FRAME %s:%s\n", Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
|
||||
}
|
||||
|
||||
ftdm_safe_free(data_str);
|
||||
/* We do not need to free mBuf in this case because stack does it */
|
||||
/* SPutMsg(mBuf); */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
|
||||
(event == TL2FRMTX)?"TX": \
|
||||
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
|
||||
|
||||
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
|
||||
{
|
||||
MsgLen mlen;
|
||||
MsgLen i;
|
||||
int16_t j;
|
||||
Buffer *tmp;
|
||||
Data *cptr;
|
||||
uint8_t data;
|
||||
uint8_t tdata[16];
|
||||
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
|
||||
|
||||
|
||||
if (trc->t.trc.evnt == TL2TMR) {
|
||||
goto end_of_trace;
|
||||
}
|
||||
|
||||
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
|
||||
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
|
||||
|
||||
if (mlen != 0) {
|
||||
tmp = mBuf->b_cont;
|
||||
cptr = tmp->b_rptr;
|
||||
data = *cptr++;
|
||||
i = 0;
|
||||
while (i < mlen) {
|
||||
j = 0;
|
||||
for(j=0;j<16;j++) {
|
||||
if (i<mlen) {
|
||||
tdata[j]= data;
|
||||
|
||||
if (cptr == tmp->b_wptr) {
|
||||
tmp = tmp->b_cont;
|
||||
if (tmp) cptr = tmp->b_rptr;
|
||||
}
|
||||
i++;
|
||||
if (i<mlen) data = *cptr++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
sngisdn_trace_q921(data_str, tdata, mlen);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] FRAME %s:%s\n", Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
|
||||
}
|
||||
end_of_trace:
|
||||
ftdm_safe_free(data_str);
|
||||
SPutMsg(mBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
|
||||
{
|
||||
char *data;
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = ftdm_vasprintf(&data, fmt, ap);
|
||||
if (ret == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (level) {
|
||||
case SNG_LOGLEVEL_DEBUG:
|
||||
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_WARN:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_INFO:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_STATS:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_ERROR:
|
||||
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
|
||||
#ifdef DEBUG_MODE
|
||||
FORCE_SEGFAULT
|
||||
#endif
|
||||
break;
|
||||
case SNG_LOGLEVEL_CRIT:
|
||||
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
|
||||
#ifdef DEBUG_MODE
|
||||
FORCE_SEGFAULT
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
|
@ -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.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;
|
||||
|
@ -131,19 +144,80 @@ void sngisdn_snd_setup(ftdm_channel_t *ftdmchan)
|
|||
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);
|
||||
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_DEBUG, "Sending con request on suId:%d suInstId:%u spInstId:%u\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
|
||||
if (sng_isdn_con_request(signal_data->cc_id, sngisdn_info->suInstId, &conEvnt, signal_data->dchan_id, sngisdn_info->ces)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP request\n");
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Used only for BRI PTMP */
|
||||
/* Unsed only for overlap receive */
|
||||
void sngisdn_snd_setup_ack(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
CnStEvnt cnStEvnt;
|
||||
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*) ftdmchan->call_data;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_ERROR, "Sending SETUP ACK , but no call data, aborting (suId:%d suInstId:%u spInstId:%u)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId);
|
||||
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT);
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&cnStEvnt, 0, sizeof(cnStEvnt));
|
||||
|
||||
cnStEvnt.chanId.eh.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.prefExc.val = IN_PE_EXCLSVE;
|
||||
cnStEvnt.chanId.dChanInd.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.dChanInd.val = IN_DSI_NOTDCHAN;
|
||||
cnStEvnt.chanId.intIdentPres.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intIdentPres.val = IN_IIP_IMPLICIT;
|
||||
|
||||
|
||||
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI ||
|
||||
ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
|
||||
|
||||
/* BRI only params */
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_BASIC;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = ftdmchan->physical_chan_id;
|
||||
} else {
|
||||
cnStEvnt.chanId.intType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.intType.val = IN_IT_OTHER;
|
||||
cnStEvnt.chanId.infoChanSel.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.infoChanSel.val = IN_ICS_B1CHAN;
|
||||
cnStEvnt.chanId.chanMapType.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanMapType.val = IN_CMT_BCHAN;
|
||||
cnStEvnt.chanId.nmbMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.nmbMap.val = IN_NM_CHNNMB;
|
||||
cnStEvnt.chanId.codeStand1.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.codeStand1.val = IN_CSTD_CCITT;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.pres = PRSNT_NODEF;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
|
||||
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
|
||||
}
|
||||
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Sending SETUP ACK (suId:%d suInstId:%u spInstId:%u dchan:%d ces:%d)\n", signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, signal_data->dchan_id, sngisdn_info->ces);
|
||||
|
||||
if(sng_isdn_con_status(signal_data->cc_id, sngisdn_info->suInstId, sngisdn_info->spInstId, &cnStEvnt, MI_SETUPACK, signal_data->dchan_id, sngisdn_info->ces)) {
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "stack refused SETUP ACK request\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* Used only for BRI PTMP - This function is used when the NT side makes a call out,
|
||||
and one or multiple TE's reply, then NT assigns the call by sending a con_complete*/
|
||||
void sngisdn_snd_con_complete(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
CnStEvnt cnStEvnt;
|
||||
|
@ -151,8 +225,14 @@ 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;
|
||||
|
@ -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,8 +283,14 @@ 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;
|
||||
|
@ -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,7 +409,12 @@ 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)
|
||||
|
||||
void sngisdn_snd_info_req(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
DiscEvnt discEvnt;
|
||||
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Sending DISCONNECT\n");
|
||||
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,20 +569,25 @@ 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(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,930 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <dyatsin@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "ftmod_sangoma_isdn.h"
|
||||
|
||||
extern void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
|
||||
extern void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
|
||||
extern void get_memory_info(void);
|
||||
|
||||
#define MAX_DECODE_STR_LEN 2000
|
||||
|
||||
|
||||
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
|
||||
{
|
||||
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
|
||||
uint8_t bchan_no = 0;
|
||||
sngisdn_chan_data_t *sngisdn_info;
|
||||
sngisdn_event_data_t *sngisdn_event;
|
||||
|
||||
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
|
||||
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
|
||||
|
||||
if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
|
||||
/* TODO: Implement me */
|
||||
ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n");
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (conEvnt->chanId.chanNmbSlotMap.pres) {
|
||||
bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0];
|
||||
} else if (conEvnt->chanId.infoChanSel.pres) {
|
||||
bchan_no = conEvnt->chanId.infoChanSel.val;
|
||||
}
|
||||
|
||||
if (!bchan_no) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n");
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_sngisdn_data.dchans[dChan].channels[bchan_no] == NULL) {
|
||||
ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
|
||||
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
|
||||
|
||||
ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SETUP (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId);
|
||||
|
||||
sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event));
|
||||
ftdm_assert(sngisdn_event, "Failed to allocate memory\n");
|
||||
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
|
||||
|
||||
sngisdn_event->event_id = SNGISDN_EVENT_CON_IND;
|
||||
sngisdn_event->sngisdn_info = sngisdn_info;
|
||||
sngisdn_event->suId = suId;
|
||||
sngisdn_event->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;j<mlen;j++) {
|
||||
tdata[j]= data;
|
||||
|
||||
if (cptr == tmp->b_wptr) {
|
||||
tmp = tmp->b_cont;
|
||||
if (tmp) cptr = tmp->b_rptr;
|
||||
}
|
||||
data = *cptr++;
|
||||
}
|
||||
|
||||
sngisdn_trace_q931(data_str, tdata, mlen);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] s%d FRAME %s:%s\n", trc->t.trc.suId, Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
|
||||
}
|
||||
|
||||
ftdm_safe_free(data_str);
|
||||
/* We do not need to free mBuf in this case because stack does it */
|
||||
/* SPutMsg(mBuf); */
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
|
||||
(event == TL2FRMTX)?"TX": \
|
||||
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
|
||||
|
||||
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
|
||||
{
|
||||
MsgLen mlen;
|
||||
MsgLen i;
|
||||
int16_t j;
|
||||
Buffer *tmp;
|
||||
Data *cptr;
|
||||
uint8_t data;
|
||||
uint8_t tdata[16];
|
||||
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
|
||||
|
||||
|
||||
if (trc->t.trc.evnt == TL2TMR) {
|
||||
goto end_of_trace;
|
||||
}
|
||||
|
||||
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
|
||||
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
|
||||
|
||||
if (mlen != 0) {
|
||||
tmp = mBuf->b_cont;
|
||||
cptr = tmp->b_rptr;
|
||||
data = *cptr++;
|
||||
i = 0;
|
||||
while (i < mlen) {
|
||||
j = 0;
|
||||
for(j=0;j<16;j++) {
|
||||
if (i<mlen) {
|
||||
tdata[j]= data;
|
||||
|
||||
if (cptr == tmp->b_wptr) {
|
||||
tmp = tmp->b_cont;
|
||||
if (tmp) cptr = tmp->b_rptr;
|
||||
}
|
||||
i++;
|
||||
if (i<mlen) data = *cptr++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
sngisdn_trace_q921(data_str, tdata, mlen);
|
||||
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] s%d FRAME %s:%s\n", trc->t.trc.lnkNmb, Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
|
||||
}
|
||||
end_of_trace:
|
||||
ftdm_safe_free(data_str);
|
||||
SPutMsg(mBuf);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_rcv_sng_assert(char *message)
|
||||
{
|
||||
ftdm_assert(0, message);
|
||||
}
|
||||
|
||||
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
|
||||
{
|
||||
char *data;
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = ftdm_vasprintf(&data, fmt, ap);
|
||||
if (ret == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (level) {
|
||||
case SNG_LOGLEVEL_DEBUG:
|
||||
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_WARN:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_INFO:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_STATS:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
case SNG_LOGLEVEL_ERROR:
|
||||
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
|
||||
/*ftdm_assert(0, "Got an error from stack");*/
|
||||
break;
|
||||
case SNG_LOGLEVEL_CRIT:
|
||||
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
|
||||
/*ftdm_assert(0, "Got an error from stack");*/
|
||||
break;
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
|
||||
/******************************************************************************/
|
|
@ -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;
|
||||
}
|
||||
if (display->dispInfo.pres != PRSNT_NODEF) {
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
||||
/* TODO check if caller name is contained in a Facility IE */
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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;
|
||||
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,27 +371,92 @@ 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);
|
||||
|
||||
/* 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");
|
||||
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);
|
||||
|
||||
/* move the state of the channel to RESTART to force a reset */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
|
||||
return FTDM_FAIL;
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed CONNECT (suId:%d suInstId:%u spInstId:%u)\n",
|
||||
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
|
||||
|
||||
sngisdn_snd_connect(ftdmchan);
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
void sngisdn_delayed_disconnect(void* p_sngisdn_info)
|
||||
{
|
||||
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info;
|
||||
ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan;
|
||||
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data;
|
||||
|
||||
ftdm_mutex_lock(ftdmchan->mutex);
|
||||
if (ftdmchan->state != FTDM_CHANNEL_STATE_DOWN) {
|
||||
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Sending delayed DISCONNECT (suId:%d suInstId:%u spInstId:%u)\n",
|
||||
signal_data->cc_id, sngisdn_info->glare.spInstId, sngisdn_info->glare.suInstId);
|
||||
|
||||
sngisdn_snd_disconnect(ftdmchan);
|
||||
}
|
||||
|
||||
ftdm_mutex_unlock(ftdmchan->mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
ftdm_status_t sngisdn_check_free_ids(void)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned j;
|
||||
ftdm_log(FTDM_LOG_INFO, "Checking suInstId's\n");
|
||||
for(j=1;j<=MAX_VARIANTS;j++) {
|
||||
if (g_sngisdn_data.ccs[j].config_done) {
|
||||
for(i=1;i<MAX_INSTID;i++) {
|
||||
if (g_sngisdn_data.ccs[j].active_suInstIds[i] != NULL) {
|
||||
ftdm_log(FTDM_LOG_INFO, "suId:%u suInstId:%u is not free\n", j, i);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ftdm_log(FTDM_LOG_INFO, "Checking spInstId's\n");
|
||||
for(j=1;j<=MAX_VARIANTS;j++) {
|
||||
if (g_sngisdn_data.ccs[j].config_done) {
|
||||
for(i=1;i<MAX_INSTID;i++) {
|
||||
if (g_sngisdn_data.ccs[j].active_spInstIds[i] != NULL) {
|
||||
ftdm_log(FTDM_LOG_INFO, "suId:%u spInstId:%u is not free\n", j, i);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ftdm_log(FTDM_LOG_INFO, "Checking ID's done\n");
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -339,6 +467,73 @@ void get_memory_info(void)
|
|||
return;
|
||||
}
|
||||
|
||||
uint8_t sngisdn_get_infoTranCap_from_stack(ftdm_bearer_cap_t bearer_capability)
|
||||
{
|
||||
switch(bearer_capability) {
|
||||
case FTDM_BEARER_CAP_SPEECH:
|
||||
return IN_ITC_SPEECH;
|
||||
|
||||
case FTDM_BEARER_CAP_64K_UNRESTRICTED:
|
||||
return IN_ITC_UNRDIG;
|
||||
|
||||
case FTDM_BEARER_CAP_3_1KHZ_AUDIO:
|
||||
return IN_ITC_A31KHZ;
|
||||
|
||||
/* Do not put a default case here, so we can see compile warnings if we have unhandled cases */
|
||||
}
|
||||
return FTDM_BEARER_CAP_SPEECH;
|
||||
}
|
||||
|
||||
uint8_t sngisdn_get_usrInfoLyr1Prot_from_stack(ftdm_user_layer1_prot_t layer1_prot)
|
||||
{
|
||||
switch(layer1_prot) {
|
||||
case FTDM_USER_LAYER1_PROT_V110:
|
||||
return IN_UIL1_CCITTV110;
|
||||
|
||||
case FTDM_USER_LAYER1_PROT_ULAW:
|
||||
return IN_UIL1_G711ULAW;
|
||||
|
||||
case FTDM_USER_LAYER1_PROT_ALAW:
|
||||
return IN_UIL1_G711ALAW;
|
||||
|
||||
/* Do not put a default case here, so we can see compile warnings if we have unhandled cases */
|
||||
}
|
||||
return IN_UIL1_G711ULAW;
|
||||
}
|
||||
|
||||
ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_user(uint8_t bearer_capability)
|
||||
{
|
||||
switch(bearer_capability) {
|
||||
case IN_ITC_SPEECH:
|
||||
return FTDM_BEARER_CAP_SPEECH;
|
||||
|
||||
case IN_ITC_UNRDIG:
|
||||
return FTDM_BEARER_CAP_64K_UNRESTRICTED;
|
||||
|
||||
case IN_ITC_A31KHZ:
|
||||
return FTDM_BEARER_CAP_3_1KHZ_AUDIO;
|
||||
|
||||
default:
|
||||
return FTDM_BEARER_CAP_SPEECH;
|
||||
}
|
||||
return FTDM_BEARER_CAP_SPEECH;
|
||||
}
|
||||
|
||||
ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_user(uint8_t layer1_prot)
|
||||
{
|
||||
switch(layer1_prot) {
|
||||
case IN_UIL1_CCITTV110:
|
||||
return FTDM_USER_LAYER1_PROT_V110;
|
||||
case IN_UIL1_G711ULAW:
|
||||
return FTDM_USER_LAYER1_PROT_ULAW;
|
||||
case IN_UIL1_G711ALAW:
|
||||
return IN_UIL1_G711ALAW;
|
||||
default:
|
||||
return FTDM_USER_LAYER1_PROT_ULAW;
|
||||
}
|
||||
return FTDM_USER_LAYER1_PROT_ULAW;
|
||||
}
|
||||
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
|
|
|
@ -205,7 +205,7 @@ void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len)
|
|||
i=i+1;
|
||||
c=c+1;
|
||||
}
|
||||
str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Origination");
|
||||
str_len += sprintf(&str[str_len], " (%s side)\n", callRefFlag?"Destination":"Originating");
|
||||
|
||||
/* Decode message type */
|
||||
str_len+= sprintf(&str[str_len], " Type:%s (0x%x)\n", get_code_2_str((int)(data[2+lenCallRef] & 0xFF), dcodQ931MsgTypeTable), (int)(data[2+lenCallRef] & 0xFF));
|
||||
|
@ -337,7 +337,7 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
|
|||
}
|
||||
|
||||
if (numberMap) {
|
||||
*str_len+= sprintf(&str[*str_len], " MAP\n");
|
||||
*str_len+= sprintf(&str[*str_len], " MAP:%s ", get_code_2_str(infoChannelSelection, dcodQ931InfoChannelSelTable));
|
||||
} else {
|
||||
*str_len+= sprintf(&str[*str_len], "No:%d ", channelNo);
|
||||
}
|
||||
|
@ -608,6 +608,9 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
|
|||
break;
|
||||
case PROT_Q931_IE_SENDING_COMPLETE:
|
||||
/* No need to decode sending complete IE, as no additional info is available except that sending is done */
|
||||
/* This is a single octet IE */
|
||||
*str_len+= sprintf(&str[*str_len], "\n");
|
||||
return 0;
|
||||
break;
|
||||
case PROT_Q931_IE_CALLED_PARTY_SUBADDRESS:
|
||||
case PROT_Q931_IE_REDIRECTION_NUMBER:
|
||||
|
|
|
@ -373,6 +373,14 @@ struct code2str dcodQ931ScreeningTable[] = {
|
|||
{-1, "invalid" },
|
||||
};
|
||||
|
||||
struct code2str dcodQ931InfoChannelSelTable[] = {
|
||||
{0, "No Chan"},
|
||||
{1, "B1"},
|
||||
{2, "B2"},
|
||||
{3, "Any Chan"},
|
||||
{-1, "invalid" },
|
||||
};
|
||||
|
||||
struct code2str dcodQ931ReasonTable[] = {
|
||||
{0x0, "Unknown"},
|
||||
{0x1, "Call forwarding busy"},
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
|
||||
|
@ -73,6 +78,7 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
int argc = 0;
|
||||
int span = 0;
|
||||
int chan = 0;
|
||||
int range = 0;
|
||||
int trace = 0;
|
||||
int trace_level = 7;
|
||||
int verbose = 1;
|
||||
|
@ -87,7 +93,7 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
|
||||
if (!strcasecmp(argv[c], "show")) {
|
||||
/**************************************************************************/
|
||||
if (check_arg_count(argc, 4)) goto handle_cli_error_argc;
|
||||
if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
|
||||
c++;
|
||||
|
||||
if (!strcasecmp(argv[c], "status")) {
|
||||
|
@ -219,6 +225,26 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
/******************************************************************/
|
||||
}
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(argv[c], "mem")) {
|
||||
/**********************************************************************/
|
||||
/*uint32_t availMem;*/
|
||||
|
||||
/*sng_sta_mem(&availMem);*/
|
||||
/**********************************************************************/
|
||||
} else if (!strcasecmp(argv[c], "stats")) {
|
||||
/**********************************************************************/
|
||||
/* sng_mtp1_sts_t sts;
|
||||
|
||||
memset(&sts, 0x0, sizeof(sng_mtp1_sts_t));
|
||||
|
||||
sng_mtp1_sts(1, &sts);
|
||||
|
||||
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");
|
||||
|
@ -258,17 +284,24 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
/**************************************************************************/
|
||||
} else if (!strcasecmp(argv[c], "block")) {
|
||||
/**************************************************************************/
|
||||
if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
|
||||
if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
|
||||
c++;
|
||||
|
||||
if (!strcasecmp(argv[c], "span")) {
|
||||
/**********************************************************************/
|
||||
if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
|
||||
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_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");
|
||||
|
@ -278,17 +311,24 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
/**************************************************************************/
|
||||
} else if (!strcasecmp(argv[c], "unblock")) {
|
||||
/**************************************************************************/
|
||||
if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
|
||||
if (check_arg_count(argc, 2)) goto handle_cli_error_argc;
|
||||
c++;
|
||||
|
||||
if (!strcasecmp(argv[c], "span")) {
|
||||
/**********************************************************************/
|
||||
if (check_arg_count(argc, 6)) goto handle_cli_error_argc;
|
||||
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");
|
||||
|
@ -296,6 +336,61 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
/**********************************************************************/
|
||||
}
|
||||
/**************************************************************************/
|
||||
} 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;
|
||||
|
@ -338,8 +433,10 @@ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream)
|
|||
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, "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;
|
||||
|
@ -391,9 +488,9 @@ static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, in
|
|||
|
||||
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;
|
||||
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 */
|
||||
|
@ -435,7 +532,7 @@ static ftdm_status_t handle_show_free(ftdm_stream_handle_t *stream, int span, in
|
|||
|
||||
/* go the next circuit */
|
||||
x++;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
|
||||
|
||||
stream->write_function(stream, "\nTotal # of CICs free = %d\n",free);
|
||||
|
||||
|
@ -454,9 +551,9 @@ static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, i
|
|||
|
||||
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;
|
||||
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 */
|
||||
|
@ -505,7 +602,7 @@ static ftdm_status_t handle_show_inuse(ftdm_stream_handle_t *stream, int span, i
|
|||
|
||||
/* go the next circuit */
|
||||
x++;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
|
||||
|
||||
stream->write_function(stream, "\nTotal # of CICs in use = %d\n",in_use);
|
||||
|
||||
|
@ -524,9 +621,9 @@ static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span,
|
|||
|
||||
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;
|
||||
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 */
|
||||
|
@ -544,7 +641,11 @@ static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span,
|
|||
}
|
||||
|
||||
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 ((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,
|
||||
|
@ -560,7 +661,7 @@ static ftdm_status_t handle_show_inreset(ftdm_stream_handle_t *stream, int span,
|
|||
|
||||
/* go the next circuit */
|
||||
x++;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
|
||||
|
||||
stream->write_function(stream, "\nTotal # of CICs in reset = %d\n",in_reset);
|
||||
|
||||
|
@ -578,9 +679,9 @@ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, i
|
|||
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;
|
||||
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 */
|
||||
|
@ -619,7 +720,7 @@ static ftdm_status_t handle_show_flags(ftdm_stream_handle_t *stream, int span, i
|
|||
|
||||
/* go the next circuit */
|
||||
x++;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
@ -634,9 +735,9 @@ static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span,
|
|||
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;
|
||||
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 */
|
||||
|
@ -678,17 +779,31 @@ static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span,
|
|||
}
|
||||
|
||||
if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
|
||||
stream->write_function(stream, "r_hw=Y\n");
|
||||
stream->write_function(stream, "r_hw=Y|");
|
||||
}else {
|
||||
stream->write_function(stream, "r_hw=N\n");
|
||||
stream->write_function(stream, "r_hw=N|");
|
||||
}
|
||||
|
||||
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|");
|
||||
}
|
||||
|
||||
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|");
|
||||
}
|
||||
|
||||
stream->write_function(stream, "\n");
|
||||
} /* if ( span and chan) */
|
||||
|
||||
} /* if ( cic != 0) */
|
||||
|
||||
/* go the next circuit */
|
||||
x++;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
@ -704,9 +819,9 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span,
|
|||
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;
|
||||
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 */
|
||||
|
@ -753,19 +868,33 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span,
|
|||
}
|
||||
|
||||
if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) {
|
||||
stream->write_function(stream, "r_hw=Y\n");
|
||||
stream->write_function(stream, "r_hw=Y|");
|
||||
}else {
|
||||
stream->write_function(stream, "r_hw=N\n");
|
||||
stream->write_function(stream, "r_hw=N|");
|
||||
}
|
||||
|
||||
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|");
|
||||
}
|
||||
|
||||
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|");
|
||||
}
|
||||
|
||||
stream->write_function(stream, "flags=0x%X",ss7_info->flags);
|
||||
|
||||
stream->write_function(stream, "\n");
|
||||
} /* if ( span and chan) */
|
||||
|
||||
} /* if ( cic != 0) */
|
||||
|
||||
/* go the next circuit */
|
||||
x++;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
@ -779,9 +908,9 @@ static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, i
|
|||
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;
|
||||
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 */
|
||||
|
@ -805,6 +934,7 @@ static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, i
|
|||
/* 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);
|
||||
|
@ -822,7 +952,7 @@ static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, i
|
|||
|
||||
/* go the next circuit */
|
||||
x++;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
|
||||
|
||||
handle_show_blocks(stream, span, chan, verbose);
|
||||
|
||||
|
@ -839,9 +969,9 @@ static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, i
|
|||
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;
|
||||
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 */
|
||||
|
@ -865,6 +995,7 @@ static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, i
|
|||
/* 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);
|
||||
|
@ -885,7 +1016,7 @@ static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, i
|
|||
|
||||
/* go the next circuit */
|
||||
x++;
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCircuit[x]id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */
|
||||
|
||||
handle_show_blocks(stream, span, chan, verbose);
|
||||
|
||||
|
@ -895,27 +1026,31 @@ static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, i
|
|||
/******************************************************************************/
|
||||
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.mtp3Link[x].id != 0) {
|
||||
if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtp3Link[x].name, name)) {
|
||||
while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) {
|
||||
if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) {
|
||||
|
||||
/* send the status request */
|
||||
if (sng_sta_mtp3_link(&g_ftdm_sngss7_data.cfg, x, &sta)) {
|
||||
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",
|
||||
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,
|
||||
DECODE_LSN_LINK_STATUS(sta.state),
|
||||
(sta.lblkd) ? "Y":"N",
|
||||
(sta.rblkd) ? "Y":"N",
|
||||
(sta.linhbt) ? "Y":"N",
|
||||
(sta.rinhbt) ? "Y":"N");
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -929,15 +1064,16 @@ 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)
|
||||
{
|
||||
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)) {
|
||||
while(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) {
|
||||
if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, name)) {
|
||||
|
||||
/* send the status request */
|
||||
if (sng_sta_mtp3_linkset(&g_ftdm_sngss7_data.cfg, x, 0, &sta)) {
|
||||
if (ftmod_ss7_mtplinkSet_sta(x, &sta)) {
|
||||
stream->write_function(stream, "Failed to read linkset=%s status\n", name);
|
||||
return FTDM_FAIL;
|
||||
}
|
||||
|
@ -945,8 +1081,8 @@ static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *n
|
|||
/* print the results */
|
||||
stream->write_function(stream, "%s|state=%s|nmbActLnk=%d\n",
|
||||
name,
|
||||
DECODE_LSN_LINKSET_STATUS(sta.state),
|
||||
sta.nmbActLnks);
|
||||
DECODE_LSN_LINKSET_STATUS(sta.t.ssta.s.snLnkSet.state),
|
||||
sta.t.ssta.s.snLnkSet.nmbActLnks);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -957,6 +1093,183 @@ static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *n
|
|||
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)
|
||||
{
|
||||
|
|
|
@ -42,680 +42,234 @@
|
|||
/******************************************************************************/
|
||||
|
||||
/* 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;
|
||||
|
||||
/* 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);
|
||||
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)) {
|
||||
|
||||
if (ftmod_ss7_enable_isap(x)) {
|
||||
SS7_CRITICAL("ISAP %d Enable: NOT OK\n", x);
|
||||
SS7_ASSERT;
|
||||
} 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);
|
||||
SS7_INFO("ISAP %d Enable: OK\n", x);
|
||||
}
|
||||
} /* if (sngss7_test_flag(cc_isup, SNGSS7_FLAG_ACTIVE) */
|
||||
|
||||
/* set the ACTIVE flag */
|
||||
g_ftdm_sngss7_data.cfg.isap[x].flags |= ACTIVE;
|
||||
} /* if !ACTIVE */
|
||||
|
||||
x++;
|
||||
cc_isup = &g_ftdm_sngss7_data.cfg.isup_cc[x];
|
||||
} /* while (cc_isup->id != 0) */
|
||||
|
||||
/* 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) */
|
||||
|
||||
x++;
|
||||
isup_mtp3 = &g_ftdm_sngss7_data.cfg.mtp3_isup[x];
|
||||
} /* while (isup_mtp3->id != 0) */
|
||||
|
||||
/* 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) */
|
||||
|
||||
x++;
|
||||
mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
|
||||
} /* while (mtp3_linkset->id != 0) */
|
||||
|
||||
return FTDM_SUCCESS;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
SS7_DEBUG("Starting LibSngSS7 configuration...\n");
|
||||
|
||||
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) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.isap[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);
|
||||
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)) {
|
||||
|
||||
if (ftmod_ss7_enable_nsap(x)) {
|
||||
SS7_CRITICAL("NSAP %d Enable: NOT OK\n", x);
|
||||
SS7_ASSERT;
|
||||
} 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);
|
||||
SS7_INFO("NSAP %d Enable: OK\n", x);
|
||||
}
|
||||
}
|
||||
/* next link */
|
||||
|
||||
/* set the ACTIVE flag */
|
||||
g_ftdm_sngss7_data.cfg.nsap[x].flags |= ACTIVE;
|
||||
} /* if !ACTIVE */
|
||||
|
||||
x++;
|
||||
mtp3_linkset = &g_ftdm_sngss7_data.cfg.mtp3LinkSet[x];
|
||||
} /* while (g_ftdm_sngss7_data.cfg.mtp1Link[x]->id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.nsap[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);
|
||||
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)) {
|
||||
|
||||
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 {
|
||||
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);
|
||||
SS7_INFO("LinkSet \"%s\" Enable: OK\n", g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name);
|
||||
}
|
||||
}
|
||||
/* next link */
|
||||
|
||||
/* set the ACTIVE flag */
|
||||
g_ftdm_sngss7_data.cfg.mtpLinkSet[x].flags |= ACTIVE;
|
||||
} /* if !ACTIVE */
|
||||
|
||||
x++;
|
||||
mtp3_route = &g_ftdm_sngss7_data.cfg.mtp3Route[x];
|
||||
} /* while (g_ftdm_sngss7_data.cfg.mtp3Route[x]->id != 0) */
|
||||
} /* while (g_ftdm_sngss7_data.cfg.mtpLinkSet[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:
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,592 @@
|
|||
/*
|
||||
* Copyright (c) 2009|Konrad Hammel <konrad@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms|with or without
|
||||
* modification|are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice|this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice|this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
|
||||
* LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
|
||||
* EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* INCLUDE ********************************************************************/
|
||||
#include "ftmod_sangoma_ss7_main.h"
|
||||
/******************************************************************************/
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* PROTOTYPES *****************************************************************/
|
||||
void handle_sng_log(uint8_t level, char *fmt,...);
|
||||
void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta);
|
||||
void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
|
||||
void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
|
||||
void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
|
||||
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
|
||||
/******************************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
void handle_sng_log(uint8_t level, char *fmt,...)
|
||||
{
|
||||
char *data;
|
||||
int ret;
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
ret = vasprintf(&data, fmt, ap);
|
||||
if (ret == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (level) {
|
||||
/**************************************************************************/
|
||||
case SNG_LOGLEVEL_DEBUG:
|
||||
ftdm_log(FTDM_LOG_DEBUG, "sng_ss7->%s", data);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
case SNG_LOGLEVEL_WARN:
|
||||
ftdm_log(FTDM_LOG_WARNING, "sng_ss7->%s", data);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
case SNG_LOGLEVEL_INFO:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
case SNG_LOGLEVEL_STATS:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
case SNG_LOGLEVEL_ERROR:
|
||||
ftdm_log(FTDM_LOG_ERROR, "sng_ss7->%s", data);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
case SNG_LOGLEVEL_CRIT:
|
||||
/*printf("%s",data);*/
|
||||
ftdm_log(FTDM_LOG_CRIT, "sng_ss7->%s", data);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta)
|
||||
{
|
||||
|
||||
|
||||
} /* handle_mtp1_alarm */
|
||||
|
||||
/******************************************************************************/
|
||||
void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
|
||||
{
|
||||
|
||||
switch (sta->t.usta.alarm.category) {
|
||||
/**************************************************************************/
|
||||
case (LCM_CATEGORY_PROTOCOL):
|
||||
case (LCM_CATEGORY_INTERFACE):
|
||||
|
||||
switch (sta->t.usta.alarm.event) {
|
||||
/**********************************************************************/
|
||||
case (LSD_EVENT_ENTR_CONG):
|
||||
case (LSD_EVENT_EXIT_CONG):
|
||||
case (LSD_EVENT_PROT_ST_UP):
|
||||
case (LSD_EVENT_PROT_ST_DN):
|
||||
case (LSD_EVENT_LINK_ALIGNED):
|
||||
case (LSD_EVENT_REMOTE_CONG_START):
|
||||
case (LSD_EVENT_REMOTE_CONG_END):
|
||||
case (LSD_EVENT_RX_REMOTE_SIPO):
|
||||
|
||||
switch (sta->t.usta.alarm.cause) {
|
||||
/******************************************************************/
|
||||
case (LCM_CAUSE_UNKNOWN):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
|
||||
break;
|
||||
/******************************************************************/
|
||||
case (LCM_CAUSE_MGMT_INITIATED):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d][MGMT] %s\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
|
||||
break;
|
||||
/******************************************************************/
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s (***unknown cause***)\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
|
||||
break;
|
||||
/******************************************************************/
|
||||
} /* switch (sta->t.usta.alarm.cause) */
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSD_EVENT_PROT_ERR):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause));
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSD_EVENT_ALIGN_LOST):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSD_EVENT_RTB_FULL):
|
||||
case (LSD_EVENT_RTB_FULL_OVER):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
sta->t.usta.evntParm[1],
|
||||
sta->t.usta.evntParm[2],
|
||||
sta->t.usta.evntParm[3],
|
||||
sta->t.usta.evntParm[4]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSD_EVENT_NEG_ACK):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
sta->t.usta.evntParm[1]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSD_EVENT_DAT_CFM_SDT):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %d\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LCM_EVENT_UI_INV_EVT):
|
||||
case (LCM_EVENT_LI_INV_EVT):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)\n",
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.evntParm[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LCM_EVENT_INV_EVT):
|
||||
|
||||
switch (sta->t.usta.alarm.cause) {
|
||||
/******************************************************************/
|
||||
case (LCM_CAUSE_UNKNOWN):
|
||||
case (LCM_CAUSE_SWVER_NAVAIL):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Event (%d)\n",
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.evntParm[0]);
|
||||
break;
|
||||
/******************************************************************/
|
||||
case (LCM_CAUSE_DECODE_ERR):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)|Version (%d)\n",
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.evntParm[0],
|
||||
sta->t.usta.evntParm[1]);
|
||||
break;
|
||||
/******************************************************************/
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
sta->t.usta.alarm.event,
|
||||
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.alarm.cause);
|
||||
break;
|
||||
/******************************************************************/
|
||||
} /* switch (sta->t.usta.alarm.cause) */
|
||||
break;
|
||||
/**********************************************************************/
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
|
||||
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
|
||||
sta->t.usta.alarm.event,
|
||||
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.alarm.cause);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
} /* switch (sta->t.usta.alarm.event) */
|
||||
break;
|
||||
/**************************************************************************/
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP2] Unknown alarm category %d\n",
|
||||
sta->t.usta.alarm.category);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
} /* switch(sta->t.usta.alarm.category) */
|
||||
|
||||
return;
|
||||
} /* handle_mtp2_alarm */
|
||||
|
||||
/******************************************************************************/
|
||||
void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
|
||||
{
|
||||
|
||||
switch (sta->hdr.elmId.elmnt) {
|
||||
/**************************************************************************/
|
||||
case (STDLSAP):
|
||||
switch (sta->t.usta.alarm.event) {
|
||||
/**********************************************************************/
|
||||
case (LSN_EVENT_INV_OPC_OTHER_END):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : OPC(0x%X%X%X%X)\n",
|
||||
sta->hdr.elmId.elmntInst1,
|
||||
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.evntParm[3],
|
||||
sta->t.usta.evntParm[2],
|
||||
sta->t.usta.evntParm[1],
|
||||
sta->t.usta.evntParm[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSN_EVENT_INV_SLC_OTHER_END):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : SLC(%d)\n",
|
||||
sta->hdr.elmId.elmntInst1,
|
||||
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.evntParm[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s(%d) : %s(%d)\n",
|
||||
sta->hdr.elmId.elmntInst1,
|
||||
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
|
||||
sta->t.usta.alarm.event,
|
||||
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.alarm.cause);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
} /* sta->t.usta.alarm.event */
|
||||
break;
|
||||
/**************************************************************************/
|
||||
case (STNSAP):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s\n",
|
||||
sta->hdr.elmId.elmntInst1,
|
||||
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
|
||||
break;
|
||||
/**************************************************************************/
|
||||
case (STLNKSET):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP3][LNKSET:%d] %s : %s\n",
|
||||
sta->hdr.elmId.elmntInst1,
|
||||
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
|
||||
break;
|
||||
/**************************************************************************/
|
||||
case (STROUT):
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%d%d%d%d] %s : %s\n",
|
||||
sta->t.usta.evntParm[0],
|
||||
sta->t.usta.evntParm[1],
|
||||
sta->t.usta.evntParm[2],
|
||||
sta->t.usta.evntParm[3],
|
||||
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
|
||||
break;
|
||||
/**************************************************************************/
|
||||
default:
|
||||
ftdm_log(FTDM_LOG_ERROR,"[MTP3] %s(%d) : %s(%d)\n",
|
||||
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
|
||||
sta->t.usta.alarm.event,
|
||||
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
|
||||
sta->t.usta.alarm.cause);
|
||||
break;
|
||||
/**************************************************************************/
|
||||
} /* switch (sta->hdr.elmId.elmnt) */
|
||||
|
||||
return;
|
||||
} /* handle_mtp3_alarm */
|
||||
|
||||
/******************************************************************************/
|
||||
void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
|
||||
{
|
||||
char msg[250];
|
||||
char tmp[25];
|
||||
char *p = NULL;
|
||||
int x = 0;
|
||||
|
||||
/* initalize the msg variable to NULLs */
|
||||
memset(&msg[0], '\0', sizeof(&msg));
|
||||
|
||||
|
||||
/* point p to the first spot in msg */
|
||||
p = &msg[0];
|
||||
|
||||
p = strcat(p, "[ISUP]");
|
||||
|
||||
/* go through the dgnVals */
|
||||
for (x = 0; x < 5; x++) {
|
||||
switch (sta->t.usta.dgn.dgnVal[x].type) {
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_NONE):
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_EVENT):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[EVENT:%d]",sta->t.usta.dgn.dgnVal[x].t.event);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_SPID):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[SPID:%d]",sta->t.usta.dgn.dgnVal[x].t.spId);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_SUID):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[SUID:%d]",sta->t.usta.dgn.dgnVal[x].t.suId);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_SPINSTID):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[SPINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.spInstId);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_SUINSTID):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[SUINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.suInstId);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_CIRCUIT):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[CKT:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cirId);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_CIC):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[CIC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cic);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_INTF):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[INTF:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.intfId);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_DPC):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[DPC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.dpc);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_ADDRS):
|
||||
#if 0
|
||||
/*
|
||||
*typedef struct addrs
|
||||
*{
|
||||
*U8 length;
|
||||
*U8 strg[ADRLEN];
|
||||
*} Addrs;
|
||||
*/
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[ADDRS:%d]",sta->t.usta.dgn.dgnVal[x].t.);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
#endif
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_SWTCH):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[SWTCH:%d]",sta->t.usta.dgn.dgnVal[x].t.swtch);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_RANGE):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[RANGE:0x%X]",sta->t.usta.dgn.dgnVal[x].t.range);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_STATUS_OCTS):
|
||||
#if 0
|
||||
/*
|
||||
*typedef struct addrs
|
||||
*{
|
||||
*U8 length;
|
||||
*U8 strg[ADRLEN];
|
||||
*} Addrs;
|
||||
*/
|
||||
/* init tmp with NULLs */
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[STATUS_OCT:0x%X]",sta->t.usta.dgn.dgnVal[x].t.);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
#endif
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_VER):
|
||||
#ifdef SI_RUG
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[VER:%d]",sta->t.usta.dgn.dgnVal[x].t.intfVer);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
#endif
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_TIMER):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[TIMER:0x%X]",sta->t.usta.dgn.dgnVal[x].t.tmrInfo);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_MSGTYPE):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[MSGTYPE:%d]",sta->t.usta.dgn.dgnVal[x].t.msgType);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
case (LSI_USTA_DGNVAL_STATE):
|
||||
/* init tmp with NULLs */
|
||||
memset(&tmp[0], '\0', sizeof(&tmp));
|
||||
|
||||
/* fill in the dgn val to tmp */
|
||||
sprintf(&tmp[0], "[STATE:%d]",sta->t.usta.dgn.dgnVal[x].t.state);
|
||||
|
||||
/* concat tmp to msg */
|
||||
p = strcat(p, &tmp[0]);
|
||||
break;
|
||||
/**********************************************************************/
|
||||
default:
|
||||
break;
|
||||
/**********************************************************************/
|
||||
} /* switch (sta->t.usta.dgn.dgnVal[x].t.type) */
|
||||
} /* for (x = 0; x < 5; x++) */
|
||||
|
||||
ftdm_log(FTDM_LOG_ERROR,"%s %s : %s\n",
|
||||
msg,
|
||||
DECODE_LSI_EVENT(sta->t.usta.alarm.event),
|
||||
DECODE_LSI_CAUSE(sta->t.usta.alarm.cause));
|
||||
|
||||
} /* handle_isup_alarm */
|
||||
|
||||
/******************************************************************************/
|
||||
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
|
||||
{
|
||||
|
||||
return;
|
||||
} /* handle_cc_alarm */
|
||||
/******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
/******************************************************************************/
|
File diff suppressed because it is too large
Load Diff
|
@ -44,36 +44,265 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "private/ftdm_core.h"
|
||||
/*
|
||||
#include "sng_sit.h"
|
||||
#include "sng_ss7_error.h"
|
||||
*/
|
||||
|
||||
#include "sng_ss7.h"
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
#define MAX_CIC_LENGTH 5
|
||||
#define MAX_CIC_MAP_LENGTH 256
|
||||
#define MAX_MTP_LINKS MAX_SN_LINKSETS
|
||||
#define MAX_NAME_LEN 10
|
||||
#define MAX_PATH 255
|
||||
|
||||
#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;
|
||||
sng_ss7_cfg_t cfg;
|
||||
int gen_config;
|
||||
int min_digits;
|
||||
int function_trace;
|
||||
int function_trace_level;
|
||||
|
@ -92,7 +321,6 @@ typedef struct sngss7_timer_data {
|
|||
}sngss7_timer_data_t;
|
||||
|
||||
typedef struct sngss7_glare_data {
|
||||
uint32_t suInstId;
|
||||
uint32_t spInstId;
|
||||
uint32_t circuit;
|
||||
SiConEvnt iam;
|
||||
|
@ -105,7 +333,8 @@ typedef struct sngss7_group_data {
|
|||
|
||||
typedef struct sngss7_chan_data {
|
||||
ftdm_channel_t *ftdmchan;
|
||||
sng_isupCircuit_t *circuit;
|
||||
sng_isup_ckt_t *circuit;
|
||||
uint32_t base_chan;
|
||||
uint32_t suInstId;
|
||||
uint32_t spInstId;
|
||||
uint32_t spId;
|
||||
|
@ -113,33 +342,72 @@ typedef struct sngss7_chan_data {
|
|||
uint32_t flags;
|
||||
sngss7_glare_data_t glare;
|
||||
sngss7_timer_data_t t35;
|
||||
sngss7_group_data_t grs;
|
||||
}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_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;
|
||||
/******************************************************************************/
|
||||
|
||||
|
@ -151,9 +419,36 @@ 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);
|
||||
|
||||
|
@ -205,6 +533,12 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
#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__ );
|
||||
#else
|
||||
|
@ -275,34 +609,43 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
} /* 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) { \
|
||||
#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(FTDM_LOG_EMERG,a,##__VA_ARGS__ ); \
|
||||
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(FTDM_LOG_ALERT,a,##__VA_ARGS__ ); \
|
||||
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(FTDM_LOG_CRIT,a,##__VA_ARGS__ ); \
|
||||
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(FTDM_LOG_ERROR,a,##__VA_ARGS__ ); \
|
||||
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(FTDM_LOG_WARNING,a,##__VA_ARGS__ ); \
|
||||
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(FTDM_LOG_NOTICE,a,##__VA_ARGS__ ); \
|
||||
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(FTDM_LOG_INFO,a,##__VA_ARGS__ ); \
|
||||
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(FTDM_LOG_DEBUG,a,##__VA_ARGS__ ); \
|
||||
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(FTDM_LOG_INFO,a,##__VA_ARGS__ ); \
|
||||
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) */
|
||||
|
@ -311,8 +654,22 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha
|
|||
#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:
|
||||
*/
|
||||
/******************************************************************************/
|
||||
|
|
|
@ -59,6 +59,9 @@ 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);
|
||||
/******************************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
|
||||
{
|
||||
|
@ -76,40 +79,40 @@ void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan)
|
|||
/* 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.satInd.val = 0; /* no satellite circuit */
|
||||
iam.natConInd.contChkInd.pres = PRSNT_NODEF;
|
||||
iam.natConInd.contChkInd.val = 0x00;
|
||||
iam.natConInd.contChkInd.val = CONTCHK_NOTREQ;
|
||||
iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF;
|
||||
iam.natConInd.echoCntrlDevInd.val = 0x01;
|
||||
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 = 0x00;
|
||||
iam.fwdCallInd.end2EndMethInd.val = E2EMTH_NOMETH;
|
||||
iam.fwdCallInd.intInd.pres = PRSNT_NODEF;
|
||||
iam.fwdCallInd.intInd.val = 0x01;
|
||||
iam.fwdCallInd.intInd.val = INTIND_NOINTW;
|
||||
iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF;
|
||||
iam.fwdCallInd.end2EndInfoInd.val = 0x00;
|
||||
iam.fwdCallInd.end2EndInfoInd.val = E2EINF_NOINFO;
|
||||
iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF;
|
||||
iam.fwdCallInd.isdnUsrPrtInd.val = 0x01;
|
||||
iam.fwdCallInd.isdnUsrPrtInd.val = ISUP_USED;
|
||||
iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF;
|
||||
iam.fwdCallInd.isdnUsrPrtPrfInd.val = 0x02;
|
||||
iam.fwdCallInd.isdnUsrPrtPrfInd.val = PREF_REQAW;
|
||||
iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF;
|
||||
iam.fwdCallInd.isdnAccInd.val = 0x01;
|
||||
iam.fwdCallInd.isdnAccInd.val = ISDNACC_ISDN;
|
||||
iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF;
|
||||
iam.fwdCallInd.sccpMethInd.val = 0x00;
|
||||
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 = 0x0a;
|
||||
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 = 0; /* SPEECH = 0, 3.1Khz = 3, 64k unres = 2 */
|
||||
iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability;
|
||||
|
||||
/* copy down the called number information */
|
||||
copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum);
|
||||
|
@ -124,13 +127,13 @@ void ft_to_sngss7_iam(ftdm_channel_t *ftdmchan)
|
|||
&iam,
|
||||
0);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted IAM on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx IAM\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
/******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
|
||||
{
|
||||
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
|
||||
|
@ -173,13 +176,13 @@ void ft_to_sngss7_acm(ftdm_channel_t *ftdmchan)
|
|||
&acm,
|
||||
ADDRCMPLT);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted ACM on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ACM\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
/******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
|
||||
{
|
||||
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
|
||||
|
@ -197,7 +200,7 @@ void ft_to_sngss7_anm(ftdm_channel_t *ftdmchan)
|
|||
&anm,
|
||||
5);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted ANM on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx ANM\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -230,7 +233,7 @@ void ft_to_sngss7_rel(ftdm_channel_t *ftdmchan)
|
|||
sngss7_info->circuit->id,
|
||||
&rel);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted REL on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx REL\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -253,7 +256,7 @@ void ft_to_sngss7_rlc(ftdm_channel_t *ftdmchan)
|
|||
sngss7_info->circuit->id,
|
||||
&rlc);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted RLC on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RLC\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -274,7 +277,7 @@ void ft_to_sngss7_rsc(ftdm_channel_t *ftdmchan)
|
|||
SIT_STA_CIRRESREQ,
|
||||
NULL);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted RSC on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -295,7 +298,7 @@ void ft_to_sngss7_rsca(ftdm_channel_t *ftdmchan)
|
|||
SIT_STA_CIRRESRSP,
|
||||
NULL);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted RSC-RLC on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx RSC-RLC\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -316,7 +319,7 @@ void ft_to_sngss7_blo(ftdm_channel_t *ftdmchan)
|
|||
SIT_STA_CIRBLOREQ,
|
||||
NULL);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted BLO on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLO\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -337,14 +340,15 @@ void ft_to_sngss7_bla(ftdm_channel_t *ftdmchan)
|
|||
SIT_STA_CIRBLORSP,
|
||||
NULL);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted BLA on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx BLA\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan)
|
||||
void
|
||||
ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan)
|
||||
{
|
||||
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
|
||||
|
||||
|
@ -358,7 +362,7 @@ void ft_to_sngss7_ubl(ftdm_channel_t *ftdmchan)
|
|||
SIT_STA_CIRUBLREQ,
|
||||
NULL);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted UBL on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBL\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -379,7 +383,7 @@ void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan)
|
|||
SIT_STA_CIRUBLRSP,
|
||||
NULL);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted UBA on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx UBA\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -400,7 +404,7 @@ void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan)
|
|||
SIT_STA_LOOPBACKACK,
|
||||
NULL);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted LPA on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx LPA\n");
|
||||
|
||||
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
|
||||
return;
|
||||
|
@ -411,24 +415,76 @@ 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;
|
||||
|
||||
/* get the original channel the message came in on */
|
||||
sngss7_info = g_ftdm_sngss7_data.cfg.isupCircuit[sngss7_info->grs.circuit].obj;
|
||||
/* 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_info->circuit->id,
|
||||
sngss7_info->globalFlg,
|
||||
sngss7_span->rx_grs.circuit,
|
||||
0,
|
||||
SIT_STA_GRSRSP,
|
||||
NULL);
|
||||
&gra);
|
||||
|
||||
SS7_MSG_TRACE("Transmitted GRA on CIC # %d\n", sngss7_info->circuit->cic);
|
||||
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:
|
||||
*/
|
||||
/******************************************************************************/
|
||||
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Konrad Hammel <konrad@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms|with or without
|
||||
* modification|are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice|this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice|this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
|
||||
* LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
|
||||
* EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* INCLUDE ********************************************************************/
|
||||
#include "ftmod_sangoma_ss7_main.h"
|
||||
/******************************************************************************/
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* PROTOTYPES *****************************************************************/
|
||||
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm);
|
||||
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
|
||||
/******************************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm)
|
||||
{
|
||||
SnMngmt sta;
|
||||
|
||||
memset(&sta, 0x0, sizeof(sta));
|
||||
|
||||
sta.hdr.elmId.elmnt = STDLSAP;
|
||||
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id;
|
||||
|
||||
return(sng_sta_mtp3(&sta, cfm));
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm)
|
||||
{
|
||||
SnMngmt sta;
|
||||
|
||||
memset(&sta, 0x0, sizeof(sta));
|
||||
|
||||
sta.hdr.elmId.elmnt = STLNKSET;
|
||||
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id;
|
||||
sta.hdr.elmId.elmntInst2 = 1;
|
||||
|
||||
return(sng_sta_mtp3(&sta, cfm));
|
||||
}
|
||||
/******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
/******************************************************************************/
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright (c) 2009 Konrad Hammel <konrad@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms|with or without
|
||||
* modification|are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice|this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice|this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
|
||||
* LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
|
||||
* EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* INCLUDE ********************************************************************/
|
||||
#include "ftmod_sangoma_ss7_main.h"
|
||||
/******************************************************************************/
|
||||
|
||||
/* DEFINES ********************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* GLOBALS ********************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* PROTOTYPES *****************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/* FUNCTIONS ******************************************************************/
|
||||
/******************************************************************************/
|
||||
|
||||
/******************************************************************************/
|
||||
/* For Emacs:
|
||||
* Local Variables:
|
||||
* mode:c
|
||||
* indent-tabs-mode:t
|
||||
* tab-width:4
|
||||
* c-basic-offset:4
|
||||
* End:
|
||||
* For VIM:
|
||||
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
|
||||
*/
|
||||
/******************************************************************************/
|
|
@ -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);
|
||||
|
@ -69,7 +72,7 @@ uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
|
|||
int k;
|
||||
int j;
|
||||
int flag;
|
||||
char tmp;
|
||||
char tmp[2];
|
||||
unsigned char lower;
|
||||
unsigned char upper;
|
||||
|
||||
|
@ -93,26 +96,33 @@ uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
|
|||
/**************************************************************************/
|
||||
cgPtyNum->addrSig.pres = PRSNT_NODEF;
|
||||
|
||||
/* 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;
|
||||
|
||||
while (1) {
|
||||
tmp = ftdm->cid_num.digits[k];
|
||||
if (tmp != '\0') {
|
||||
if (isdigit(tmp)) {
|
||||
lower = atoi(&tmp);
|
||||
tmp[0] = ftdm->cid_num.digits[k];
|
||||
|
||||
if (tmp[0] != '\0') {
|
||||
if (isdigit(tmp[0])) {
|
||||
lower = atoi(&tmp[0]);
|
||||
k++;
|
||||
tmp = ftdm->cid_num.digits[k];
|
||||
tmp[0] = ftdm->cid_num.digits[k];
|
||||
} else {
|
||||
while (!(isdigit(tmp)) && (tmp != '\0')) {
|
||||
while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
|
||||
k++;
|
||||
tmp = ftdm->cid_num.digits[k];
|
||||
tmp[0] = ftdm->cid_num.digits[k];
|
||||
} /* while(!(isdigit(tmp))) */
|
||||
|
||||
if (tmp != '\0') {
|
||||
lower = atoi(&tmp);
|
||||
if (tmp[0] != '\0') {
|
||||
lower = atoi(&tmp[0]);
|
||||
k++;
|
||||
tmp = ftdm->cid_num.digits[k];
|
||||
tmp[0] = ftdm->cid_num.digits[k];
|
||||
} else {
|
||||
flag = 1;
|
||||
lower = 0xf;
|
||||
|
@ -123,18 +133,19 @@ uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
|
|||
lower = 0xf;
|
||||
} /* if (tmp != '\0') */
|
||||
|
||||
tmp = ftdm->cid_num.digits[k];
|
||||
if (tmp != '\0') {
|
||||
if (isdigit(tmp)) {
|
||||
upper = (atoi(&tmp)) << 4;
|
||||
tmp[0] = ftdm->cid_num.digits[k];
|
||||
|
||||
if (tmp[0] != '\0') {
|
||||
if (isdigit(tmp[0])) {
|
||||
upper = (atoi(&tmp[0])) << 4;
|
||||
} else {
|
||||
while (!(isdigit(tmp)) && (tmp != '\0')) {
|
||||
while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
|
||||
k++;
|
||||
tmp = ftdm->cid_num.digits[k];
|
||||
tmp[0] = ftdm->cid_num.digits[k];
|
||||
} /* while(!(isdigit(tmp))) */
|
||||
|
||||
if (tmp != '\0') {
|
||||
upper = (atoi(&tmp)) << 4;
|
||||
if (tmp[0] != '\0') {
|
||||
upper = (atoi(&tmp[0])) << 4;
|
||||
k++;
|
||||
} else {
|
||||
flag = 1;
|
||||
|
@ -151,6 +162,7 @@ uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
|
|||
} /* if (tmp != '\0') */
|
||||
|
||||
cgPtyNum->addrSig.val[j] = upper | lower;
|
||||
|
||||
j++;
|
||||
|
||||
if (flag) {
|
||||
|
@ -161,9 +173,12 @@ uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum)
|
|||
} /* while(1) */
|
||||
|
||||
cgPtyNum->addrSig.len = j;
|
||||
|
||||
/**************************************************************************/
|
||||
cgPtyNum->oddEven.pres = PRSNT_NODEF;
|
||||
|
||||
cgPtyNum->oddEven.val = ((cgPtyNum->addrSig.val[j] >> 4) == 0x0 ) ? 0x01 : 0x00;
|
||||
|
||||
/**************************************************************************/
|
||||
return 0;
|
||||
}
|
||||
|
@ -181,7 +196,7 @@ uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
|
|||
int k;
|
||||
int j;
|
||||
int flag;
|
||||
char tmp;
|
||||
char tmp[2];
|
||||
unsigned char lower;
|
||||
unsigned char upper;
|
||||
|
||||
|
@ -199,26 +214,33 @@ uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
|
|||
/**************************************************************************/
|
||||
cdPtyNum->addrSig.pres = PRSNT_NODEF;
|
||||
|
||||
/* 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;
|
||||
|
||||
while (1) {
|
||||
tmp = ftdm->dnis.digits[k];
|
||||
if (tmp != '\0') {
|
||||
if (isdigit(tmp)) {
|
||||
lower = atoi(&tmp);
|
||||
tmp[0] = ftdm->dnis.digits[k];
|
||||
|
||||
if (tmp[0] != '\0') {
|
||||
if (isdigit(tmp[0])) {
|
||||
lower = atoi(&tmp[0]);
|
||||
k++;
|
||||
tmp = ftdm->dnis.digits[k];
|
||||
tmp[0] = ftdm->dnis.digits[k];
|
||||
} else {
|
||||
while (!(isdigit(tmp)) && (tmp != '\0')) {
|
||||
while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
|
||||
k++;
|
||||
tmp = ftdm->dnis.digits[k];
|
||||
tmp[0] = ftdm->dnis.digits[k];
|
||||
} /* while(!(isdigit(tmp))) */
|
||||
|
||||
if (tmp != '\0') {
|
||||
lower = atoi(&tmp);
|
||||
if (tmp[0] != '\0') {
|
||||
lower = atoi(&tmp[0]);
|
||||
k++;
|
||||
tmp = ftdm->dnis.digits[k];
|
||||
tmp[0] = ftdm->dnis.digits[k];
|
||||
} else {
|
||||
flag = 1;
|
||||
lower = 0xf;
|
||||
|
@ -229,18 +251,19 @@ uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
|
|||
lower = 0xf;
|
||||
} /* if (tmp != '\0') */
|
||||
|
||||
tmp = ftdm->dnis.digits[k];
|
||||
if (tmp != '\0') {
|
||||
if (isdigit(tmp)) {
|
||||
upper = (atoi(&tmp)) << 4;
|
||||
tmp[0] = ftdm->dnis.digits[k];
|
||||
|
||||
if (tmp[0] != '\0') {
|
||||
if (isdigit(tmp[0])) {
|
||||
upper = (atoi(&tmp[0])) << 4;
|
||||
} else {
|
||||
while (!(isdigit(tmp)) && (tmp != '\0')) {
|
||||
while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) {
|
||||
k++;
|
||||
tmp = ftdm->dnis.digits[k];
|
||||
tmp[0] = ftdm->dnis.digits[k];
|
||||
} /* while(!(isdigit(tmp))) */
|
||||
|
||||
if (tmp != '\0') {
|
||||
upper = (atoi(&tmp)) << 4;
|
||||
if (tmp[0] != '\0') {
|
||||
upper = (atoi(&tmp[0])) << 4;
|
||||
k++;
|
||||
} else {
|
||||
flag = 1;
|
||||
|
@ -257,6 +280,7 @@ uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
|
|||
} /* if (tmp != '\0') */
|
||||
|
||||
cdPtyNum->addrSig.val[j] = upper | lower;
|
||||
|
||||
j++;
|
||||
|
||||
if (flag) {
|
||||
|
@ -267,9 +291,12 @@ uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum)
|
|||
} /* while(1) */
|
||||
|
||||
cdPtyNum->addrSig.len = j;
|
||||
|
||||
/**************************************************************************/
|
||||
cdPtyNum->oddEven.pres = PRSNT_NODEF;
|
||||
|
||||
cdPtyNum->oddEven.val = ((cdPtyNum->addrSig.val[j] >> 4) == 0x0 ) ? 0x01 : 0x00;
|
||||
|
||||
/**************************************************************************/
|
||||
return 0;
|
||||
}
|
||||
|
@ -281,6 +308,7 @@ uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven)
|
|||
uint8_t j;
|
||||
|
||||
/* check if the token string is present */
|
||||
|
||||
if (str.pres == 1) {
|
||||
j = 0;
|
||||
|
||||
|
@ -309,49 +337,106 @@ uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven)
|
|||
int check_for_state_change(ftdm_channel_t *ftdmchan)
|
||||
{
|
||||
|
||||
#if 0
|
||||
SS7_DEBUG("Checking for pending state change on span: %d, chan: %d\n!",
|
||||
ftdmchan->physical_span_id,
|
||||
ftdmchan->physical_chan_id);
|
||||
#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);
|
||||
|
||||
/* move the state of the channel to RESTART to force a reset */
|
||||
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
|
||||
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
|
||||
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
|
||||
|
||||
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) {
|
||||
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");
|
||||
|
||||
*sngss7_info = g_ftdm_sngss7_data.cfg.isupCkt[circuit].obj;
|
||||
|
||||
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__);
|
||||
/*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)
|
||||
{
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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);
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright (c) 2010, Sangoma Technologies
|
||||
* David Yat Sin <dyatsin@sangoma.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of the original author; nor the names of any contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#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__ */
|
||||
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue