Merge remote branch 'smgfs/master'

This commit is contained in:
Moises Silva 2010-09-07 13:39:18 -04:00
commit 7fd0f84cce
37 changed files with 13456 additions and 7803 deletions

View File

@ -41,6 +41,9 @@ INCS += -I$(FT_SRCDIR)/$(SRC)/ftmod/ftmod_sangoma_boost
if SNGSS7
INCS += -I/usr/include/sng_ss7/
endif
if SNGISDN
INCS += -I/usr/include/sng_isdn/
endif
MY_CFLAGS = $(INCS) $(FTDM_CFLAGS) -DFTDM_CONFIG_DIR=\"@confdir@\" -DFTDM_MOD_DIR=\"$(moddir)\" @COMP_VENDOR_CFLAGS@ @DEFS@
COMPILE = $(CC) $(MY_CFLAGS) $(INCS)
@ -70,6 +73,7 @@ $(SRC)/hashtable_itr.c \
$(SRC)/ftdm_io.c \
$(SRC)/ftdm_queue.c \
$(SRC)/ftdm_sched.c \
$(SRC)/ftdm_call_utils.c \
$(SRC)/ftdm_config.c \
$(SRC)/ftdm_callerid.c \
$(SRC)/fsk.c \
@ -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)

View File

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

View File

@ -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);

View File

@ -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;
}

View File

@ -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)

View File

@ -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;
}

View File

@ -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

View File

@ -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;

View File

@ -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__ */

View File

@ -47,7 +47,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) span->signal_data;
switch(span->trunk_type) {
case FTDM_TRUNK_T1:
if (!strcasecmp(switch_name, "ni2")) {
if (!strcasecmp(switch_name, "ni2") ||
!strcasecmp(switch_name, "national")) {
signal_data->switchtype = SNGISDN_SWITCH_NI2;
} else if (!strcasecmp(switch_name, "5ess")) {
signal_data->switchtype = SNGISDN_SWITCH_5ESS;
@ -127,6 +128,7 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
dchan_data->channels[chan_id] = (sngisdn_chan_data_t*)ftdmchan->call_data;
dchan_data->num_chans++;
}
return FTDM_SUCCESS;
}
@ -144,7 +146,7 @@ ftdm_status_t parse_signalling(const char* signalling, ftdm_span_t *span)
signal_data->signalling = SNGISDN_SIGNALING_CPE;
} else {
ftdm_log(FTDM_LOG_ERROR, "Unsupported signalling %s\n", signalling);
ftdm_log(FTDM_LOG_ERROR, "Unsupported signalling/interface %s\n", signalling);
return FTDM_FAIL;
}
return FTDM_SUCCESS;
@ -156,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;
}

View File

@ -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;
}

View File

