Merge branch 'master' of git.sangoma.com:smg_freeswitch

Conflicts:
	libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c
This commit is contained in:
David Yat Sin committed 2011-05-31 13:25:03 -04:00
commit 01eb776469
297 files changed
+12215 -7874

No files matched your search

@@ -426,7 +426,6 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = analog_data->wait_dialtone_timeout;
uint32_t answer_on_polarity_counter = 0;
ftdm_sigmsg_t sig;
ftdm_status_t status;
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "ANALOG CHANNEL thread starting.\n");
@@ -916,7 +915,7 @@ static void *ftdm_analog_channel_run(ftdm_thread_t *me, void *obj)
}
if (codec_func) {
status = codec_func(frame, sizeof(frame), &rlen);
codec_func(frame, sizeof(frame), &rlen);
} else {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
goto done;
@@ -221,7 +221,6 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
ftdm_channel_t *closed_chan;
uint32_t state_counter = 0, elapsed = 0, collecting = 0, interval = 0, last_digit = 0, indicate = 0, dial_timeout = 30000;
ftdm_sigmsg_t sig;
ftdm_status_t status;
ftdm_log(FTDM_LOG_DEBUG, "ANALOG EM CHANNEL thread starting.\n");
@@ -545,7 +544,7 @@ static void *ftdm_analog_em_channel_run(ftdm_thread_t *me, void *obj)
}
if (codec_func) {
status = codec_func(frame, sizeof(frame), &rlen);
codec_func(frame, sizeof(frame), &rlen);
} else {
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "codec error!");
goto done;
@@ -979,7 +979,6 @@ static L3INT ftdm_isdn_931_34(void *pvt, struct Q931_Call *call, Q931mes_Generic
{
Q931ie_CallingNum *callingnum = Q931GetIEPtr(gen->CallingNum, gen->buf);
Q931ie_CalledNum *callednum = Q931GetIEPtr(gen->CalledNum, gen->buf);
uint32_t cplen = mlen;
int overlap_dial = 0;
int fail_cause = 0;
int fail = 1;
@@ -2128,7 +2127,7 @@ static int ftdm_isdn_q921_log(void *pvt, Q921LogLevel_t level, char *msg, L2INT
return 0;
}
static L3INT ftdm_isdn_q931_log(void *pvt, Q931LogLevel_t level, char *msg, L3INT size)
static L3INT ftdm_isdn_q931_log(void *pvt, Q931LogLevel_t level, const char *msg, L3INT size)
{
ftdm_span_t *span = (ftdm_span_t *) pvt;
@@ -562,14 +562,18 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
sig.chan_id = ftdm_channel_get_id(chan);
sig.span_id = ftdm_channel_get_span_id(chan);
sig.channel = chan;
ftdm_channel_complete_state(chan);
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DOWN:
{
ftdm_channel_t *chtmp = chan;
chan->call_data = NULL;
if (call) {
pri_destroycall(isdn_data->spri.pri, call);
chan->call_data = NULL;
}
if (ftdm_channel_close(&chtmp) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_WARNING, "-- Failed to close channel %d:%d\n",
@@ -776,8 +780,7 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
pri_hangup(isdn_data->spri.pri, call, caller_data->hangup_cause);
// pri_destroycall(isdn_data->spri.pri, call);
chan->call_data = NULL;
// chan->call_data = NULL;
}
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
}
@@ -785,10 +788,10 @@ static ftdm_status_t state_advance(ftdm_channel_t *chan)
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
{
if (call) {
pri_destroycall(isdn_data->spri.pri, call);
chan->call_data = NULL;
}
// if (call) {
// pri_destroycall(isdn_data->spri.pri, call);
// chan->call_data = NULL;
// }
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_DOWN);
}
break;
@@ -854,7 +857,6 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
{
ftdm_span_t *span = spri->span;
ftdm_channel_t *chan = ftdm_span_get_channel(span, pevent->hangup.channel);
q931_call *call = NULL;
if (!chan) {
ftdm_log(FTDM_LOG_CRIT, "-- Hangup on channel %d:%d %s but it's not in use?\n", ftdm_span_get_id(spri->span), pevent->hangup.channel);
@@ -863,27 +865,61 @@ static int on_hangup(lpwrap_pri_t *spri, lpwrap_pri_event_t event_type, pri_even
ftdm_channel_lock(chan);
if (ftdm_channel_get_state(chan) >= FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n", ftdm_channel_get_state_str(chan));
goto done;
switch (event_type) {
case LPWRAP_PRI_EVENT_HANGUP_REQ: /* DISCONNECT */
if (ftdm_channel_get_state(chan) >= FTDM_CHANNEL_STATE_TERMINATING) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s\n",
ftdm_channel_get_state_str(chan));
goto done;
}
ftdm_log(FTDM_LOG_DEBUG, "-- Hangup REQ on channel %d:%d\n",
ftdm_span_get_id(spri->span), pevent->hangup.channel);
pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause);
chan->caller_data.hangup_cause = pevent->hangup.cause;
ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case LPWRAP_PRI_EVENT_HANGUP_ACK: /* */
ftdm_log(FTDM_LOG_DEBUG, "-- Hangup ACK on channel %d:%d\n",
ftdm_span_get_id(spri->span), pevent->hangup.channel);
pri_hangup(spri->pri, pevent->hangup.call, pevent->hangup.cause);
ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
break;
case LPWRAP_PRI_EVENT_HANGUP: /* "RELEASE/RELEASE_COMPLETE/other" */
ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n",
ftdm_span_get_id(spri->span), pevent->hangup.channel);
switch (ftdm_channel_get_state(chan)) {
case FTDM_CHANNEL_STATE_DIALING:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_PROCEED:
case FTDM_CHANNEL_STATE_UP:
chan->caller_data.hangup_cause = pevent->hangup.cause;
ftdm_set_state(chan, FTDM_CHANNEL_STATE_TERMINATING);
break;
case FTDM_CHANNEL_STATE_HANGUP:
chan->caller_data.hangup_cause = pevent->hangup.cause;
ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP_COMPLETE);
break;
// case FTDM_CHANNEL_STATE_TERMINATING:
// ftdm_set_state(chan, FTDM_CHANNEL_STATE_HANGUP);
// break;
// case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
// ftdm_set_state(chan, FTDM_CHANNEL_STATE_DOWN);
// break;
}
break;
default:
break;
}
if (!chan->call_data) {
ftdm_log_chan(chan, FTDM_LOG_DEBUG, "Ignoring remote hangup in state %s with no call data\n", ftdm_channel_get_state_str(chan));
goto done;
}
call = (q931_call *)chan->call_data;
ftdm_log(FTDM_LOG_DEBUG, "-- Hangup on channel %d:%d\n", ftdm_span_get_id(spri->span), pevent->hangup.channel);
pri_release(spri->pri, call, 0);
pri_destroycall(spri->pri, call);
chan->caller_data.hangup_cause = pevent->hangup.cause;
chan->call_data = NULL;
ftdm_set_state_locked(chan, FTDM_CHANNEL_STATE_TERMINATING);
done:
ftdm_channel_unlock(chan);
return 0;
@@ -1654,6 +1690,7 @@ static void *ftdm_libpri_run(ftdm_thread_t *me, void *obj)
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_UP, on_dchan_up);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_DCHAN_DOWN, on_dchan_down);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_REQ, on_hangup);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP_ACK, on_hangup);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_HANGUP, on_hangup);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_INFO_RECEIVED, on_info);
LPWRAP_MAP_PRI_EVENT(isdn_data->spri, LPWRAP_PRI_EVENT_RESTART, on_restart);
@@ -1928,6 +1965,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
assert(isdn_data != NULL);
memset(isdn_data, 0, sizeof(*isdn_data));
/* set some default values */
isdn_data->mode = PRI_CPE;
isdn_data->ton = PRI_UNKNOWN;
switch (ftdm_span_get_trunk_type(span)) {
case FTDM_TRUNK_BRI:
case FTDM_TRUNK_BRI_PTMP:
@@ -1938,12 +1979,14 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_libpri_configure_span)
#endif
case FTDM_TRUNK_E1:
ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ALAW since this is an E1/BRI/BRI PTMP trunk\n");
isdn_data->layer1 = PRI_LAYER_1_ALAW;
isdn_data->layer1 = PRI_LAYER_1_ALAW;
isdn_data->dialect = PRI_SWITCH_EUROISDN_E1;
break;
case FTDM_TRUNK_T1:
case FTDM_TRUNK_J1:
ftdm_log(FTDM_LOG_NOTICE, "Setting default Layer 1 to ULAW since this is a T1/J1 trunk\n");
isdn_data->layer1 = PRI_LAYER_1_ULAW;
isdn_data->layer1 = PRI_LAYER_1_ULAW;
isdn_data->dialect = PRI_SWITCH_LUCENT5E;
break;
default:
ftdm_log(FTDM_LOG_ERROR, "Invalid trunk type: '%s'\n", ftdm_span_get_trunk_type_str(span));
+13 -3
View File
@@ -360,11 +360,15 @@ static void ft_r2_clean_call(ftdm_r2_call_t *call)
static void ft_r2_accept_call(ftdm_channel_t *ftdmchan)
{
openr2_chan_t *r2chan = R2CALL(ftdmchan)->r2chan;
// FIXME: not always accept as no charge, let the user decide that
// also we should check the return code from openr2_chan_accept_call and handle error condition
ftdm_r2_data_t *r2data = ftdmchan->span->signal_data;
// FIXME: we should check the return code from openr2_chan_accept_call and handle error condition
// hanging up the call with protocol error as the reason, this openr2 API will fail only when there something
// wrong at the I/O layer or the library itself
openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
if (r2data->charge_calls)
openr2_chan_accept_call(r2chan, OR2_CALL_WITH_CHARGE);
else
openr2_chan_accept_call(r2chan, OR2_CALL_NO_CHARGE);
}
static void ft_r2_answer_call(ftdm_channel_t *ftdmchan)
@@ -1697,6 +1701,8 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_r2_configure_span_signaling)
r2data->category = r2conf.category;
r2data->allow_collect_calls = r2conf.allow_collect_calls;
r2data->flags = 0;
r2data->charge_calls = r2conf.charge_calls;
r2data->forced_release = r2conf.forced_release;
spanpvt->r2context = r2data->r2context;
/* just the value must be freed by the hash */
@@ -1854,6 +1860,10 @@ static ftdm_status_t ftdm_r2_state_advance(ftdm_channel_t *ftdmchan)
{
if (!r2call->disconnect_rcvd) {
openr2_call_disconnect_cause_t disconnect_cause = ftdm_r2_ftdm_cause_to_openr2_cause(ftdmchan);
/* overwrite the hangup cause if this is an incoming call and forced_release is set */
if (openr2_chan_get_direction(r2chan) == OR2_DIR_BACKWARD && r2data->forced_release) {
disconnect_cause = OR2_CAUSE_FORCED_RELEASE;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Clearing call, cause = %s\n", openr2_proto_get_disconnect_string(disconnect_cause));
/* this will disconnect the call, but need to wait for the call end before moving to DOWN */
openr2_chan_disconnect_call(r2chan, disconnect_cause);
@@ -1198,9 +1198,17 @@ static FIO_SIG_UNLOAD_FUNCTION(ftdm_sangoma_isdn_unload)
return FTDM_SUCCESS;
}
#define SANGOMA_ISDN_API_USAGE_TRACE "ftdm sangoma_isdn trace <q921|q931> <span name>\n"
#define SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS "ftdm sangoma_isdn l1_stats <span name>\n"
#define SANGOMA_ISDN_API_USAGE_SHOW_SPANS "ftdm sangoma_isdn show_spans [<span name>]\n"
#define SANGOMA_ISDN_API_USAGE "\t"SANGOMA_ISDN_API_USAGE_TRACE \
"\t"SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS \
"\t"SANGOMA_ISDN_API_USAGE_SHOW_SPANS
static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
{
ftdm_status_t status = FTDM_SUCCESS;
ftdm_status_t status = FTDM_EINVAL;
char *mycmd = NULL, *argv[10] = { 0 };
int argc = 0;
@@ -1222,7 +1230,7 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
ftdm_span_t *span;
if (argc < 3) {
ftdm_log(FTDM_LOG_ERROR, "Usage: ftdm sangoma_isdn trace <q921|q931> <span name>\n");
ftdm_log(FTDM_LOG_ERROR, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_TRACE);
status = FTDM_FAIL;
goto done;
}
@@ -1231,34 +1239,40 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
status = ftdm_span_find_by_name(argv[2], &span);
if (FTDM_SUCCESS != status) {
stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]);
status = FTDM_FAIL;
goto done;
}
if (!strcasecmp(trace_opt, "q921")) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
status = sngisdn_activate_trace(span, SNGISDN_TRACE_Q921);
} else if (!strcasecmp(trace_opt, "q931")) {
sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
status = sngisdn_activate_trace(span, SNGISDN_TRACE_Q931);
} else if (!strcasecmp(trace_opt, "disable")) {
sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
status = sngisdn_activate_trace(span, SNGISDN_TRACE_DISABLE);
} else {
stream->write_function(stream, "-ERR invalid trace option <q921|q931> <span name>\n");
status = FTDM_FAIL;
}
goto done;
}
if (!strcasecmp(argv[0], "l1_stats")) {
ftdm_span_t *span;
if (argc < 2) {
stream->write_function(stream, "Usage: ftdm sangoma_isdn l1_stats <span name>\n");
stream->write_function(stream, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_SHOW_L1_STATS);
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 with name %s\n", argv[1]);
/* Return SUCCESS because we do not want to print the general FTDM usage list */
status = FTDM_SUCCESS;
status = FTDM_FAIL;
goto done;
}
sngisdn_print_phy_stats(stream, span);
status = sngisdn_show_l1_stats(stream, span);
goto done;
}
if (!strcasecmp(argv[0], "show_spans")) {
@@ -1267,20 +1281,42 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
status = ftdm_span_find_by_name(argv[1], &span);
if (FTDM_SUCCESS != status) {
stream->write_function(stream, "-ERR failed to find span with name %s\n", argv[1]);
/* Return SUCCESS because we do not want to print the general FTDM usage list */
status = FTDM_SUCCESS;
stream->write_function(stream, "Usage: %s\n", SANGOMA_ISDN_API_USAGE_SHOW_SPANS);
status = FTDM_FAIL;
goto done;
}
sngisdn_print_span(stream, span);
status = FTDM_SUCCESS;
status = sngisdn_show_span(stream, span);
goto done;
}
sngisdn_print_spans(stream);
status = sngisdn_show_spans(stream);
goto done;
}
if (!strcasecmp(argv[0], "check_ids")) {
sngisdn_check_free_ids();
status = sngisdn_check_free_ids();
goto done;
}
if (!strcasecmp(argv[0], "check_mem")) {
sngisdn_get_memory_info();
}
done:
switch (status) {
case FTDM_SUCCESS:
stream->write_function(stream, "Command executed OK\n");
break;
case FTDM_EINVAL:
stream->write_function(stream, "Invalid arguments [%s]\n", mycmd);
stream->write_function(stream, "Usage:\n%s\n", SANGOMA_ISDN_API_USAGE);
break;
default:
/* FTDM_FAIL - Do nothing since we already printed the cause of the error */
break;
}
/* Return SUCCESS because we do not want to print the general FTDM usage list */
status = FTDM_SUCCESS;
ftdm_safe_free(mycmd);
return status;
}
@@ -292,6 +292,12 @@ typedef struct ftdm_sngisdn_data {
sngisdn_span_data_t *spans[MAX_L1_LINKS+1]; /* spans are indexed by link_id */
}ftdm_sngisdn_data_t;
typedef struct ftdm2trillium
{
uint8_t ftdm_val;
uint8_t trillium_val;
}ftdm2trillium_t;
/* TODO implement these 2 functions */
#define ISDN_FUNC_TRACE_ENTER(a)
@@ -388,7 +394,7 @@ void sngisdn_trace_interpreted_q931(sngisdn_span_data_t *signal_data, ftdm_trace
void sngisdn_trace_raw_q921(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void sngisdn_trace_raw_q931(sngisdn_span_data_t *signal_data, ftdm_trace_dir_t dir, uint8_t *data, uint32_t data_len);
void get_memory_info(void);
void sngisdn_get_memory_info(void);
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
ftdm_status_t sngisdn_check_free_ids(void);
@@ -471,9 +477,9 @@ ftdm_status_t sngisdn_stack_start(ftdm_span_t *span);
ftdm_status_t sngisdn_stack_stop(ftdm_span_t *span);
ftdm_status_t sngisdn_wake_up_phy(ftdm_span_t *span);
void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span);
void sngisdn_print_spans(ftdm_stream_handle_t *stream);
void sngisdn_print_span(ftdm_stream_handle_t *stream, ftdm_span_t *span);
ftdm_status_t sngisdn_show_l1_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span);
ftdm_status_t sngisdn_show_spans(ftdm_stream_handle_t *stream);
ftdm_status_t sngisdn_show_span(ftdm_stream_handle_t *stream, ftdm_span_t *span);
#endif /* __FTMOD_SNG_ISDN_H__ */
@@ -745,8 +745,16 @@ ftdm_status_t sngisdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
/* TODO: Fill in these timers with proper values - eventually pass them */
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;
/* It looks like ETSI is the only variant that supports Overlap */
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN) {
cfg.t.cfg.s.inDLSAP.tmr.t302.enb = TRUE;
cfg.t.cfg.s.inDLSAP.tmr.t302.val = 15;
} else {
cfg.t.cfg.s.inDLSAP.tmr.t302.enb = FALSE;
cfg.t.cfg.s.inDLSAP.tmr.t302.val = 0;
}
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;
@@ -35,6 +35,7 @@
#include "ftmod_sangoma_isdn.h"
static ftdm_status_t sngisdn_cause_val_requires_disconnect(ftdm_channel_t *ftdmchan, CauseDgn *causeDgn);
static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan);
static ftdm_status_t sngisdn_force_down(ftdm_channel_t *ftdmchan);
/* Remote side transmit a SETUP */
void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
@@ -191,8 +192,7 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
}
}
#endif
#endif
if (signal_data->overlap_dial == SNGISDN_OPT_TRUE && !conEvnt->sndCmplt.eh.pres) {
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_COLLECT);
} else {
@@ -831,7 +831,7 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event)
if (sng_isdn_retrieve_facility_caller_name(&facEvnt->facElmt.facStr.val[2], facEvnt->facElmt.facStr.len, retrieved_str) == 0) {
strcpy(ftdmchan->caller_data.cid_name, retrieved_str);
} else {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n");
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Failed to retrieve Caller Name from Facility IE\n");
}
if (signal_data->facility_timeout) {
/* Cancel facility timeout */
@@ -920,36 +920,8 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event)
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;
if (sngisdn_force_down(ftdmchan) != FTDM_SUCCESS) {
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;
case 1:
@@ -1159,6 +1131,48 @@ static void sngisdn_process_restart_confirm(ftdm_channel_t *ftdmchan)
return;
}
static ftdm_status_t sngisdn_force_down(ftdm_channel_t *ftdmchan)
{
sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)ftdmchan->call_data;
ftdm_status_t status = FTDM_SUCCESS;
ftdm_log_chan(ftdmchan, FTDM_LOG_NOTICE, "Forcing channel to DOWN state (%s)\n", ftdm_channel_state2str(ftdmchan->state));
switch (ftdmchan->state) {
case FTDM_CHANNEL_STATE_DOWN:
/* Do nothing */
break;
case FTDM_CHANNEL_STATE_RESET:
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_DOWN);
break;
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 already waiting for usr to respond to SIGEVENT stop.
FreeTDM already scheduled a timout in case the User does respond to
SIGEVENT_STOP, no need to do anything here */
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;
default:
status = FTDM_FAIL;
}
return status;
}
void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
{
@@ -1171,12 +1185,12 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
sngisdn_span_data_t *signal_data = g_sngisdn_data.dchans[dChan].spans[1];
if (!signal_data) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART on unconfigured span (suId:%d)\n", suId);
ftdm_log(FTDM_LOG_CRIT, "Received RESTART CFM on unconfigured span (suId:%d)\n", suId);
return;
}
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Receved RESTART, but Restart Indicator IE not present\n");
if (rstEvnt->rstInd.eh.pres != PRSNT_NODEF && rstEvnt->rstInd.rstClass.pres != PRSNT_NODEF) {
ftdm_log(FTDM_LOG_DEBUG, "Received RESTART, but Restart Indicator IE not present\n");
return;
}
@@ -1233,24 +1247,101 @@ void sngisdn_process_rst_cfm (sngisdn_event_data_t *sngisdn_event)
}
/* The remote side sent us a RESTART Msg. Trillium automatically acks with RESTART ACK, but
we need to clear our call states if there is a call on this channel */
void sngisdn_process_rst_ind (sngisdn_event_data_t *sngisdn_event)
{
uint8_t chan_no = 0;
int16_t suId = sngisdn_event->suId;
int16_t dChan = sngisdn_event->dChan;
uint8_t ces = sngisdn_event->ces;
uint8_t evntType = sngisdn_event->evntType;
Rst *rstEvnt = NULL;
sngisdn_span_data_t *signal_data = NULL;
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
/* 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,
rstEvnt = &sngisdn_event->event.rstEvnt;
/* TODO: readjust this when NFAS is implemented as signal_data will not always be the first
* span for that d-channel */
signal_data = g_sngisdn_data.dchans[dChan].spans[1];
if (!signal_data) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on unconfigured span (suId:%d)\n", suId);
return;
}
ftdm_log(FTDM_LOG_DEBUG, "Processing RESTART IND (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");
if (!rstEvnt->rstInd.eh.pres || !rstEvnt->rstInd.rstClass.pres) {
ftdm_log(FTDM_LOG_DEBUG, "Received RESTART IND, but Restart Indicator IE not present\n");
return;
}
switch(rstEvnt->rstInd.rstClass.val) {
case IN_CL_INDCHAN: /* Indicated b-channel */
if (rstEvnt->chanId.eh.pres) {
if (rstEvnt->chanId.intType.val == IN_IT_BASIC) {
if (rstEvnt->chanId.infoChanSel.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.infoChanSel.val;
}
} else if (rstEvnt->chanId.intType.val == IN_IT_OTHER) {
if (rstEvnt->chanId.chanNmbSlotMap.pres == PRSNT_NODEF) {
chan_no = rstEvnt->chanId.chanNmbSlotMap.val[0];
}
}
}
if (!chan_no) {
ftdm_log(FTDM_LOG_CRIT, "Failed to determine channel from RESTART\n");
return;
}
break;
case IN_CL_SNGINT: /* Single interface */
case IN_CL_ALLINT: /* All interfaces */
/* In case restart class indicates all interfaces, we will duplicate
this event on each span associated to this d-channel in sngisdn_rcv_rst_cfm,
so treat it as a single interface anyway */
break;
default:
ftdm_log(FTDM_LOG_CRIT, "Invalid restart indicator class:%d\n", rstEvnt->rstInd.rstClass.val);
return;
}
if (chan_no) { /* For a single channel */
if (chan_no > ftdm_span_get_chan_count(signal_data->ftdm_span)) {
ftdm_log(FTDM_LOG_CRIT, "Received RESTART IND on invalid channel:%d\n", chan_no);
} else {
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_channel_t *ftdmchan = (ftdm_channel_t*)ftdm_iterator_current(curr);
if (ftdmchan->physical_chan_id == chan_no) {
sngisdn_force_down(ftdmchan);
}
}
ftdm_iterator_free(chaniter);
}
} else { /* for all channels */
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(signal_data->ftdm_span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_force_down((ftdm_channel_t*)ftdm_iterator_current(curr));
}
ftdm_iterator_free(chaniter);
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
@@ -708,7 +708,7 @@ void sngisdn_rcv_q921_ind(BdMngmt *status)
void sngisdn_rcv_q931_ind(InMngmt *status)
{
if (status->t.usta.alarm.cause == 287) {
get_memory_info();
sngisdn_get_memory_info();
return;
}
@@ -779,7 +779,6 @@ void sngisdn_rcv_cc_ind(CcMngmt *status)
void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
{
MsgLen mlen;
MsgLen i;
int16_t j;
Buffer *tmp;
Data *cptr;
@@ -802,7 +801,6 @@ void sngisdn_rcv_q931_trace(InMngmt *trc, Buffer *mBuf)
tmp = mBuf->b_cont;
cptr = tmp->b_rptr;
data = *cptr++;
i = 0;
for(j=0;j<mlen;j++) {
tdata[j]= data;
@@ -43,10 +43,53 @@ SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_descr, ftdm_sngisdn_progind_descr
SNGISDN_ENUM_NAMES(SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_STRINGS)
SNGISDN_STR2ENUM(ftdm_str2ftdm_sngisdn_progind_loc, ftdm_sngisdn_progind_loc2str, ftdm_sngisdn_progind_loc_t, SNGISDN_PROGIND_LOC_NAMES, SNGISDN_PROGIND_LOC_INVALID)
ftdm_status_t sngisdn_check_free_ids(void);
static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val);
static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val);
extern ftdm_sngisdn_data_t g_sngisdn_data;
void get_memory_info(void);
ftdm2trillium_t npi_codes[] = {
{FTDM_NPI_UNKNOWN, IN_NP_UNK},
{FTDM_NPI_ISDN, IN_NP_ISDN},
{FTDM_NPI_DATA, IN_NP_DATA},
{FTDM_NPI_TELEX, IN_NP_TELEX},
{FTDM_NPI_NATIONAL, IN_NP_NATIONAL},
{FTDM_NPI_PRIVATE, IN_NP_PRIVATE},
{FTDM_NPI_RESERVED, IN_NP_EXT},
};
ftdm2trillium_t ton_codes[] = {
{FTDM_TON_UNKNOWN, IN_TON_UNK},
{FTDM_TON_INTERNATIONAL, IN_TON_INT},
{FTDM_TON_NATIONAL, IN_TON_NAT},
{FTDM_TON_NETWORK_SPECIFIC, IN_TON_NETSPEC},
{FTDM_TON_SUBSCRIBER_NUMBER, IN_TON_SUB},
{FTDM_TON_ABBREVIATED_NUMBER, IN_TON_ABB},
{FTDM_TON_RESERVED, IN_TON_EXT},
};
static uint8_t get_trillium_val(ftdm2trillium_t *vals, uint8_t ftdm_val, uint8_t default_val)
{
ftdm2trillium_t *val = vals;
while(val++) {
if (val->ftdm_val == ftdm_val) {
return val->trillium_val;
}
}
return default_val;
}
static uint8_t get_ftdm_val(ftdm2trillium_t *vals, uint8_t trillium_val, uint8_t default_val)
{
ftdm2trillium_t *val = vals;
while(val++) {
if (val->trillium_val == trillium_val) {
return val->ftdm_val;
}
}
return default_val;
}
void clear_call_data(sngisdn_chan_data_t *sngisdn_info)
{
@@ -259,11 +302,11 @@ ftdm_status_t get_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
}
if (cdPtyNmb->nmbPlanId.pres == PRSNT_NODEF) {
caller_data->dnis.plan = cdPtyNmb->nmbPlanId.val;
caller_data->dnis.plan = get_ftdm_val(npi_codes, cdPtyNmb->nmbPlanId.val, IN_NP_UNK);
}
if (cdPtyNmb->typeNmb0.pres == PRSNT_NODEF) {
caller_data->dnis.type = cdPtyNmb->typeNmb0.val;
caller_data->dnis.type = get_ftdm_val(ton_codes, cdPtyNmb->typeNmb0.val, IN_TON_UNK);
}
if (cdPtyNmb->nmbDigits.pres == PRSNT_NODEF) {
@@ -283,11 +326,11 @@ ftdm_status_t get_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
}
if (redirNmb->nmbPlanId.pres == PRSNT_NODEF) {
caller_data->rdnis.plan = redirNmb->nmbPlanId.val;
caller_data->rdnis.plan = get_ftdm_val(npi_codes, redirNmb->nmbPlanId.val, IN_NP_UNK);
}
if (redirNmb->typeNmb.pres == PRSNT_NODEF) {
caller_data->rdnis.type = redirNmb->typeNmb.val;
caller_data->rdnis.type = get_ftdm_val(ton_codes, redirNmb->typeNmb.val, IN_TON_UNK);
}
if (redirNmb->nmbDigits.pres == PRSNT_NODEF) {
@@ -382,11 +425,13 @@ ftdm_status_t get_facility_ie_str(ftdm_channel_t *ftdmchan, uint8_t *data, uint8
ftdm_status_t get_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd)
{
uint8_t val;
if (!progInd->eh.pres) {
return FTDM_FAIL;
}
if (progInd->progDesc.pres) {
/* TODO: use get_ftdm_val function and table here */
switch (progInd->progDesc.val) {
case IN_PD_NOTETEISDN:
val = SNGISDN_PROGIND_DESCR_NETE_ISDN;
@@ -464,19 +509,11 @@ ftdm_status_t set_calling_num(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
cgPtyNmb->presInd0.val = caller_data->pres;
cgPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
if (caller_data->cid_num.plan >= FTDM_NPI_INVALID) {
cgPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
}
cgPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->cid_num.plan, IN_NP_UNK);
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
if (caller_data->cid_num.type >= FTDM_TON_INVALID) {
cgPtyNmb->typeNmb1.val = FTDM_TON_UNKNOWN;
} else {
cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
}
cgPtyNmb->typeNmb1.val = get_trillium_val(ton_codes, caller_data->cid_num.type, IN_TON_UNK);
cgPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cgPtyNmb->nmbDigits.len = len;
@@ -510,7 +547,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
val = FTDM_SCREENING_INVALID;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.screening_ind");
if ((string != NULL) && (*string)) {
if (!ftdm_strlen_zero(string)) {
val = ftdm_str2ftdm_screening(string);
}
@@ -527,7 +564,7 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
val = FTDM_PRES_INVALID;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.presentation_ind");
if ((string != NULL) && (*string)) {
if (!ftdm_strlen_zero(string)) {
val = ftdm_str2ftdm_presentation(string);
}
@@ -542,14 +579,14 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
val = FTDM_NPI_INVALID;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.npi");
if ((string != NULL) && (*string)) {
if (!ftdm_strlen_zero(string)) {
val = ftdm_str2ftdm_npi(string);
}
if (val == FTDM_NPI_INVALID) {
cgPtyNmb->nmbPlanId.val = caller_data->cid_num.plan;
} else {
cgPtyNmb->nmbPlanId.val = val;
cgPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, val, IN_NP_UNK);
}
cgPtyNmb->typeNmb1.pres = PRSNT_NODEF;
@@ -557,14 +594,14 @@ ftdm_status_t set_calling_num2(ftdm_channel_t *ftdmchan, CgPtyNmb *cgPtyNmb)
/* Type of Number */
val = FTDM_TON_INVALID;
string = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.cg_pty2.ton");
if ((string != NULL) && (*string)) {
if (!ftdm_strlen_zero(string)) {
val = ftdm_str2ftdm_ton(string);
}
if (val == FTDM_TON_INVALID) {
cgPtyNmb->typeNmb1.val = caller_data->cid_num.type;
} else {
cgPtyNmb->typeNmb1.val = val;
cgPtyNmb->typeNmb1.val = get_trillium_val(ton_codes, val, IN_TON_UNK);
}
return FTDM_SUCCESS;
}
@@ -577,21 +614,14 @@ ftdm_status_t set_called_num(ftdm_channel_t *ftdmchan, CdPtyNmb *cdPtyNmb)
if (!len) {
return FTDM_SUCCESS;
}
cdPtyNmb->eh.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
if (caller_data->dnis.plan >= FTDM_NPI_INVALID) {
cdPtyNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
cdPtyNmb->nmbPlanId.val = caller_data->dnis.plan;
}
cdPtyNmb->typeNmb0.pres = PRSNT_NODEF;
if (caller_data->dnis.type >= FTDM_TON_INVALID) {
cdPtyNmb->typeNmb0.val = FTDM_TON_UNKNOWN;
} else {
cdPtyNmb->typeNmb0.val = caller_data->dnis.type;
}
cdPtyNmb->eh.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.pres = PRSNT_NODEF;
cdPtyNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->dnis.plan, IN_NP_UNK);
cdPtyNmb->typeNmb0.pres = PRSNT_NODEF;
cdPtyNmb->typeNmb0.val = get_trillium_val(ton_codes, caller_data->dnis.type, IN_TON_UNK);
cdPtyNmb->nmbDigits.pres = PRSNT_NODEF;
cdPtyNmb->nmbDigits.len = len;
@@ -612,18 +642,10 @@ ftdm_status_t set_redir_num(ftdm_channel_t *ftdmchan, RedirNmb *redirNmb)
redirNmb->eh.pres = PRSNT_NODEF;
redirNmb->nmbPlanId.pres = PRSNT_NODEF;
if (caller_data->rdnis.plan >= FTDM_NPI_INVALID) {
redirNmb->nmbPlanId.val = FTDM_NPI_UNKNOWN;
} else {
redirNmb->nmbPlanId.val = caller_data->rdnis.plan;
}
redirNmb->nmbPlanId.val = get_trillium_val(npi_codes, caller_data->rdnis.plan, IN_NP_UNK);
redirNmb->typeNmb.pres = PRSNT_NODEF;
if (caller_data->rdnis.type >= FTDM_TON_INVALID) {
redirNmb->typeNmb.val = FTDM_TON_UNKNOWN;
} else {
redirNmb->typeNmb.val = caller_data->rdnis.type;
}
redirNmb->typeNmb.val = get_trillium_val(ton_codes, caller_data->rdnis.type, IN_TON_UNK);
redirNmb->nmbDigits.pres = PRSNT_NODEF;
redirNmb->nmbDigits.len = len;
@@ -743,7 +765,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
int loc = prog_ind.loc;
str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.prog_ind.descr");
if (str && *str) {
if (!ftdm_strlen_zero(str)) {
/* User wants to override progress indicator */
descr = ftdm_str2ftdm_sngisdn_progind_descr(str);
}
@@ -754,7 +776,7 @@ ftdm_status_t set_prog_ind_ie(ftdm_channel_t *ftdmchan, ProgInd *progInd, ftdm_s
}
str = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "isdn.prog_ind.loc");
if (str && *str) {
if (!ftdm_strlen_zero(str)) {
loc = ftdm_str2ftdm_sngisdn_progind_loc(str);
}
if (loc == SNGISDN_PROGIND_LOC_INVALID) {
@@ -1062,25 +1084,27 @@ ftdm_status_t sngisdn_check_free_ids(void)
return FTDM_SUCCESS;
}
void get_memory_info(void)
void sngisdn_get_memory_info(void)
{
U32 availmen = 0;
SRegInfoShow(S_REG, &availmen);
return;
}
uint8_t sngisdn_get_infoTranCap_from_user(ftdm_bearer_cap_t bearer_capability)
{
switch(bearer_capability) {
case FTDM_BEARER_CAP_SPEECH:
return IN_ITC_SPEECH;
case FTDM_BEARER_CAP_64K_UNRESTRICTED:
case FTDM_BEARER_CAP_UNRESTRICTED:
return IN_ITC_UNRDIG;
case FTDM_BEARER_CAP_3_1KHZ_AUDIO:
return IN_ITC_A31KHZ;
case FTDM_BEARER_CAP_INVALID:
return IN_ITC_SPEECH;
/* Do not put a default case here, so we can see compile warnings if we have unhandled cases */
default:
return IN_ITC_SPEECH;
}
return FTDM_BEARER_CAP_SPEECH;
}
@@ -1096,7 +1120,8 @@ uint8_t sngisdn_get_usrInfoLyr1Prot_from_user(ftdm_user_layer1_prot_t layer1_pro
return IN_UIL1_G711ALAW;
case FTDM_USER_LAYER1_PROT_INVALID:
return IN_UIL1_G711ULAW;
/* Do not put a default case here, so we can see compile warnings if we have unhandled cases */
default:
return IN_UIL1_G711ULAW;
}
return IN_UIL1_G711ULAW;
}
@@ -1105,9 +1130,9 @@ ftdm_bearer_cap_t sngisdn_get_infoTranCap_from_stack(uint8_t bearer_capability)
{
switch(bearer_capability) {
case IN_ITC_SPEECH:
return FTDM_BEARER_CAP_SPEECH;
return FTDM_BEARER_CAP_SPEECH;
case IN_ITC_UNRDIG:
return FTDM_BEARER_CAP_64K_UNRESTRICTED;
return FTDM_BEARER_CAP_UNRESTRICTED;
case IN_ITC_A31KHZ:
return FTDM_BEARER_CAP_3_1KHZ_AUDIO;
default:
@@ -1131,7 +1156,7 @@ ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_stack(uint8_t layer1_pr
return FTDM_USER_LAYER1_PROT_ULAW;
}
void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span)
ftdm_status_t sngisdn_show_l1_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span)
{
L1Mngmt sts;
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
@@ -1169,11 +1194,11 @@ void sngisdn_print_phy_stats(ftdm_stream_handle_t *stream, ftdm_span_t *span)
stream->write_function(stream, " TX Errors Details");
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, "Aborted:\t%u\tFifo:\t\t%u\tCarrier:\t%u\n", sts.t.sts.tx_aborted_errors, sts.t.sts.tx_fifo_errors, sts.t.sts.tx_carrier_errors);
return;
return FTDM_SUCCESS;
}
void sngisdn_print_span(ftdm_stream_handle_t *stream, ftdm_span_t *span)
ftdm_status_t sngisdn_show_span(ftdm_stream_handle_t *stream, ftdm_span_t *span)
{
ftdm_signaling_status_t sigstatus;
ftdm_alarm_flag_t alarmbits;
@@ -1188,18 +1213,18 @@ void sngisdn_print_span(ftdm_stream_handle_t *stream, ftdm_span_t *span)
stream->write_function(stream, "span:%s physical:%s signalling:%s\n",
span->name, alarmbits ? "ALARMED" : "OK",
ftdm_signaling_status2str(sigstatus));
return;
return FTDM_SUCCESS;
}
void sngisdn_print_spans(ftdm_stream_handle_t *stream)
ftdm_status_t sngisdn_show_spans(ftdm_stream_handle_t *stream)
{
int i;
for(i=1;i<=MAX_L1_LINKS;i++) {
if (g_sngisdn_data.spans[i]) {
sngisdn_print_span(stream, g_sngisdn_data.spans[i]->ftdm_span);
sngisdn_show_span(stream, g_sngisdn_data.spans[i]->ftdm_span);
}
}
return;
return FTDM_SUCCESS;
}
ftdm_status_t sngisdn_add_var(sngisdn_chan_data_t *sngisdn_info, const char* var, const char* val)
@@ -334,11 +334,12 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
switch(ieId) {
case PROT_Q931_IE_BEARER_CAP:
{
uint8_t codingStandard, infTransferCap, transferMode, infTransferRate, usrL1Prot;
uint8_t codingStandard, infTransferCap, infTransferRate, usrL1Prot;
/*uint8_t transferMode;*/
codingStandard = get_bits(OCTET(3),6,7);
infTransferCap = get_bits(OCTET(3),1,5);
transferMode = get_bits(OCTET(4),6,7);
/*transferMode = get_bits(OCTET(4),6,7);*/
infTransferRate = get_bits(OCTET(4),1,5);
usrL1Prot = get_bits(OCTET(5),1,5);
@@ -404,8 +405,9 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
uint8_t infoChannelSelection=0;
uint8_t prefExclusive=0;
uint8_t ifaceIdPresent=0;
uint8_t ifaceIdentifier = 0; /* octet_3_1 */
uint8_t chanType=0, numberMap=0, codingStandard=0;
/* uint8_t ifaceIdentifier = 0; */ /* octet_3_1 */
uint8_t chanType=0, numberMap=0;
/* uint8_t codingStandard=0; */
uint8_t channelNo = 0;
infoChannelSelection = get_bits(OCTET(3),1,2);
@@ -413,15 +415,15 @@ uint32_t sngisdn_decode_ie(char *str, uint32_t *str_len, uint8_t current_codeset
ifaceIdPresent = get_bits(OCTET(3),7,7);
if (ifaceIdPresent) {
ifaceIdentifier= get_bits(OCTET(4),1,7);
/*ifaceIdentifier= get_bits(OCTET(4),1,7);*/
chanType = get_bits(OCTET(5),1,4);
numberMap = get_bits(OCTET(5),5,5);
codingStandard = get_bits(OCTET(5),6,7);
/*codingStandard = get_bits(OCTET(5),6,7);*/
channelNo = get_bits(OCTET(6),1,7);
} else {
chanType = get_bits(OCTET(4),1,4);
numberMap = get_bits(OCTET(4),5,5);
codingStandard = get_bits(OCTET(4),6,7);
/*codingStandard = get_bits(OCTET(4),6,7);*/
channelNo = get_bits(OCTET(5),1,7);
}
@@ -755,7 +757,7 @@ void print_hex_dump(char* str, uint32_t *str_len, uint8_t* data, uint32_t index_
{
uint32_t k;
*str_len += sprintf(&str[*str_len], " [ ");
for(k=index_start; k <= index_end; k++) {
for(k=index_start; k < index_end; k++) {
if (k && !(k%32)) {
*str_len += sprintf(&str[*str_len], "\n ");
}
@@ -33,12 +33,14 @@
/* INCLUDE ********************************************************************/
#include "ftmod_sangoma_ss7_main.h"
/******************************************************************************/
/* DEFINES ********************************************************************/
/******************************************************************************/
/* GLOBALS ********************************************************************/
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
@@ -79,14 +81,14 @@ ftdm_status_t handle_olm_msg(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt)
{
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
sngss7_chan_data_t *sngss7_info = NULL;
ftdm_channel_t *ftdmchan = NULL;
char nadi[2];
SS7_FUNC_TRACE_ENTER(__FUNCTION__);
memset(nadi, '\0', sizeof(nadi));
/* get the ftdmchan and ss7_chan_data from the circuit */
@@ -185,17 +187,11 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
SS7_INFO_CHAN(ftdmchan,"No Called party (DNIS) information in IAM!%s\n", " ");
}
/* fill in rdnis information*/
if (siConEvnt->redirgNum.eh.pres) {
if (siConEvnt->redirgNum.addrSig.pres) {
/* fill in the rdnis digits */
copy_tknStr_from_sngss7(siConEvnt->redirgNum.addrSig,
ftdmchan->caller_data.rdnis.digits,
siConEvnt->cgPtyNum.oddEven);
}
} else {
SS7_DEBUG_CHAN(ftdmchan,"No RDNIS party information in IAM!%s\n", " ");
}
copy_redirgNum_from_sngss7(ftdmchan, &siConEvnt->redirgNum);
copy_genNmb_from_sngss7(ftdmchan, &siConEvnt->genNmb);
copy_cgPtyCat_from_sngss7(ftdmchan, &siConEvnt->cgPtyCat);
/* fill in the TMR/bearer capability */
if (siConEvnt->txMedReq.eh.pres) {
@@ -214,6 +210,10 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
sprintf(nadi, "%d", siConEvnt->cdPtyNum.natAddrInd.val);
sngss7_add_var(sngss7_info, "ss7_cld_nadi", nadi);
if (sngss7_info->circuit->transparent_iam) {
sngss7_save_iam(ftdmchan, siConEvnt);
}
/* check if a COT test is requested */
if ((siConEvnt->natConInd.eh.pres) &&
(siConEvnt->natConInd.contChkInd.pres) &&
@@ -237,7 +237,6 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ
siConEvnt->cgPtyNum.natAddrInd.val,
ftdmchan->caller_data.dnis.digits,
siConEvnt->cdPtyNum.natAddrInd.val);
} /* if (channel is usable */
break;
@@ -490,6 +489,47 @@ ftdm_status_t handle_con_sta(uint32_t suInstId, uint32_t spInstId, uint32_t circ
case (SUBDIRNUM):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx SUB-DIR\n", sngss7_info->circuit->cic);
break;
#ifdef SANGOMA_SPIROU
case (CHARGE_ACK):
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx TXA\n", sngss7_info->circuit->cic);
break;
case (CHARGE_UNIT):
{
uint32_t charging_unit = 0;
uint32_t msg_num = 0;
char val[3];
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx ITX\n", sngss7_info->circuit->cic);
memset(val, '\0', sizeof(val));
if (siCnStEvnt->chargUnitNum.eh.pres == PRSNT_NODEF &&
siCnStEvnt->chargUnitNum.chargUnitNum.pres == PRSNT_NODEF) {
charging_unit = siCnStEvnt->chargUnitNum.chargUnitNum.val;
}
if (siCnStEvnt->msgNum.eh.pres == PRSNT_NODEF &&
siCnStEvnt->msgNum.msgNum.pres == PRSNT_NODEF) {
msg_num = siCnStEvnt->msgNum.msgNum.val;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Charging Unit:%d Msg Num:%d\n", charging_unit, msg_num);
sprintf(val, "%d", charging_unit);
sngss7_add_var(sngss7_info, "ss7_itx_charge_unit", val);
sprintf(val, "%d", msg_num);
sngss7_add_var(sngss7_info, "ss7_itx_msg_num", val);
if (sngss7_info->circuit->itx_auto_reply) {
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_INFO, "Auto-reply with TXA msg\n");
ft_to_sngss7_txa (ftdmchan);
}
}
break;
#endif
/**************************************************************************/
default:
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Rx Unknown Msg\n", sngss7_info->circuit->cic);
@@ -532,7 +572,7 @@ ftdm_status_t handle_con_cfm(uint32_t suInstId, uint32_t spInstId, uint32_t circ
/* go to UP */
ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_UP);
break;
/**************************************************************************/
case FTDM_CHANNEL_STATE_DIALING:
@@ -609,6 +649,7 @@ ftdm_channel_command(ftdmchan, FTDM_COMMAND_DISABLE_LOOP, NULL);
break;
/**************************************************************************/
case FTDM_CHANNEL_STATE_RING:
case FTDM_CHANNEL_STATE_RINGING:
case FTDM_CHANNEL_STATE_PROGRESS:
case FTDM_CHANNEL_STATE_PROGRESS_MEDIA:
case FTDM_CHANNEL_STATE_UP:
@@ -42,6 +42,7 @@
static sng_isup_event_interface_t sng_event;
static ftdm_io_interface_t g_ftdm_sngss7_interface;
ftdm_sngss7_data_t g_ftdm_sngss7_data;
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
@@ -509,11 +510,6 @@ ftdm_status_t ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan)
SS7_DEBUG_CHAN(ftdmchan, "ftmod_sangoma_ss7 processing state %s\n", ftdm_channel_state2str (ftdmchan->state));
#if 0
/* clear the state change flag...since we might be setting a new state */
ftdm_channel_complete_state(ftdmchan);
#endif
/*check what state we are supposed to be in */
switch (ftdmchan->state) {
/**************************************************************************/
@@ -60,6 +60,13 @@
#define MAX_SIZEOF_SUBADDR_IE 24 /* as per Q931 4.5.9 */
typedef struct ftdm2trillium
{
uint8_t ftdm_val;
uint8_t trillium_val;
}ftdm2trillium_t;
typedef enum {
SNGSS7_CON_IND_EVENT = 0,
SNGSS7_CON_CFM_EVENT,
@@ -320,8 +327,19 @@ typedef struct sng_isup_ckt {
uint32_t clg_nadi;
uint32_t cld_nadi;
uint8_t rdnis_nadi;
/* Generic Number defaults */
uint8_t gn_nmbqual; /* Number Qualifier */
uint8_t gn_nadi; /* Nature of Address indicator */
uint8_t gn_screen_ind; /* Screening Indicator */
uint8_t gn_pres_ind; /* Presentation Indicator */
uint8_t gn_npi; /* Numbering Plan Indicator */
uint8_t gn_num_inc_ind; /* Number Incomplete Indicator */
/* END - Generic Number defaults */
uint32_t min_digits;
uint8_t itx_auto_reply;
uint8_t transparent_iam;
void *obj;
uint16_t t3;
uint16_t t12;
@@ -389,6 +407,7 @@ typedef struct sng_ss7_cfg {
uint32_t procId;
char license[MAX_PATH];
char signature[MAX_PATH];
uint32_t transparent_iam_max_size;
uint32_t flags;
sng_relay_t relay[MAX_RELAY_CHANNELS+1];
sng_mtp1_link_t mtp1Link[MAX_MTP_LINKS+1];
@@ -728,6 +747,9 @@ void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_itx (ftdm_channel_t * ftdmchan);
void ft_to_sngss7_txa (ftdm_channel_t * ftdmchan);
/* in ftmod_sangoma_ss7_in.c */
void sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt);
@@ -745,6 +767,10 @@ void sngss7_resm_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiR
void sngss7_susp_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiSuspEvnt *siSuspEvnt);
void sngss7_ssp_sta_cfm(uint32_t infId);
ftdm_status_t sngss7_bufferzero_iam(SiConEvnt *siConEvnt);
ftdm_status_t sngss7_retrieve_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt);
ftdm_status_t sngss7_save_iam(ftdm_channel_t *ftdmchan, SiConEvnt *siConEvnt);
/* in ftmod_sangoma_ss7_handle.c */
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);
@@ -785,12 +811,21 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa
ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data);
/* in ftmod_sangoma_ss7_support.c */
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);
ftdm_status_t copy_cgPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum);
ftdm_status_t copy_cgPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyNum *cgPtyNum);
ftdm_status_t copy_cdPtyNum_from_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum);
ftdm_status_t copy_cdPtyNum_to_sngss7(ftdm_channel_t *ftdmchan, SiCdPtyNum *cdPtyNum);
ftdm_status_t copy_redirgNum_to_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum);
ftdm_status_t copy_redirgNum_from_sngss7(ftdm_channel_t *ftdmchan, SiRedirNum *redirgNum);
ftdm_status_t copy_genNmb_to_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb);
ftdm_status_t copy_genNmb_from_sngss7(ftdm_channel_t *ftdmchan, SiGenNum *genNmb);
ftdm_status_t copy_cgPtyCat_to_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat);
ftdm_status_t copy_cgPtyCat_from_sngss7(ftdm_channel_t *ftdmchan, SiCgPtyCat *cgPtyCat);
ftdm_status_t copy_accTrnspt_to_sngss7(ftdm_channel_t *ftdmchan, SiAccTrnspt *accTrnspt);
ftdm_status_t copy_natConInd_to_sngss7(ftdm_channel_t *ftdmchan, SiNatConInd *natConInd);
ftdm_status_t copy_fwdCallInd_to_sngss7(ftdm_channel_t *ftdmchan, SiFwdCallInd *fwdCallInd);
ftdm_status_t copy_txMedReq_to_sngss7(ftdm_channel_t *ftdmchan, SiTxMedReq *txMedReq);
ftdm_status_t copy_usrServInfoA_to_sngss7(ftdm_channel_t *ftdmchan, SiUsrServInfo *usrServInfoA);
ftdm_status_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
ftdm_status_t append_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven);
@@ -36,10 +36,8 @@
/******************************************************************************/
/* DEFINES ********************************************************************/
/******************************************************************************/
/* GLOBALS ********************************************************************/
/******************************************************************************/
/* PROTOTYPES *****************************************************************/
void ft_to_sngss7_iam(ftdm_channel_t * ftdmchan);
@@ -66,243 +64,74 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan);
void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan);
/******************************************************************************/
/* FUNCTIONS ******************************************************************/
void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
const char *clg_nadi = NULL;
const char *cld_nadi = NULL;
const char *clg_subAddr = NULL;
const char *cld_subAddr = NULL;
char subAddrIE[MAX_SIZEOF_SUBADDR_IE];
{
SiConEvnt iam;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
sngss7_info->suInstId = get_unique_id ();
sngss7_info->spInstId = 0;
sngss7_info->spId = 1;
memset (&iam, 0x0, sizeof (iam));
/* copy down the nature of connection indicators */
iam.natConInd.eh.pres = PRSNT_NODEF;
iam.natConInd.satInd.pres = PRSNT_NODEF;
iam.natConInd.satInd.val = 0; /* no satellite circuit */
iam.natConInd.contChkInd.pres = PRSNT_NODEF;
iam.natConInd.contChkInd.val = CONTCHK_NOTREQ;
iam.natConInd.echoCntrlDevInd.pres = PRSNT_NODEF;
iam.natConInd.echoCntrlDevInd.val = ECHOCDEV_INCL;
/* copy down the forward call indicators */
iam.fwdCallInd.eh.pres = PRSNT_NODEF;
iam.fwdCallInd.natIntCallInd.pres = PRSNT_NODEF;
iam.fwdCallInd.natIntCallInd.val = 0x00;
iam.fwdCallInd.end2EndMethInd.pres = PRSNT_NODEF;
iam.fwdCallInd.end2EndMethInd.val = E2EMTH_NOMETH;
iam.fwdCallInd.intInd.pres = PRSNT_NODEF;
iam.fwdCallInd.intInd.val = INTIND_NOINTW;
iam.fwdCallInd.end2EndInfoInd.pres = PRSNT_NODEF;
iam.fwdCallInd.end2EndInfoInd.val = E2EINF_NOINFO;
iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF;
iam.fwdCallInd.isdnUsrPrtInd.val = ISUP_USED;
iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF;
iam.fwdCallInd.isdnUsrPrtPrfInd.val = PREF_PREFAW;
iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF;
iam.fwdCallInd.isdnAccInd.val = ISDNACC_ISDN;
iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF;
iam.fwdCallInd.sccpMethInd.val = SCCPMTH_NOIND;
/* copy down the calling number information */
iam.cgPtyCat.eh.pres = PRSNT_NODEF;
iam.cgPtyCat.cgPtyCat.pres = PRSNT_NODEF;
iam.cgPtyCat.cgPtyCat.val = CAT_ORD; /* ordinary suscriber */
/* copy down the transmission medium requirements */
iam.txMedReq.eh.pres = PRSNT_NODEF;
iam.txMedReq.trMedReq.pres = PRSNT_NODEF;
iam.txMedReq.trMedReq.val = ftdmchan->caller_data.bearer_capability;
if ((g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS88) ||
(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS92) ||
(g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].switchType == LSI_SW_ANS95)) {
/* include only if we're running ANSI */
iam.fwdCallInd.transCallNInd.pres = PRSNT_NODEF;
iam.fwdCallInd.transCallNInd.val = 0x0;
iam.usrServInfoA.eh.pres = PRSNT_NODEF;
iam.usrServInfoA.infoTranCap.pres = PRSNT_NODEF;
switch (ftdmchan->caller_data.bearer_capability) {
/**********************************************************************/
case (FTDM_BEARER_CAP_SPEECH):
iam.usrServInfoA.infoTranCap.val = 0x0; /* speech as per ATIS-1000113.3.2005 */
break;
/**********************************************************************/
case (FTDM_BEARER_CAP_64K_UNRESTRICTED):
iam.usrServInfoA.infoTranCap.val = 0x8; /* unrestricted digital as per ATIS-1000113.3.2005 */
break;
/**********************************************************************/
case (FTDM_BEARER_CAP_3_1KHZ_AUDIO):
iam.usrServInfoA.infoTranCap.val = 0x10; /* 3.1kHz audio as per ATIS-1000113.3.2005 */
break;
/**********************************************************************/
default:
SS7_ERROR_CHAN(ftdmchan, "Unknown Bearer capability falling back to speech%s\n", " ");
iam.usrServInfoA.infoTranCap.val = 0x0; /* speech as per ATIS-1000113.3.2005 */
break;
/**********************************************************************/
} /* switch (ftdmchan->caller_data.bearer_capability) */
iam.usrServInfoA.cdeStand.pres = PRSNT_NODEF;
iam.usrServInfoA.cdeStand.val = 0x0; /* ITU-T standardized coding */
iam.usrServInfoA.tranMode.pres = PRSNT_NODEF;
iam.usrServInfoA.tranMode.val = 0x0; /* circuit mode */
iam.usrServInfoA.infoTranRate0.pres = PRSNT_NODEF;
iam.usrServInfoA.infoTranRate0.val = 0x10; /* 64kbps origination to destination */
iam.usrServInfoA.infoTranRate1.pres = PRSNT_NODEF;
iam.usrServInfoA.infoTranRate1.val = 0x10; /* 64kbps destination to origination */
iam.usrServInfoA.chanStruct.pres = PRSNT_NODEF;
iam.usrServInfoA.chanStruct.val = 0x1; /* 8kHz integrity */
iam.usrServInfoA.config.pres = PRSNT_NODEF;
iam.usrServInfoA.config.val = 0x0; /* point to point configuration */
iam.usrServInfoA.establish.pres = PRSNT_NODEF;
iam.usrServInfoA.establish.val = 0x0; /* on demand */
iam.usrServInfoA.symmetry.pres = PRSNT_NODEF;
iam.usrServInfoA.symmetry.val = 0x0; /* bi-directional symmetric */
iam.usrServInfoA.usrInfLyr1Prot.pres = PRSNT_NODEF;
iam.usrServInfoA.usrInfLyr1Prot.val = 0x2; /* G.711 ulaw */
iam.usrServInfoA.rateMultiplier.pres = PRSNT_NODEF;
iam.usrServInfoA.rateMultiplier.val = 0x1; /* 1x rate multipler */
} /* if ANSI */
/* copy down the called number information */
copy_cdPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cdPtyNum);
/* copy down the calling number information */
copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum);
/* check if the user would like a custom NADI value for the calling Pty Num */
clg_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_nadi");
if ((clg_nadi != NULL) && (*clg_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling NADI value \"%s\"\n", clg_nadi);
iam.cgPtyNum.natAddrInd.val = atoi(clg_nadi);
if (sngss7_info->circuit->transparent_iam &&
sngss7_retrieve_iam(ftdmchan, &iam) == FTDM_SUCCESS) {
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM (Transparent)\n", sngss7_info->circuit->cic);
} else {
iam.cgPtyNum.natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].clg_nadi;
SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLG, using \"%d\"\n", iam.cgPtyNum.natAddrInd.val);
}
cld_nadi = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_nadi");
if ((cld_nadi != NULL) && (*cld_nadi)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called NADI value \"%s\"\n", cld_nadi);
iam.cdPtyNum.natAddrInd.val = atoi(cld_nadi);
} else {
iam.cdPtyNum.natAddrInd.val = g_ftdm_sngss7_data.cfg.isupCkt[sngss7_info->circuit->id].cld_nadi;
SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found for CLD, using \"%d\"\n", iam.cdPtyNum.natAddrInd.val);
}
/* Nature of Connection Indicators */
copy_natConInd_to_sngss7(ftdmchan, &iam.natConInd);
/* check if the user would like us to send a clg_sub-address */
clg_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_clg_subaddr");
if ((clg_subAddr != NULL) && (*clg_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Calling Sub-Address value \"%s\"\n", clg_subAddr);
/* Forward Call Indicators */
copy_fwdCallInd_to_sngss7(ftdmchan, &iam.fwdCallInd);
/* Transmission medium requirements */
copy_txMedReq_to_sngss7(ftdmchan, &iam.txMedReq);
/* User Service Info A */
copy_usrServInfoA_to_sngss7(ftdmchan, &iam.usrServInfoA);
/* clean out the subAddrIE */
memset(subAddrIE, 0x0, sizeof(subAddrIE));
/* check the first character in the sub-address to see what type of encoding to use */
switch (clg_subAddr[0]) {
case '0': /* NSAP */
encode_subAddrIE_nsap(&clg_subAddr[1], subAddrIE, SNG_CALLING);
break;
case '1': /* national variant */
encode_subAddrIE_nat(&clg_subAddr[1], subAddrIE, SNG_CALLING);
break;
default:
SS7_ERROR_CHAN(ftdmchan,"Invalid Calling Sub-Address encoding requested: %c\n", clg_subAddr[0]);
break;
} /* switch (cld_subAddr[0]) */
/* if subaddIE is still empty don't copy it in */
if (subAddrIE[0] != '0') {
/* check if the clg_subAddr has already been added */
if (iam.accTrnspt.eh.pres == PRSNT_NODEF) {
/* append the subAddrIE */
memcpy(&iam.accTrnspt.infoElmts.val[iam.accTrnspt.infoElmts.len], subAddrIE, (subAddrIE[1] + 2));
iam.accTrnspt.infoElmts.len = iam.accTrnspt.infoElmts.len +subAddrIE[1] + 2;
} else {
/* fill in from the beginning */
iam.accTrnspt.eh.pres = PRSNT_NODEF;
iam.accTrnspt.infoElmts.pres = PRSNT_NODEF;
memcpy(iam.accTrnspt.infoElmts.val, subAddrIE, (subAddrIE[1] + 2));
iam.accTrnspt.infoElmts.len = subAddrIE[1] + 2;
} /* if (iam.accTrnspt.eh.pres */
} /* if (subAddrIE[0] != '0') */
}
copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
/* check if the user would like us to send a cld_sub-address */
cld_subAddr = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_cld_subaddr");
if ((cld_subAddr != NULL) && (*cld_subAddr)) {
SS7_DEBUG_CHAN(ftdmchan,"Found user supplied Called Sub-Address value \"%s\"\n", cld_subAddr);
/* Called Number information */
copy_cdPtyNum_to_sngss7(ftdmchan, &iam.cdPtyNum);
/* clean out the subAddrIE */
memset(subAddrIE, 0x0, sizeof(subAddrIE));
/* Calling Number information */
copy_cgPtyNum_to_sngss7(ftdmchan, &iam.cgPtyNum);
/* check the first character in the sub-address to see what type of encoding to use */
switch (cld_subAddr[0]) {
case '0': /* NSAP */
encode_subAddrIE_nsap(&cld_subAddr[1], subAddrIE, SNG_CALLED);
break;
case '1': /* national variant */
encode_subAddrIE_nat(&cld_subAddr[1], subAddrIE, SNG_CALLED);
break;
default:
SS7_ERROR_CHAN(ftdmchan,"Invalid Called Sub-Address encoding requested: %c\n", cld_subAddr[0]);
break;
} /* switch (cld_subAddr[0]) */
/* Generic Number information */
copy_genNmb_to_sngss7(ftdmchan, &iam.genNmb);
/* if subaddIE is still empty don't copy it in */
if (subAddrIE[0] != '0') {
/* check if the cld_subAddr has already been added */
if (iam.accTrnspt.eh.pres == PRSNT_NODEF) {
/* append the subAddrIE */
memcpy(&iam.accTrnspt.infoElmts.val[iam.accTrnspt.infoElmts.len], subAddrIE, (subAddrIE[1] + 2));
iam.accTrnspt.infoElmts.len = iam.accTrnspt.infoElmts.len +subAddrIE[1] + 2;
} else {
/* fill in from the beginning */
iam.accTrnspt.eh.pres = PRSNT_NODEF;
iam.accTrnspt.infoElmts.pres = PRSNT_NODEF;
memcpy(iam.accTrnspt.infoElmts.val, subAddrIE, (subAddrIE[1] + 2));
iam.accTrnspt.infoElmts.len = subAddrIE[1] + 2;
} /* if (iam.accTrnspt.eh.pres */
} /* if (subAddrIE[0] != '0') */
} /* if ((cld_subAddr != NULL) && (*cld_subAddr)) */
/* Calling Party's Category */
copy_cgPtyCat_to_sngss7(ftdmchan, &iam.cgPtyCat);
/* Redirecting Number */
copy_redirgNum_to_sngss7(ftdmchan, &iam.redirgNum);
/* Access Transport */
copy_accTrnspt_to_sngss7(ftdmchan, &iam.accTrnspt);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.cid_num.digits,
iam.cgPtyNum.natAddrInd.val,
ftdmchan->caller_data.dnis.digits,
iam.cdPtyNum.natAddrInd.val);
}
sng_cc_con_request (sngss7_info->spId,
sngss7_info->suInstId,
sngss7_info->spInstId,
sngss7_info->circuit->id,
&iam,
sngss7_info->circuit->id,
&iam,
0);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx IAM clg = \"%s\" (NADI=%d), cld = \"%s\" (NADI=%d)\n",
sngss7_info->circuit->cic,
ftdmchan->caller_data.cid_num.digits,
iam.cgPtyNum.natAddrInd.val,
ftdmchan->caller_data.dnis.digits,
iam.cdPtyNum.natAddrInd.val);
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@@ -339,7 +168,7 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
acm.bckCallInd.echoCtrlDevInd.val = 0x1;
break;
/**********************************************************************/
case (FTDM_BEARER_CAP_64K_UNRESTRICTED):
case (FTDM_BEARER_CAP_UNRESTRICTED):
acm.bckCallInd.echoCtrlDevInd.val = 0x0;
break;
/**********************************************************************/
@@ -382,7 +211,6 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan)
return;
}
/******************************************************************************/
void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan)
{
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
@@ -892,6 +720,69 @@ void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan)
return;
}
/* French SPIROU send Charge Unit */
/* No one calls this function yet, but it has been implemented to complement TXA messages */
void ft_to_sngss7_itx (ftdm_channel_t * ftdmchan)
{
#ifndef SANGOMA_SPIROU
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "ITX message not supported!, please update your libsng_ss7\n");
#else
const char* var = NULL;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SiCnStEvnt itx;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
memset (&itx, 0x0, sizeof (itx));
itx.msgNum.eh.pres = PRSNT_NODEF;
itx.msgNum.msgNum.pres = PRSNT_NODEF;
var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_itx_msg_num");
if (!ftdm_strlen_zero(var)) {
itx.msgNum.msgNum.val = atoi(var);
} else {
itx.msgNum.msgNum.val = 0x1;
}
itx.chargUnitNum.eh.pres = PRSNT_NODEF;
itx.chargUnitNum.chargUnitNum.pres = PRSNT_NODEF;
var = ftdm_usrmsg_get_var(ftdmchan->usrmsg, "ss7_itx_charge_unit");
if (!ftdm_strlen_zero(var)) {
itx.chargUnitNum.chargUnitNum.val = atoi(var);
} else {
itx.chargUnitNum.chargUnitNum.val = 0x1;
}
ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "ITX Charging Unit:%d Msg Num:%d\n", itx.chargUnitNum.chargUnitNum.val, itx.msgNum.msgNum.val);
sng_cc_con_status (1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &itx, CHARGE_UNIT);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx ITX\n", sngss7_info->circuit->cic);
#endif
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/* French SPIROU send Charging Acknowledgement */
void ft_to_sngss7_txa (ftdm_channel_t * ftdmchan)
{
#ifndef SANGOMA_SPIROU
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
ftdm_log_chan_msg(ftdmchan, FTDM_LOG_CRIT, "TXA message not supported!, please update your libsng_ss7\n");
#else
SiCnStEvnt txa;
sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;
SS7_FUNC_TRACE_ENTER (__FUNCTION__);
memset (&txa, 0x0, sizeof(txa));
sng_cc_con_status(1, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &txa, CHARGE_ACK);
SS7_INFO_CHAN(ftdmchan,"[CIC:%d]Tx TXA\n", sngss7_info->circuit->cic);
#endif
SS7_FUNC_TRACE_EXIT (__FUNCTION__);
return;
}
/******************************************************************************/
/* For Emacs:
File diff suppressed because it is too large. Load diff
@@ -124,6 +124,8 @@ typedef struct sng_ccSpan
uint32_t cld_nadi;
uint32_t rdnis_nadi;
uint32_t min_digits;
uint8_t itx_auto_reply;
uint8_t transparent_iam;
uint32_t t3;
uint32_t t12;
uint32_t t13;
@@ -465,6 +467,9 @@ static int ftmod_ss7_parse_sng_gen(ftdm_conf_node_t *sng_gen)
SS7_DEBUG("Found license file = %s\n", g_ftdm_sngss7_data.cfg.license);
SS7_DEBUG("Found signature file = %s\n", g_ftdm_sngss7_data.cfg.signature);
/**********************************************************************/
} else if (!strcasecmp(parm->var, "transparent_iam_max_size")) {
g_ftdm_sngss7_data.cfg.transparent_iam_max_size = atoi(parm->val);
SS7_DEBUG("Found a transparent_iam max size = %d\n", g_ftdm_sngss7_data.cfg.transparent_iam_max_size);
} else {
/**********************************************************************/
SS7_ERROR("Found an invalid parameter \"%s\"!\n", parm->val);
@@ -1892,7 +1897,16 @@ static int ftmod_ss7_parse_cc_span(ftdm_conf_node_t *cc_span)
sng_ccSpan.typeCntrl = sng_cic_cntrl_type_map[ret].tril_type;
SS7_DEBUG("Found an ccSpan typeCntrl = %s\n", sng_cic_cntrl_type_map[ret].sng_type);
}
/**********************************************************************/
} else if (!strcasecmp(parm->var, "itx_auto_reply")) {
sng_ccSpan.itx_auto_reply = ftdm_true(parm->val);
SS7_DEBUG("Found itx_auto_reply %d\n", sng_ccSpan.itx_auto_reply);
} else if (!strcasecmp(parm->var, "transparent_iam")) {
#ifndef HAVE_ZLIB
SS7_CRIT("Cannot enable transparent IAM becauze zlib not installed\n");
#else
sng_ccSpan.transparent_iam = ftdm_true(parm->val);
SS7_DEBUG("Found transparent_iam %d\n", sng_ccSpan.transparent_iam);
#endif
} else if (!strcasecmp(parm->var, "cicbase")) {
/**********************************************************************/
sng_ccSpan.cicbase = atoi(parm->val);
@@ -2904,15 +2918,17 @@ static int ftmod_ss7_fill_in_ccSpan(sng_ccSpan_t *ccSpan)
g_ftdm_sngss7_data.cfg.isupCkt[x].cic = 0;
}
g_ftdm_sngss7_data.cfg.isupCkt[x].infId = ccSpan->isupInf;
g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = ccSpan->typeCntrl;
g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = ccSpan->ssf;
g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi = ccSpan->cld_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi = ccSpan->clg_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].options = ccSpan->options;
g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType;
g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits;
g_ftdm_sngss7_data.cfg.isupCkt[x].infId = ccSpan->isupInf;
g_ftdm_sngss7_data.cfg.isupCkt[x].typeCntrl = ccSpan->typeCntrl;
g_ftdm_sngss7_data.cfg.isupCkt[x].ssf = ccSpan->ssf;
g_ftdm_sngss7_data.cfg.isupCkt[x].cld_nadi = ccSpan->cld_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].clg_nadi = ccSpan->clg_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].rdnis_nadi = ccSpan->rdnis_nadi;
g_ftdm_sngss7_data.cfg.isupCkt[x].options = ccSpan->options;
g_ftdm_sngss7_data.cfg.isupCkt[x].switchType = ccSpan->switchType;
g_ftdm_sngss7_data.cfg.isupCkt[x].min_digits = ccSpan->min_digits;
g_ftdm_sngss7_data.cfg.isupCkt[x].itx_auto_reply = ccSpan->itx_auto_reply;
g_ftdm_sngss7_data.cfg.isupCkt[x].transparent_iam = ccSpan->transparent_iam;
if (ccSpan->t3 == 0) {
g_ftdm_sngss7_data.cfg.isupCkt[x].t3 = 1200;
@@ -950,7 +950,6 @@ static void wanpipe_read_stats(ftdm_channel_t *ftdmchan, wp_tdm_api_rx_hdr_t *rx
static FIO_READ_FUNCTION(wanpipe_read)
{
int rx_len = 0;
int myerrno = 0;
wp_tdm_api_rx_hdr_t hdrframe;
memset(&hdrframe, 0, sizeof(hdrframe));
@@ -964,7 +963,6 @@ static FIO_READ_FUNCTION(wanpipe_read)
}
if (rx_len < 0) {
myerrno = errno;
snprintf(ftdmchan->last_error, sizeof(ftdmchan->last_error), "%s", strerror(errno));
ftdm_log_chan(ftdmchan, FTDM_LOG_WARNING, "Failed to read from sangoma device: %s (%d)\n", strerror(errno), rx_len);
return FTDM_FAIL;
@@ -1269,7 +1267,7 @@ static FIO_GET_ALARMS_FUNCTION(wanpipe_get_alarms)
ftdm_channel_command(ftdmchan, FTDM_COMMAND_GET_LINK_STATUS, &sangoma_status);
ftdmchan->alarm_flags = sangoma_status == FTDM_HW_LINK_DISCONNECTED ? FTDM_ALARM_RED : FTDM_ALARM_NONE;
ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Link status is %d\n", sangoma_status);
}
}
}
if (alarms) {
@@ -1293,6 +1291,7 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_type) {
case WP_API_EVENT_LINK_STATUS:
{
if (FTDM_IS_DIGITAL_CHANNEL(fchan)) {
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
/* *event_id = FTDM_OOB_ALARM_CLEAR; */
@@ -1305,6 +1304,22 @@ static __inline__ ftdm_status_t wanpipe_channel_process_event(ftdm_channel_t *fc
};
/* The WP_API_EVENT_ALARM event should be used to clear alarms */
*event_id = FTDM_OOB_NOOP;
} else {
switch(tdm_api->wp_tdm_cmd.event.wp_tdm_api_event_link_status) {
case WP_TDMAPI_EVENT_LINK_STATUS_CONNECTED:
/* *event_id = FTDM_OOB_ALARM_CLEAR; */
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Using analog link connected event as alarm clear\n");
*event_id = FTDM_OOB_ALARM_CLEAR;
fchan->alarm_flags = FTDM_ALARM_NONE;
break;
default:
/* *event_id = FTDM_OOB_ALARM_TRAP; */
ftdm_log_chan_msg(fchan, FTDM_LOG_DEBUG, "Using analog link disconnected event as alarm trap\n");
*event_id = FTDM_OOB_ALARM_TRAP;
fchan->alarm_flags = FTDM_ALARM_RED;
break;
};
}
}
break;