@ -223,17 +223,17 @@ ftdm_status_t sng_isdn_stack_cfg_phy_psap(ftdm_span_t *span)
switch(span->trunk_type) {
case FTDM_TRUNK_E1:
cfg.t.cfg.s.l1PSAP.chan = 16;
cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_PRI;
cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI;
break;
case FTDM_TRUNK_T1:
case FTDM_TRUNK_J1:
cfg.t.cfg.s.l1PSAP.chan = 24;
cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_PRI;
cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_PRI;
break;
case FTDM_TRUNK_BRI:
case FTDM_TRUNK_BRI_PTMP:
cfg.t.cfg.s.l1PSAP.chan = 3;
cfg.t.cfg.s.l1PSAP.type = SNG_LINKTYPE_BRI;
cfg.t.cfg.s.l1PSAP.type = SNG_L1_TYPE_BRI;
break;
default:
ftdm_log(FTDM_LOG_ERROR, "%s:Unsupported trunk type %d\n", span->name, span->trunk_type);
@ -280,10 +280,10 @@ ftdm_status_t sng_isdn_stack_cfg_q921_gen(void)
cfg.t.cfg.s.bdGen.nmbASPLnks = MAX_L1_LINKS+1;
#ifdef LAPD_3_4
cfg.t.cfg.s.bdGen.timeRes = 10; /* timer resolution */
cfg.t.cfg.s.bdGen.timeRes = 100; /* timer resolution = 1 sec */
#endif
cfg.t.cfg.s.bdGen.poolTrUpper = POOL_UP_TR; /* upper pool threshold */
cfg.t.cfg.s.bdGen.poolTrLower = POOL_LW_TR; /* lower pool threshold */
cfg.t.cfg.s.bdGen.poolTrUpper = 2; /* upper pool threshold */
cfg.t.cfg.s.bdGen.poolTrLower = 1; /* lower pool threshold */
if (sng_isdn_q921_config(&pst, &cfg)) {
return FTDM_FAIL;
@ -315,9 +315,9 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.lnkNmb = signal_data->link_id;
cfg.t.cfg.s.bdMSAP.maxOutsFrms = 2; /* MAC window */
cfg.t.cfg.s.bdMSAP.tQUpperTrs = 16; /* Tx Queue Upper Threshold */
cfg.t.cfg.s.bdMSAP.tQLowerTrs = 8; /* Tx Queue Lower Threshold */
cfg.t.cfg.s.bdMSAP.maxOutsFrms = 24; /* MAC window */
cfg.t.cfg.s.bdMSAP.tQUpperTrs = 32; /* Tx Queue Upper Threshold */
cfg.t.cfg.s.bdMSAP.tQLowerTrs = 24; /* Tx Queue Lower Threshold */
cfg.t.cfg.s.bdMSAP.selector = 0; /* Selector 0 */
/* TODO: check if bdMSAP parameters can be initialized by calling stack_pst_init */
cfg.t.cfg.s.bdMSAP.mem.region = S_REG; /* Memory region */
@ -327,8 +327,8 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.dstProcId = SFndProcId(); /* destination proc id */
cfg.t.cfg.s.bdMSAP.dstEnt = ENTL1; /* entity */
cfg.t.cfg.s.bdMSAP.dstInst = S_INST; /* instance */
cfg.t.cfg.s.bdMSAP.t201Tmr = 5; /* T201 */
cfg.t.cfg.s.bdMSAP.t202Tmr = 200; /* T202 */
cfg.t.cfg.s.bdMSAP.t201Tmr = 1; /* T201 - should be equal to t200Tmr */
cfg.t.cfg.s.bdMSAP.t202Tmr = 2; /* T202 */
cfg.t.cfg.s.bdMSAP.bndRetryCnt = 2; /* bind retry counter */
cfg.t.cfg.s.bdMSAP.tIntTmr = 200; /* bind retry timer */
cfg.t.cfg.s.bdMSAP.n202 = 3; /* N202 */
@ -341,7 +341,21 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.kpL1Up = TRUE; /* flag to keep l1 up or not */
}
cfg.t.cfg.s.bdMSAP.type = sng_isdn_stack_switchtype(signal_data->switchtype);
switch(signal_data->switchtype) {
case SNGISDN_SWITCH_NI2:
case SNGISDN_SWITCH_5ESS:
case SNGISDN_SWITCH_4ESS:
case SNGISDN_SWITCH_DMS100:
cfg.t.cfg.s.bdMSAP.type = SW_NI2;
break;
case SNGISDN_SWITCH_INSNET:
cfg.t.cfg.s.bdMSAP.type = SW_CCITT;
break;
case SNGISDN_SWITCH_EUROISDN:
case SNGISDN_SWITCH_QSIG:
cfg.t.cfg.s.bdMSAP.type = SW_ETSI;
break;
}
if (span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
cfg.t.cfg.s.bdMSAP.teiChkTmr = 20; /* Tei check timer */
@ -357,6 +371,12 @@ ftdm_status_t sng_isdn_stack_cfg_q921_msap(ftdm_span_t *span)
cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE; /* set up arbitration */
}
/* Overwrite setUpArb value if user forced it */
if (signal_data->setup_arb == SNGISDN_OPT_TRUE) {
cfg.t.cfg.s.bdMSAP.setUpArb = ACTIVE;
} else if (signal_data->setup_arb == SNGISDN_OPT_FALSE) {
cfg.t.cfg.s.bdMSAP.setUpArb = PASSIVE;
}
if (sng_isdn_q921_config(&pst, &cfg)) {
return FTDM_FAIL;
@ -389,11 +409,18 @@ ftdm_status_t sng_isdn_stack_cfg_q921_dlsap(ftdm_span_t *span, uint8_t managemen
cfg.t.cfg.s.bdDLSAP.lnkNmb = signal_data->link_id;
cfg.t.cfg.s.bdDLSAP.n201 = 1028; /* n201 */
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;

View File

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

View File

@ -0,0 +1,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;
}

View File

@ -1,935 +0,0 @@
/*
* Copyright (c) 2010, Sangoma Technologies
* David Yat Sin <davidy@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "ftmod_sangoma_isdn.h"
extern ftdm_status_t cpy_calling_num_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
extern ftdm_status_t cpy_called_num_from_sngisdn(ftdm_caller_data_t *ftdm, CdPtyNmb *cdPtyNmb);
extern ftdm_status_t cpy_called_name_from_sngisdn(ftdm_caller_data_t *ftdm, CgPtyNmb *cgPtyNmb);
extern ftdm_status_t cpy_calling_name_from_sngisdn(ftdm_caller_data_t *ftdm, ConEvnt *conEvnt);
extern void sngisdn_trace_q921(char* str, uint8_t* data, uint32_t data_len);
extern void sngisdn_trace_q931(char* str, uint8_t* data, uint32_t data_len);
extern void get_memory_info(void);
extern ftdm_sngisdn_data_t g_sngisdn_data;
#define MAX_DECODE_STR_LEN 2000
/* Remote side transmit a SETUP */
void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, ConEvnt *conEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
uint8_t bchan_no = 0;
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan;
/*sngisdn_span_data_t *span_info;*/
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
ftdm_assert(g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] == NULL, "Con Ind on busy spInstId");
if (conEvnt->chanId.eh.pres != PRSNT_NODEF) {
/* TODO: Implement me */
ftdm_log(FTDM_LOG_ERROR, "Incoming call without Channel Id not supported yet\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (conEvnt->chanId.chanNmbSlotMap.pres) {
bchan_no = conEvnt->chanId.chanNmbSlotMap.val[0];
} else if (conEvnt->chanId.infoChanSel.pres) {
bchan_no = conEvnt->chanId.infoChanSel.val;
}
if (!bchan_no) {
ftdm_log(FTDM_LOG_ERROR, "Failed to obtain b-channel number from SETUP message\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (g_sngisdn_data.dchans[dChan].channels[bchan_no] == NULL) {
ftdm_log(FTDM_LOG_ERROR, "Incoming call on unconfigured b-channel:%d\n", bchan_no);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
sngisdn_info = g_sngisdn_data.dchans[dChan].channels[bchan_no];
ftdmchan = sngisdn_info->ftdmchan;
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a pending state change, give it a bit to clear */
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received SETUP\n");
switch (ftdmchan->state){
case FTDM_CHANNEL_STATE_DOWN: /* Proper state to receive a SETUP */
sngisdn_info->suInstId = get_unique_suInstId(suId);
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info;
/* try to open the channel */
if (ftdm_channel_open_chan(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to open channel");
sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_REL);
ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE;
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_CANCEL);
} else {
/* Fill in call information */
cpy_calling_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
cpy_called_num_from_sngisdn(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
cpy_calling_name_from_sngisdn(&ftdmchan->caller_data, conEvnt);
/* Get ani2 */
#if 0
/* TODO: confirm that this works in the field */
if (conEvnt->niOperSysAcc.eh.pres) {
if (conEvnt->niOperSysAcc.typeAcc.pres) {
ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeAcc.val;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of access:%x", conEvnt->niOperSysAcc.typeAcc.val);
}
if (conEvnt->niOperSysAcc.typeServ.pres) {
ftdmchan->caller_data.aniII = (uint8_t)conEvnt->niOperSysAcc.typeServ.val;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Received ANI: type of service:%x", conEvnt->niOperSysAcc.typeServ.val);
}
}
#endif
/* set the state of the channel to collecting...the rest is done by the chan monitor */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
}
break;
case FTDM_CHANNEL_STATE_DIALING: /* glare */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Received SETUP in DIALING state, glare, queueing incoming call\n");
/* the flag the channel as having a collision */
sngisdn_set_flag(sngisdn_info, FLAG_GLARE);
/* save the SETUP for processing once the channel has gone to DOWN */
memcpy(&sngisdn_info->glare.setup, conEvnt, sizeof(*conEvnt));
sngisdn_info->glare.suId = suId;
sngisdn_info->glare.suInstId = suInstId;
sngisdn_info->glare.spInstId = spInstId;
sngisdn_info->glare.dChan = dChan;
sngisdn_info->glare.ces = ces;
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received SETUP in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
break;
}
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
/* Remote side transmit a CONNECT or CONNECT ACK */
void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan;
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
if (!sngisdn_info->spInstId) {
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received CONNECT/CONNECT ACK\n");
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a pending state change, give it a bit to clear */
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (ftdmchan->span->trunk_type == FTDM_TRUNK_BRI_PTMP &&
((sngisdn_span_data_t*)ftdmchan->span->signal_data)->signalling == SNGISDN_SIGNALING_NET) {
if(sngisdn_info->ces == CES_MNGMNT) {
/* We assign the call to the first TE */
sngisdn_info->ces = ces;
} else {
/* We already assigned this call, do nothing */
ftdm_mutex_unlock(ftdmchan->mutex);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Call already assigned, ignoring connect\n");
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
}
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_DIALING:
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_UP);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
} else {
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* This is the only valid state we should get a CONNECT ACK on */
/* do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
}
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan;
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d dChan:%d ces:%d\n", __FUNCTION__, suId, suInstId, spInstId, dChan, ces);
ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n");
ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n");
if (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
if (!sngisdn_info->spInstId) {
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
}
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Received %s\n",
(evntType == MI_ALERTING)?"ALERT":
(evntType == MI_CALLPROC)?"PROCEED":
(evntType == MI_PROGRESS)?"PROGRESS":"UNKNOWN");
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a pending state change, give it a bit to clear */
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
switch(ftdmchan->state) {
case FTDM_CHANNEL_STATE_DIALING:
if (evntType == MI_PROGRESS) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
} else {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS:
if (evntType == MI_PROGRESS) {
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA);
}
break;
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* Do nothing */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received ALERT/PROCEED/PROGRESS in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
sngisdn_chan_data_t *sngisdn_info;
ftdm_channel_t *ftdmchan = NULL;
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id");
if (spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) {
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
} else if (suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS) {
ftdmchan = (ftdm_channel_t*)sngisdn_info->ftdmchan;
} else {
ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
return;
}
if (!sngisdn_info->spInstId) {
sngisdn_info->spInstId = spInstId;
g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT\n");
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a pending state change, give it a bit to clear */
if (check_for_state_change(ftdmchan) != FTDM_SUCCESS) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_UP:
if (discEvnt->causeDgn[0].eh.pres && discEvnt->causeDgn[0].causeVal.pres) {
ftdmchan->caller_data.hangup_cause = discEvnt->causeDgn[0].causeVal.val;
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "DISCONNECT did not have a cause code\n");
ftdmchan->caller_data.hangup_cause = 0;
}
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_REL);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received DISCONNECT in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
/* start reset procedure */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
sngisdn_chan_data_t *sngisdn_info ;
ftdm_channel_t *ftdmchan = NULL;
/* get the ftdmchan and ss7_chan_data from the circuit */
if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdmchan = sngisdn_info->ftdmchan;
} else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdmchan = sngisdn_info->ftdmchan;
}
if (ftdmchan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE\n");
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a pending state change, give it a bit to clear */
if (check_for_state_change(ftdmchan)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
};
/* check whether the ftdm channel is in a state to accept a call */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* go to DOWN */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* do nothing, just drop the message */
break;
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
/* Remote side sent a SETUP, then a RELEASE COMPLETE to abort call - this is an abort */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_DIALING:
/* Remote side rejected our SETUP message on outbound call */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_UP:
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
default:
/* Should just stop the call...but a reset is easier for now (since it does hangup the call) */
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Received RELEASE in an invalid state (%s)\n",
ftdm_channel_state2str(ftdmchan->state));
/* go to RESTART */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
/**************************************************************************/
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, InfoEvnt *infoEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received DATA IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received SSHL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, SsHlEvnt *ssHlEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received SSHL CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE ind suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received FLOW CONTROL IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, FacEvnt *facEvnt, uint8_t evntType, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received FACILITY IND suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_sta_cfm ( int16_t suId, uint32_t suInstId, uint32_t spInstId, StaEvnt *staEvnt)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_DEBUG, "%s suId:%d suInstId:%d spInstId:%d\n", __FUNCTION__, suId, suInstId, spInstId);
sngisdn_chan_data_t *sngisdn_info ;
ftdm_channel_t *ftdmchan = NULL;
uint8_t call_state = 0;
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
call_state = staEvnt->callSte.callGlblSte.val;
}
/* get the ftdmchan and ss7_chan_data from the circuit */
if (suInstId && (get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdmchan = sngisdn_info->ftdmchan;
} else if (spInstId && (get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS)) {
ftdmchan = sngisdn_info->ftdmchan;
}
if (ftdmchan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Failed to find matching channel suId:%d suInstId:%d spInstId:%d\n", suId, suInstId, spInstId);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM\n");
/* now that we have the right channel...put a lock on it so no-one else can use it */
ftdm_mutex_lock(ftdmchan->mutex);
/* check if there is a pending state change, give it a bit to clear */
if (check_for_state_change(ftdmchan)) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "Failed to wait for pending state change\n");
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
};
if (staEvnt->causeDgn[0].eh.pres && staEvnt->causeDgn[0].causeVal.pres) {
if (staEvnt->causeDgn[0].causeVal.val != 30) {
if (staEvnt->callSte.eh.pres && staEvnt->callSte.callGlblSte.pres) {
call_state = staEvnt->callSte.callGlblSte.val;
/* Section 4.3.30 from INT Interface - Service Definition */
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
/* There is incompatibility between local and remote side call states some Q931 msgs probably got lost - initiate disconnect */
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Incompatible call states detected, remote side indicated state:%d our state:%s cause:%d\n", call_state, ftdm_channel_state2str(ftdmchan->state), staEvnt->causeDgn[0].causeVal.val);
switch(call_state) {
/* Sere ITU-T Q931 for definition of call states */
case 0: /* Remote switch thinks there are no calls on this channel */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_COLLECT:
case FTDM_CHANNEL_STATE_DIALING:
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_TERMINATING:
/* We are in the process of clearing local states,
just make sure we will not send any messages to remote switch */
sngisdn_set_flag(sngisdn_info, FLAG_REMOTE_ABORT);
break;
case FTDM_CHANNEL_STATE_HANGUP:
/* This cannot happen, state_advance always sets
ftdmchan to STATE_HANGUP_COMPLETE when in STATE_HANGUP
and we called check_for_state_change earlier so something is very wrong here!!! */
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "How can we we in FTDM_CHANNEL_STATE_HANGUP after checking for state change?\n");
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We were waiting for remote switch to send RELEASE COMPLETE
but this will not happen, so just clear local state */
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
case FTDM_CHANNEL_STATE_DOWN:
/* If our local state is down as well, then there is nothing to do */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
case 8: /* Remote switch is in "Connect Request state" */
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_UP:
/* This is ok. We sent a Connect, and we are waiting for a connect ack */
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We hung up locally, but remote switch doesn't know send disconnect again*/
sngisdn_snd_disconnect(ftdmchan);
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
break;
}
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Don't know how to handle incompatible state. remote call state:%d our state:%s\n", call_state, ftdm_channel_state2str(ftdmchan->state));
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
break;
}
} else {
ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val;
/* We could not extract the call state */
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Incompatible call states detected, but could not determine call (cause:%d)\n", ftdmchan->caller_data.hangup_cause);
ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART);
}
}
/**************************************************************************/
}
/* unlock the channel */
ftdm_mutex_unlock(ftdmchan->mutex);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_srv_ind ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_srv_cfm ( int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESTART IND suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_rst_cfm ( int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces, uint8_t evtType)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM suId:%d dChan:%d ces:%d\n", suId, dChan, ces);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_q921_ind(BdMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned j,k;
ftdm_span_t *ftdmspan = NULL;
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.lnkNmb) {
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
}
}
}
if (ftdmspan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Received q921 status on unconfigured span\n", status->t.usta.lnkNmb);
#ifdef DEBUG_MODE
FORCE_SEGFAULT
#endif
return;
}
switch (status->t.usta.alarm.category) {
case (LCM_CATEGORY_INTERFACE):
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
default:
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] %s: %s: %s(%d): %s(%d)\n",
ftdmspan->name,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LLD_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LLD_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__)
return;
}
void sngisdn_rcv_q931_ind(InMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_span_t *ftdmspan = NULL;
if (status->t.usta.alarm.cause == 287) {
get_memory_info();
return;
}
switch (status->t.usta.alarm.category) {
case (LCM_CATEGORY_INTERFACE):
ftdm_log(FTDM_LOG_WARNING, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
/* clean this up later */
switch (status->t.usta.alarm.event) {
case LCM_EVENT_UP:
case LCM_EVENT_DOWN:
{
unsigned j,k;
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.suId) {
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
}
}
}
if (ftdmspan == NULL) {
ftdm_log(FTDM_LOG_CRIT, "Received q931 LCM EVENT on unconfigured span (suId:%d)\n", status->t.usta.suId);
return;
}
sngisdn_set_span_sig_status(ftdmspan, (status->t.usta.alarm.event == LCM_EVENT_UP)?FTDM_SIG_STATE_UP:FTDM_SIG_STATE_DOWN);
}
break;
}
break;
default:
ftdm_log(FTDM_LOG_DEBUG, "[SNGISDN Q931] s%d: %s: %s(%d): %s(%d)\n",
status->t.usta.suId,
DECODE_LCM_CATEGORY(status->t.usta.alarm.category),
DECODE_LCM_EVENT(status->t.usta.alarm.event), status->t.usta.alarm.event,
DECODE_LCM_CAUSE(status->t.usta.alarm.cause), status->t.usta.alarm.cause);
break;
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_cc_ind(CcMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
ftdm_log(FTDM_LOG_INFO, "RECEIVED %s\n", __FUNCTION__);
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
#define Q931_TRC_EVENT(event) (event == TL3PKTTX)?"TX": \
(event == TL3PKTRX)?"RX":"UNKNOWN"
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
uint8_t data;
uint8_t tdata[1000];
char *data_str = ftdm_calloc(1,MAX_DECODE_STR_LEN); /* TODO Find a proper size */
ftdm_assert(mBuf != NULLP, "Received a Q931 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
i = 0;
for(j=0;j<mlen;j++) {
tdata[j]= data;
if (cptr == tmp->b_wptr) {
tmp = tmp->b_cont;
if (tmp) cptr = tmp->b_rptr;
}
data = *cptr++;
}
sngisdn_trace_q931(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q931] FRAME %s:%s\n", Q931_TRC_EVENT(trc->t.trc.evnt), data_str);
}
ftdm_safe_free(data_str);
/* We do not need to free mBuf in this case because stack does it */
/* SPutMsg(mBuf); */
return;
}
#define Q921_TRC_EVENT(event) (event == TL2FRMRX)?"RX": \
(event == TL2FRMTX)?"TX": \
(event == TL2TMR)?"TMR EXPIRED":"UNKNOWN"
void sngisdn_rcv_q921_trace(BdMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
uint8_t data;
uint8_t tdata[16];
char *data_str = ftdm_calloc(1,200); /* TODO Find a proper size */
if (trc->t.trc.evnt == TL2TMR) {
goto end_of_trace;
}
ftdm_assert(mBuf != NULLP, "Received a Q921 trace with no buffer");
mlen = ((SsMsgInfo*)(mBuf->b_rptr))->len;
if (mlen != 0) {
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
i = 0;
while (i < mlen) {
j = 0;
for(j=0;j<16;j++) {
if (i<mlen) {
tdata[j]= data;
if (cptr == tmp->b_wptr) {
tmp = tmp->b_cont;
if (tmp) cptr = tmp->b_rptr;
}
i++;
if (i<mlen) data = *cptr++;
}
}
}
sngisdn_trace_q921(data_str, tdata, mlen);
ftdm_log(FTDM_LOG_INFO, "[SNGISDN Q921] FRAME %s:%s\n", Q921_TRC_EVENT(trc->t.trc.evnt), data_str);
}
end_of_trace:
ftdm_safe_free(data_str);
SPutMsg(mBuf);
return;
}
void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
{
char *data;
int ret;
va_list ap;
va_start(ap, fmt);
ret = ftdm_vasprintf(&data, fmt, ap);
if (ret == -1) {
return;
}
switch (level) {
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_WARN:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_isdn->%s", data);
#ifdef DEBUG_MODE
FORCE_SEGFAULT
#endif
break;
case SNG_LOGLEVEL_CRIT:
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
#ifdef DEBUG_MODE
FORCE_SEGFAULT
#endif
break;
default:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
}
return;
}
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/
/******************************************************************************/

View File

@ -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;
}

View File

@ -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:
*/
/******************************************************************************/

View File

@ -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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -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)
{

View File

@ -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

View File

@ -0,0 +1,592 @@
/*
* Copyright (c) 2009|Konrad Hammel <konrad@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms|with or without
* modification|are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice|this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice|this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
* LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
* EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* INCLUDE ********************************************************************/
#include "ftmod_sangoma_ss7_main.h"
/******************************************************************************/
/* DEFINES ********************************************************************/
/******************************************************************************/
/* GLOBALS ********************************************************************/
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
void handle_sng_log(uint8_t level, char *fmt,...);
void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta);
void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta);
void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta);
void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta);
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
void handle_sng_log(uint8_t level, char *fmt,...)
{
char *data;
int ret;
va_list ap;
va_start(ap, fmt);
ret = vasprintf(&data, fmt, ap);
if (ret == -1) {
return;
}
switch (level) {
/**************************************************************************/
case SNG_LOGLEVEL_DEBUG:
ftdm_log(FTDM_LOG_DEBUG, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_WARN:
ftdm_log(FTDM_LOG_WARNING, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_INFO:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_STATS:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_ERROR:
ftdm_log(FTDM_LOG_ERROR, "sng_ss7->%s", data);
break;
/**************************************************************************/
case SNG_LOGLEVEL_CRIT:
/*printf("%s",data);*/
ftdm_log(FTDM_LOG_CRIT, "sng_ss7->%s", data);
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_INFO, "sng_ss7->%s", data);
break;
/**************************************************************************/
}
return;
}
/******************************************************************************/
void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta)
{
} /* handle_mtp1_alarm */
/******************************************************************************/
void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta)
{
switch (sta->t.usta.alarm.category) {
/**************************************************************************/
case (LCM_CATEGORY_PROTOCOL):
case (LCM_CATEGORY_INTERFACE):
switch (sta->t.usta.alarm.event) {
/**********************************************************************/
case (LSD_EVENT_ENTR_CONG):
case (LSD_EVENT_EXIT_CONG):
case (LSD_EVENT_PROT_ST_UP):
case (LSD_EVENT_PROT_ST_DN):
case (LSD_EVENT_LINK_ALIGNED):
case (LSD_EVENT_REMOTE_CONG_START):
case (LSD_EVENT_REMOTE_CONG_END):
case (LSD_EVENT_RX_REMOTE_SIPO):
switch (sta->t.usta.alarm.cause) {
/******************************************************************/
case (LCM_CAUSE_UNKNOWN):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
break;
/******************************************************************/
case (LCM_CAUSE_MGMT_INITIATED):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d][MGMT] %s\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
break;
/******************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s (***unknown cause***)\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event));
break;
/******************************************************************/
} /* switch (sta->t.usta.alarm.cause) */
break;
/**********************************************************************/
case (LSD_EVENT_PROT_ERR):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause));
break;
/**********************************************************************/
case (LSD_EVENT_ALIGN_LOST):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
break;
/**********************************************************************/
case (LSD_EVENT_RTB_FULL):
case (LSD_EVENT_RTB_FULL_OVER):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.evntParm[1],
sta->t.usta.evntParm[2],
sta->t.usta.evntParm[3],
sta->t.usta.evntParm[4]);
break;
/**********************************************************************/
case (LSD_EVENT_NEG_ACK):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.evntParm[1]);
break;
/**********************************************************************/
case (LSD_EVENT_DAT_CFM_SDT):
ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %d\n",
sta->t.usta.evntParm[0],
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_DISC_REASON(sta->t.usta.evntParm[1]));
break;
/**********************************************************************/
case (LCM_EVENT_UI_INV_EVT):
case (LCM_EVENT_LI_INV_EVT):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0]);
break;
/**********************************************************************/
case (LCM_EVENT_INV_EVT):
switch (sta->t.usta.alarm.cause) {
/******************************************************************/
case (LCM_CAUSE_UNKNOWN):
case (LCM_CAUSE_SWVER_NAVAIL):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Event (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0]);
break;
/******************************************************************/
case (LCM_CAUSE_DECODE_ERR):
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s : %s : Primitive (%d)|Version (%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
DECODE_LCM_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0],
sta->t.usta.evntParm[1]);
break;
/******************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.alarm.cause);
break;
/******************************************************************/
} /* switch (sta->t.usta.alarm.cause) */
break;
/**********************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2] %s(%d) : %s(%d)\n",
DECODE_LSD_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSD_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.alarm.cause);
break;
/**********************************************************************/
} /* switch (sta->t.usta.alarm.event) */
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP2] Unknown alarm category %d\n",
sta->t.usta.alarm.category);
break;
/**************************************************************************/
} /* switch(sta->t.usta.alarm.category) */
return;
} /* handle_mtp2_alarm */
/******************************************************************************/
void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta)
{
switch (sta->hdr.elmId.elmnt) {
/**************************************************************************/
case (STDLSAP):
switch (sta->t.usta.alarm.event) {
/**********************************************************************/
case (LSN_EVENT_INV_OPC_OTHER_END):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : OPC(0x%X%X%X%X)\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[3],
sta->t.usta.evntParm[2],
sta->t.usta.evntParm[1],
sta->t.usta.evntParm[0]);
break;
/**********************************************************************/
case (LSN_EVENT_INV_SLC_OTHER_END):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : SLC(%d)\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.evntParm[0]);
break;
/**********************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s(%d) : %s(%d)\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.alarm.cause);
break;
/**********************************************************************/
} /* sta->t.usta.alarm.event */
break;
/**************************************************************************/
case (STNSAP):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
break;
/**************************************************************************/
case (STLNKSET):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][LNKSET:%d] %s : %s\n",
sta->hdr.elmId.elmntInst1,
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
break;
/**************************************************************************/
case (STROUT):
ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%d%d%d%d] %s : %s\n",
sta->t.usta.evntParm[0],
sta->t.usta.evntParm[1],
sta->t.usta.evntParm[2],
sta->t.usta.evntParm[3],
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause));
break;
/**************************************************************************/
default:
ftdm_log(FTDM_LOG_ERROR,"[MTP3] %s(%d) : %s(%d)\n",
DECODE_LSN_EVENT(sta->t.usta.alarm.event),
sta->t.usta.alarm.event,
DECODE_LSN_CAUSE(sta->t.usta.alarm.cause),
sta->t.usta.alarm.cause);
break;
/**************************************************************************/
} /* switch (sta->hdr.elmId.elmnt) */
return;
} /* handle_mtp3_alarm */
/******************************************************************************/
void handle_sng_isup_alarm(Pst *pst, SiMngmt *sta)
{
char msg[250];
char tmp[25];
char *p = NULL;
int x = 0;
/* initalize the msg variable to NULLs */
memset(&msg[0], '\0', sizeof(&msg));
/* point p to the first spot in msg */
p = &msg[0];
p = strcat(p, "[ISUP]");
/* go through the dgnVals */
for (x = 0; x < 5; x++) {
switch (sta->t.usta.dgn.dgnVal[x].type) {
/**********************************************************************/
case (LSI_USTA_DGNVAL_NONE):
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_EVENT):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[EVENT:%d]",sta->t.usta.dgn.dgnVal[x].t.event);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SPID):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SPID:%d]",sta->t.usta.dgn.dgnVal[x].t.spId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SUID):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SUID:%d]",sta->t.usta.dgn.dgnVal[x].t.suId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SPINSTID):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SPINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.spInstId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SUINSTID):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SUINSTID:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.suInstId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_CIRCUIT):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[CKT:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cirId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_CIC):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[CIC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.cic);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_INTF):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[INTF:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.intfId);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_DPC):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[DPC:%d]", (int)sta->t.usta.dgn.dgnVal[x].t.dpc);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_ADDRS):
#if 0
/*
*typedef struct addrs
*{
*U8 length;
*U8 strg[ADRLEN];
*} Addrs;
*/
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[ADDRS:%d]",sta->t.usta.dgn.dgnVal[x].t.);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
#endif
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_SWTCH):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[SWTCH:%d]",sta->t.usta.dgn.dgnVal[x].t.swtch);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_RANGE):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[RANGE:0x%X]",sta->t.usta.dgn.dgnVal[x].t.range);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_STATUS_OCTS):
#if 0
/*
*typedef struct addrs
*{
*U8 length;
*U8 strg[ADRLEN];
*} Addrs;
*/
/* init tmp with NULLs */
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[STATUS_OCT:0x%X]",sta->t.usta.dgn.dgnVal[x].t.);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
#endif
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_VER):
#ifdef SI_RUG
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[VER:%d]",sta->t.usta.dgn.dgnVal[x].t.intfVer);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
#endif
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_TIMER):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[TIMER:0x%X]",sta->t.usta.dgn.dgnVal[x].t.tmrInfo);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_MSGTYPE):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[MSGTYPE:%d]",sta->t.usta.dgn.dgnVal[x].t.msgType);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
case (LSI_USTA_DGNVAL_STATE):
/* init tmp with NULLs */
memset(&tmp[0], '\0', sizeof(&tmp));
/* fill in the dgn val to tmp */
sprintf(&tmp[0], "[STATE:%d]",sta->t.usta.dgn.dgnVal[x].t.state);
/* concat tmp to msg */
p = strcat(p, &tmp[0]);
break;
/**********************************************************************/
default:
break;
/**********************************************************************/
} /* switch (sta->t.usta.dgn.dgnVal[x].t.type) */
} /* for (x = 0; x < 5; x++) */
ftdm_log(FTDM_LOG_ERROR,"%s %s : %s\n",
msg,
DECODE_LSI_EVENT(sta->t.usta.alarm.event),
DECODE_LSI_CAUSE(sta->t.usta.alarm.cause));
} /* handle_isup_alarm */
/******************************************************************************/
void handle_sng_cc_alarm(Pst *pst, CcMngmt *sta)
{
return;
} /* handle_cc_alarm */
/******************************************************************************/
/******************************************************************************/
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/
/******************************************************************************/

View File

@ -44,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:
*/
/******************************************************************************/

View File

@ -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:
*/
/******************************************************************************/

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2009 Konrad Hammel <konrad@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms|with or without
* modification|are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice|this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice|this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
* LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
* EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* INCLUDE ********************************************************************/
#include "ftmod_sangoma_ss7_main.h"
/******************************************************************************/
/* DEFINES ********************************************************************/
/******************************************************************************/
/* GLOBALS ********************************************************************/
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm);
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm)
{
SnMngmt sta;
memset(&sta, 0x0, sizeof(sta));
sta.hdr.elmId.elmnt = STDLSAP;
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id;
return(sng_sta_mtp3(&sta, cfm));
}
/******************************************************************************/
int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm)
{
SnMngmt sta;
memset(&sta, 0x0, sizeof(sta));
sta.hdr.elmId.elmnt = STLNKSET;
sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id;
sta.hdr.elmId.elmntInst2 = 1;
return(sng_sta_mtp3(&sta, cfm));
}
/******************************************************************************/
/******************************************************************************/
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/
/******************************************************************************/

View File

@ -0,0 +1,61 @@
/*
* Copyright (c) 2009 Konrad Hammel <konrad@sangoma.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms|with or without
* modification|are permitted provided that the following conditions
* are met:
*
* * Redistributions of source code must retain the above copyright
* notice|this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright
* notice|this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* * Neither the name of the original author; nor the names of any contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES|INCLUDING|BUT NOT
* LIMITED TO|THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT|INDIRECT|INCIDENTAL|SPECIAL,
* EXEMPLARY|OR CONSEQUENTIAL DAMAGES (INCLUDING|BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE|DATA|OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY|WHETHER IN CONTRACT|STRICT LIABILITY|OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE|EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* INCLUDE ********************************************************************/
#include "ftmod_sangoma_ss7_main.h"
/******************************************************************************/
/* DEFINES ********************************************************************/
/******************************************************************************/
/* GLOBALS ********************************************************************/
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
/******************************************************************************/
/******************************************************************************/
/* For Emacs:
* Local Variables:
* mode:c
* indent-tabs-mode:t
* tab-width:4
* c-basic-offset:4
* End:
* For VIM:
* vim:set softtabstop=4 shiftwidth=4 tabstop=4:
*/
/******************************************************************************/

View File

@ -50,6 +50,9 @@ uint8_t copy_cdPtyNum_from_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum
uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum);
int check_for_state_change(ftdm_channel_t *ftdmchan);
int check_cics_in_range(sngss7_chan_data_t *sngss7_info);
int check_for_reset(sngss7_chan_data_t *sngss7_info);
unsigned long get_unique_id(void);
ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan);
@ -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)
{

View File

@ -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);

View File

@ -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__ */

View File

@ -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

View File

@ -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 */