freetdm: Used channel iterator.

Removed assert when we cannot find a call on RelInd, it seems like Trillium as a bug where they sometimes send release twice
		Fixes to some memory leaks
		Fix for bug in q921 trace disable command
		Fix for not recognizing etsi switchtype
		Fix for sending RESTART when we are not supposed to in EUROISDN NETWORK mode
		Support for l1 stats
		Fix for deadlocks/segfaults on shutdown
		Added index per link_id, support for show_spans
		Added progress-ind when sending CONNECT message
		Fix for sending CONNECT ACK when configured as TE
This commit is contained in:
David Yat Sin 2010-09-08 19:41:34 -04:00
parent 5219ab8c63
commit 5812c5fd53
12 changed files with 341 additions and 164 deletions

View File

@ -2182,9 +2182,8 @@ static void ftdm_logger(const char *file, const char *func, int line, int level,
if (switch_vasprintf(&data, fmt, ap) != -1) {
switch_log_printf(SWITCH_CHANNEL_ID_LOG, file, (char *)func, line, NULL, level, "%s", data);
free(data);
}
if (data) free(data);
va_end(ap);
}

View File

@ -463,6 +463,7 @@ static ftdm_status_t ftdm_span_destroy(ftdm_span_t *span)
status = FTDM_FAIL;
}
ftdm_safe_free(span->type);
ftdm_safe_free(span->name);
ftdm_safe_free(span->dtmf_hangup);
}
@ -536,7 +537,7 @@ static void ftdm_span_add(ftdm_span_t *span)
} else {
globals.spans = span;
}
hashtable_insert(globals.span_hash, (void *)span->name, span, HASHTABLE_FLAG_NONE);
hashtable_insert(globals.span_hash, (void *)span->name, span, HASHTABLE_FLAG_FREE_VALUE);
ftdm_mutex_unlock(globals.span_mutex);
}
@ -3550,12 +3551,20 @@ static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t
FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan, ftdm_iterator_t *iter)
{
ftdm_hash_iterator_t *hashiter = NULL;
ftdm_channel_lock(ftdmchan);
hashiter = ftdmchan->variable_hash == NULL ? NULL : hashtable_first(ftdmchan->variable_hash);
ftdm_channel_unlock(ftdmchan);
if (hashiter == NULL) {
return NULL;
}
if (!(iter = get_iterator(FTDM_ITERATOR_VARS, iter))) {
return NULL;
}
ftdm_channel_lock(ftdmchan);
iter->pvt.hashiter = ftdmchan->variable_hash == NULL ? NULL : hashtable_first(ftdmchan->variable_hash);
ftdm_channel_unlock(ftdmchan);
iter->pvt.hashiter = hashiter;
return iter;
}
@ -4837,11 +4846,13 @@ FT_DECLARE(ftdm_status_t) ftdm_global_destroy(void)
ftdm_mutex_lock(globals.mutex);
hashtable_destroy(globals.interface_hash);
hashtable_destroy(globals.module_hash);
hashtable_destroy(globals.module_hash);
hashtable_destroy(globals.span_hash);
hashtable_destroy(globals.group_hash);
ftdm_mutex_unlock(globals.mutex);
ftdm_mutex_destroy(&globals.mutex);
ftdm_mutex_destroy(&globals.span_mutex);
ftdm_mutex_destroy(&globals.group_mutex);
memset(&globals, 0, sizeof(globals));
return FTDM_SUCCESS;

View File

@ -472,10 +472,7 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan)
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);
@ -694,7 +691,7 @@ static FIO_CHANNEL_OUTGOING_CALL_FUNCTION(ftdm_sangoma_isdn_outgoing_call)
return status;
}
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_sig_status)
static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_chan_sig_status)
{
if (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) {
*status = FTDM_SIG_STATE_UP;
@ -705,17 +702,34 @@ static FIO_CHANNEL_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_sig_status)
return FTDM_SUCCESS;
}
static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_sig_status)
static FIO_CHANNEL_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_chan_sig_status)
{
ftdm_log(FTDM_LOG_ERROR,"Cannot set channel status in this module\n");
return FTDM_NOTIMPL;
}
static FIO_SPAN_GET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_get_span_sig_status)
{
if (ftdm_test_flag(span->channels[1], FTDM_CHANNEL_SIG_UP)) {
*status = FTDM_SIG_STATE_UP;
} else {
*status = FTDM_SIG_STATE_DOWN;
}
return FTDM_SUCCESS;
}
static FIO_SPAN_SET_SIG_STATUS_FUNCTION(ftdm_sangoma_isdn_set_span_sig_status)
{
ftdm_log(FTDM_LOG_ERROR,"Cannot set span status in this module\n");
return FTDM_NOTIMPL;
}
static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
{
ftdm_log(FTDM_LOG_INFO,"Starting span %s:%u.\n",span->name,span->span_id);
if (sng_isdn_stack_activate(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to activate span %s\n", span->name);
if (sng_isdn_stack_start(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to start span %s\n", span->name);
return FTDM_FAIL;
}
/* clear the monitor thread stop flag */
@ -734,7 +748,8 @@ static ftdm_status_t ftdm_sangoma_isdn_start(ftdm_span_t *span)
static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
{
unsigned i;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
ftdm_log(FTDM_LOG_INFO, "Stopping span %s\n", span->name);
/* throw the STOP_THREAD flag to signal monitor thread stop */
@ -746,11 +761,19 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
ftdm_sleep(10);
}
/* 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);
if (sng_isdn_stack_stop(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "Failed to stop span %s\n", span->name);
}
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_safe_free(((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data);
((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = NULL;
}
ftdm_iterator_free(chaniter);
ftdm_sched_destroy(&((sngisdn_span_data_t*)span->signal_data)->sched);
ftdm_queue_destroy(&((sngisdn_span_data_t*)span->signal_data)->event_queue);
ftdm_safe_free(span->signal_data);
ftdm_log(FTDM_LOG_DEBUG, "Finished stopping span %s\n", span->name);
@ -760,6 +783,9 @@ static ftdm_status_t ftdm_sangoma_isdn_stop(ftdm_span_t *span)
static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
{
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
sngisdn_span_data_t *span_data;
ftdm_log(FTDM_LOG_INFO, "Configuring ftmod_sangoma_isdn span = %s\n", span->name);
@ -767,13 +793,15 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span_data = ftdm_calloc(1, sizeof(sngisdn_span_data_t));
span_data->ftdm_span = span;
span->signal_data = span_data;
unsigned i;
for (i=1;i <= span->chan_count; i++) {
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_chan_data_t *chan_data = ftdm_calloc(1, sizeof(sngisdn_chan_data_t));
chan_data->ftdmchan = span->channels[i];
span->channels[i]->call_data = chan_data;
chan_data->ftdmchan = ((ftdm_channel_t*)ftdm_iterator_current(curr));
((ftdm_channel_t*)ftdm_iterator_current(curr))->call_data = chan_data;
}
ftdm_iterator_free(chaniter);
if (ftmod_isdn_parse_cfg(ftdm_parameters, span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Failed to parse configuration\n");
@ -792,8 +820,10 @@ static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(ftdm_sangoma_isdn_span_config)
span->outgoing_call = ftdm_sangoma_isdn_outgoing_call;
span->channel_request = NULL;
span->signal_cb = sig_cb;
span->get_channel_sig_status = ftdm_sangoma_isdn_get_sig_status;
span->set_channel_sig_status = ftdm_sangoma_isdn_set_sig_status;
span->get_channel_sig_status = ftdm_sangoma_isdn_get_chan_sig_status;
span->set_channel_sig_status = ftdm_sangoma_isdn_set_chan_sig_status;
span->get_span_sig_status = ftdm_sangoma_isdn_get_span_sig_status;
span->set_span_sig_status = ftdm_sangoma_isdn_set_span_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);
@ -855,7 +885,7 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_isdn_init)
for(i=1;i<=MAX_VARIANTS;i++) {
ftdm_mutex_create(&g_sngisdn_data.ccs[i].mutex);
}
/* initalize sng_isdn library */
sng_isdn_init(&g_sngisdn_event_interface);
return FTDM_SUCCESS;
@ -923,16 +953,35 @@ static FIO_API_FUNCTION(ftdm_sangoma_isdn_api)
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");
stream->write_function(stream, "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]);
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;
goto done;
}
/* TODO: implement PHY stats */
sngisdn_print_phy_stats(stream, span);
}
if (!strcasecmp(argv[0], "show_spans")) {
ftdm_span_t *span = NULL;
if (argc == 2) {
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;
goto done;
}
sngisdn_print_span(stream, span);
status = FTDM_SUCCESS;
goto done;
}
sngisdn_print_spans(stream);
}
if (!strcasecmp(argv[0], "check_ids")) {
sngisdn_check_free_ids();

View File

@ -243,7 +243,8 @@ typedef struct ftdm_sngisdn_data {
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];
sngisdn_dchan_data_t dchans[MAX_L1_LINKS+1];
sngisdn_span_data_t *spans[MAX_L1_LINKS+1]; /* spans are indexed by link_id */
}ftdm_sngisdn_data_t;
@ -363,9 +364,12 @@ void sngisdn_facility_timeout(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);
ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span);
ftdm_status_t sng_isdn_stack_stop(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);
#endif /* __FTMOD_SNG_ISDN_H__ */

View File

@ -62,7 +62,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
}
break;
case FTDM_TRUNK_E1:
if (!strcasecmp(switch_name, "euroisdn") || strcasecmp(switch_name, "etsi")) {
if (!strcasecmp(switch_name, "euroisdn") ||
!strcasecmp(switch_name, "etsi")) {
signal_data->switchtype = SNGISDN_SWITCH_EUROISDN;
} else if (!strcasecmp(switch_name, "qsig")) {
signal_data->switchtype = SNGISDN_SWITCH_QSIG;
@ -116,6 +117,8 @@ ftdm_status_t parse_switchtype(const char* switch_name, ftdm_span_t *span)
signal_data->span_id = dchan_data->num_spans;
dchan_data->spans[signal_data->span_id] = signal_data;
g_sngisdn_data.spans[signal_data->link_id] = signal_data;
ftdm_log(FTDM_LOG_DEBUG, "%s: cc_id:%d dchan_id:%d span_id:%d\n", span->name, signal_data->cc_id, signal_data->dchan_id, signal_data->span_id);
@ -163,6 +166,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
signal_data->overlap_dial = SNGISDN_OPT_DEFAULT;
signal_data->setup_arb = SNGISDN_OPT_DEFAULT;
signal_data->link_id = span->span_id;
span->default_caller_data.bearer_capability = IN_ITC_SPEECH;
/* Cannot set default bearer_layer1 yet, as we do not know the switchtype */
@ -258,7 +262,7 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_
ftdm_log(FTDM_LOG_WARNING, "Ignoring unknown parameter %s\n", ftdm_parameters[paramindex].var);
}
}
signal_data->link_id = span->span_id;
if (signal_data->switchtype == SNGISDN_SWITCH_INVALID) {
ftdm_log(FTDM_LOG_ERROR, "%s: switchtype not specified", span->name);
return FTDM_FAIL;

View File

@ -35,7 +35,6 @@
#include "ftmod_sangoma_isdn.h"
void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status);
void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status_t status)
@ -53,23 +52,21 @@ void sngisdn_set_chan_sig_status(ftdm_channel_t *ftdmchan, ftdm_signaling_status
return;
}
void sngisdn_set_span_sig_status(ftdm_span_t *span, ftdm_signaling_status_t status)
{
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t status)
{
unsigned i;
/* TODO: use channel iterator once it is implemented */
for (i=1;i<=ftdmspan->chan_count;i++) {
sngisdn_set_chan_sig_status(ftdmspan->channels[i], status);
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
sngisdn_set_chan_sig_status(((ftdm_channel_t*)ftdm_iterator_current(curr)), status);
}
ftdm_iterator_free(chaniter);
return;
}
/* For Emacs:
* Local Variables:
* mode:c

View File

@ -656,8 +656,7 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
cfg.t.cfg.s.inDLSAP.ctldInt[1] = 1;
}
cfg.t.cfg.s.inDLSAP.numRstInd = 255;
cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
cfg.t.cfg.s.inDLSAP.numRstInd = 255;
cfg.t.cfg.s.inDLSAP.relOpt = TRUE;
#ifdef ISDN_SRV
cfg.t.cfg.s.inDLSAP.bcas = FALSE;
@ -666,16 +665,19 @@ ftdm_status_t sng_isdn_stack_cfg_q931_dlsap(ftdm_span_t *span)
#endif /* ISDN_SRV */
if (signal_data->signalling == SNGISDN_SIGNALING_NET) {
cfg.t.cfg.s.inDLSAP.ackOpt = TRUE;
cfg.t.cfg.s.inDLSAP.intType = NETWORK;
cfg.t.cfg.s.inDLSAP.clrGlr = FALSE; /* in case of glare, do not clear local call */
cfg.t.cfg.s.inDLSAP.statEnqOpt = TRUE;
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
if (signal_data->switchtype == SNGISDN_SWITCH_EUROISDN ||
signal_data->switchtype == SNGISDN_SWITCH_INSNET) {
cfg.t.cfg.s.inDLSAP.rstOpt = FALSE;
} else {
cfg.t.cfg.s.inDLSAP.rstOpt = TRUE;
}
} else {
cfg.t.cfg.s.inDLSAP.ackOpt = FALSE;
cfg.t.cfg.s.inDLSAP.intType = USER;
cfg.t.cfg.s.inDLSAP.clrGlr = TRUE; /* in case of glare, clear local call */
cfg.t.cfg.s.inDLSAP.statEnqOpt = FALSE;

View File

@ -38,8 +38,8 @@
void stack_resp_hdr_init(Header *hdr);
ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span);
ftdm_status_t sng_isdn_activate_q921(ftdm_span_t *span);
ftdm_status_t sng_isdn_activate_q931(ftdm_span_t *span);
ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span);
ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span);
ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t trace_opt);
@ -52,14 +52,23 @@ 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)
ftdm_status_t sng_isdn_stack_start(ftdm_span_t *span)
{
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
if (sng_isdn_activate_q921(span) != FTDM_SUCCESS) {
if (sng_isdn_cntrl_q921(span, ABND_ENA, NOTUSED) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q921\n", span->name);
return FTDM_FAIL;
}
/* Try to find an alternative for this */
/* LAPD will call LdUiDatBndCfm before it received a LdLiMacBndCfm from L1,
so we need to give some time before activating q931, as q931 will send a
LdUiDatConReq when activated, and this requires the Mac SAP to be already
bound first */
ftdm_sleep(500);
ftdm_log(FTDM_LOG_DEBUG, "%s:Stack q921 activated\n", span->name);
if (!g_sngisdn_data.ccs[signal_data->cc_id].activation_done) {
g_sngisdn_data.ccs[signal_data->cc_id].activation_done = 1;
@ -70,7 +79,8 @@ ftdm_status_t sng_isdn_stack_activate(ftdm_span_t *span)
ftdm_log(FTDM_LOG_DEBUG, "%s:Stack CC activated\n", span->name);
}
if (sng_isdn_activate_q931(span) != FTDM_SUCCESS) {
if (sng_isdn_cntrl_q931(span, ABND_ENA, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to activate stack q931\n", span->name);
return FTDM_FAIL;
}
@ -80,50 +90,72 @@ 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)
ftdm_status_t sng_isdn_stack_stop(ftdm_span_t *span)
{
/* Stop L1 first, so we do not receive any more frames */
if (sng_isdn_deactivate_phy(span) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack phy\n", span->name);
return FTDM_FAIL;
}
if (sng_isdn_cntrl_q931(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q931\n", span->name);
return FTDM_FAIL;
}
if (sng_isdn_cntrl_q921(span, AUBND_DIS, SAELMNT) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_CRIT, "%s:Failed to deactivate stack q921\n", span->name);
return FTDM_FAIL;
}
ftdm_log(FTDM_LOG_INFO, "%s:Signalling stopped\n", span->name);
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_activate_phy(ftdm_span_t *span)
{
/* There is no need to start phy, as it will Q921 will send a activate request to phy when it starts */
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_deactivate_phy(ftdm_span_t *span)
{
L1Mngmt cntrl;
Pst pst;
Pst pst;
ftdm_log(FTDM_LOG_ERROR, "%s:PHY control not implemented\n", span->name);
return FTDM_SUCCESS;
/* TODO: phy cntrl not implemented yet */
sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*)span->signal_data;
sng_isdn_phy_cntrl(&pst, &cntrl);
/* initalize the post structure */
stack_pst_init(&pst);
/* insert the destination Entity */
pst.dstEnt = ENTL1;
/* initalize the control structure */
memset(&cntrl, 0, sizeof(cntrl));
/* initalize the control header */
stack_hdr_init(&cntrl.hdr);
cntrl.hdr.msgType = TCNTRL; /* configuration */
cntrl.hdr.entId.ent = ENTL1; /* entity */
cntrl.hdr.entId.inst = S_INST; /* instance */
cntrl.hdr.elmId.elmnt = STTSAP; /* SAP Specific cntrl */
cntrl.t.cntrl.action = AUBND_DIS;
cntrl.t.cntrl.subAction = SAELMNT;
cntrl.t.cntrl.sapId = signal_data->link_id;
if (sng_isdn_phy_cntrl(&pst, &cntrl)) {
return FTDM_FAIL;
}
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_activate_q921(ftdm_span_t *span)
{
ftdm_status_t status;
status = sng_isdn_cntrl_q921(span, ABND_ENA, NOTUSED);
/* Try to find an alternative for this */
/* LAPD will call LdUiDatBndCfm before it received a LdLiMacBndCfm from L1,
so we need to give some time before activating q931, as q931 will send a
LdUiDatConReq when activated, and this requires the Mac SAP to be already
bound first */
if (status == FTDM_SUCCESS) {
ftdm_sleep(500);
}
return status;
}
ftdm_status_t sng_isdn_activate_q931(ftdm_span_t *span)
{
/* TODO: remove this function later, just call sng_isdn_cntrl_q931 directly */
return sng_isdn_cntrl_q931(span, ABND_ENA, SAELMNT);
}
ftdm_status_t sng_isdn_activate_cc(ftdm_span_t *span)
{
CcMngmt cntrl;;
@ -167,7 +199,7 @@ ftdm_status_t sng_isdn_activate_trace(ftdm_span_t *span, sngisdn_tracetype_t tra
ftdm_log(FTDM_LOG_INFO, "s%d Disabling q921 trace\n", signal_data->link_id);
sngisdn_clear_trace_flag(signal_data, SNGISDN_TRACE_Q921);
if (sng_isdn_cntrl_q921(span, ADISIMM, SAELMNT) != FTDM_SUCCESS) {
if (sng_isdn_cntrl_q921(span, ADISIMM, SATRC) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "s%d Failed to disable q921 trace\n");
}
}

View File

@ -106,6 +106,13 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event)
break;
}
#if 0
/* Export ftdmchan variables here if we need to */
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");
#endif
/* Fill in call information */
cpy_calling_num_from_stack(&ftdmchan->caller_data, &conEvnt->cgPtyNmb);
cpy_called_num_from_stack(&ftdmchan->caller_data, &conEvnt->cdPtyNmb);
@ -267,6 +274,9 @@ void sngisdn_process_con_cfm (sngisdn_event_data_t *sngisdn_event)
/* This is the only valid state we should get a CONNECT ACK on */
/* do nothing */
break;
case FTDM_CHANNEL_STATE_HANGUP_COMPLETE:
/* We just hung up an incoming call right after we sent a CONNECT so ignore this message */
break;
default:
ftdm_log_chan(ftdmchan, FTDM_LOG_CRIT, "Processing CONNECT/CONNECT ACK in an invalid state (%s)\n", ftdm_channel_state2str(ftdmchan->state));

View File

@ -409,7 +409,7 @@ 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;
if (!sngisdn_info->suInstId || !sngisdn_info->spInstId) {
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);
@ -450,6 +450,14 @@ void sngisdn_snd_connect(ftdm_channel_t *ftdmchan)
cnStEvnt.chanId.chanNmbSlotMap.len = 1;
cnStEvnt.chanId.chanNmbSlotMap.val[0] = ftdmchan->physical_chan_id;
}
cnStEvnt.progInd.eh.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.pres = PRSNT_NODEF;
cnStEvnt.progInd.location.val = IN_LOC_USER;
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; /* Not end-to-end ISDN */
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)) {

View File

@ -239,7 +239,8 @@ void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Re
!(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");
/* It seems that Trillium has a bug where they sometimes send release twice on a call, so do not crash on these for now */
/* ftdm_assert(0, "Inconsistent call states\n"); */
return;
}
@ -591,6 +592,7 @@ void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t 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 != NULL, "Failed to allocate memory\n");
memset(sngisdn_event, 0, sizeof(*sngisdn_event));
@ -640,30 +642,24 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces
void sngisdn_rcv_phy_ind(SuId suId, Reason reason)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
if (reason != LL1_REASON_CON_REQ_FAIL) {
ftdm_log(FTDM_LOG_INFO, "[SNGISDN PHY] D-chan %d : %s\n", suId, DECODE_LL1_REASON(reason));
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
void sngisdn_rcv_q921_ind(BdMngmt *status)
{
ISDN_FUNC_TRACE_ENTER(__FUNCTION__);
unsigned j,k;
ftdm_span_t *ftdmspan = NULL;
for(j=1;j<=g_sngisdn_data.num_dchan;j++) {
for(k=1;k<=g_sngisdn_data.dchans[j].num_spans;k++) {
if (g_sngisdn_data.dchans[j].spans[k]->link_id == status->t.usta.lnkNmb) {
ftdmspan = (ftdm_span_t*)g_sngisdn_data.dchans[j].spans[k]->ftdm_span;
}
}
{
ftdm_span_t *ftdmspan;
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[status->t.usta.lnkNmb];
if (!signal_data) {
ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb);
return;
}
if (ftdmspan == NULL) {
ftdm_log(FTDM_LOG_WARNING, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb);
ftdmspan = signal_data->ftdm_span;
if (!ftdmspan) {
ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.lnkNmb);
return;
}
@ -694,69 +690,56 @@ void sngisdn_rcv_q921_ind(BdMngmt *status)
}
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;
switch (status->t.usta.alarm.event) {
case LCM_EVENT_UP:
case LCM_EVENT_DOWN:
{
ftdm_span_t *ftdmspan;
sngisdn_span_data_t *signal_data = g_sngisdn_data.spans[status->t.usta.suId];
if (!signal_data) {
ftdm_log(FTDM_LOG_INFO, "Received q921 status on unconfigured span (lnkNmb:%d)\n", status->t.usta.suId);
return;
}
break;
ftdmspan = signal_data->ftdm_span;
if (status->t.usta.alarm.event == LCM_EVENT_UP) {
ftdm_log(FTDM_LOG_INFO, "[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);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_UP);
sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_UP);
} else {
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);
sngisdn_set_span_sig_status(ftdmspan, FTDM_SIG_STATE_DOWN);
sng_isdn_set_avail_rate(ftdmspan, SNGISDN_AVAIL_PWR_SAVING);
}
}
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;
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);
}
ISDN_FUNC_TRACE_EXIT(__FUNCTION__);
return;
}
@ -902,12 +885,13 @@ void sngisdn_rcv_sng_log(uint8_t level, char *fmt,...)
break;
case SNG_LOGLEVEL_CRIT:
ftdm_log(FTDM_LOG_CRIT, "sng_isdn->%s", data);
/*ftdm_assert(0, "Got an error from stack");*/
/* ftdm_assert(0, "Got an error from stack"); */
break;
default:
ftdm_log(FTDM_LOG_INFO, "sng_isdn->%s", data);
break;
}
ftdm_safe_free(data);
return;
}

View File

@ -134,16 +134,22 @@ ftdm_status_t __inline__ get_ftdmchan_by_spInstId(uint8_t cc_id, uint32_t spInst
return FTDM_SUCCESS;
}
ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *ftdmspan, sngisdn_avail_t avail)
ftdm_status_t sng_isdn_set_avail_rate(ftdm_span_t *span, sngisdn_avail_t avail)
{
unsigned i;
if (ftdmspan->trunk_type == FTDM_TRUNK_BRI ||
ftdmspan->trunk_type == FTDM_TRUNK_BRI_PTMP) {
if (span->trunk_type == FTDM_TRUNK_BRI ||
span->trunk_type == FTDM_TRUNK_BRI_PTMP) {
for(i=1; i<=ftdmspan->chan_count; i++) {
ftdm_log_chan(ftdmspan->channels[i], FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
ftdmspan->channels[i]->availability_rate = avail;
ftdm_iterator_t *chaniter = NULL;
ftdm_iterator_t *curr = NULL;
chaniter = ftdm_span_get_chan_iterator(span, NULL);
for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) {
ftdm_log_chan(((ftdm_channel_t*)ftdm_iterator_current(curr)), FTDM_LOG_DEBUG, "Setting availability rate to:%d\n", avail);
((ftdm_channel_t*)ftdm_iterator_current(curr))->availability_rate = avail;
}
ftdm_iterator_free(chaniter);
}
return FTDM_SUCCESS;
}
@ -554,6 +560,77 @@ ftdm_user_layer1_prot_t sngisdn_get_usrInfoLyr1Prot_from_user(uint8_t layer1_pro
return FTDM_USER_LAYER1_PROT_ULAW;
}
void sngisdn_print_phy_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;
memset(&sts, 0, sizeof(sts));
sng_isdn_phy_stats(signal_data->link_id , &sts);
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, " Span:%s", span->name);
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, " Performance Counters");
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, "RX Packets:\t%u\tTX Packets:\t%u\tEvents:%u\n", sts.t.sts.rx_packets, sts.t.sts.tx_packets, sts.t.sts.rx_events);
stream->write_function(stream, "RX Bytes:\t%u\tTX Bytes:\t%u\n\n", sts.t.sts.rx_bytes, sts.t.sts.tx_bytes);
stream->write_function(stream, "TX Queue:\t%u/%u\tRX Queue:\t%u/%u\tEvents Queue:\t%u/%u\n",
sts.t.sts.num_frames_in_tx_queue,sts.t.sts.tx_queue_len,
sts.t.sts.num_frames_in_rx_queue, sts.t.sts.rx_queue_len,
sts.t.sts.rx_events_in_queue, sts.t.sts.event_queue_len);
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, " Errors");
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, "RX Errors:\t%u\tTX Errors:\t%u\n", sts.t.sts.rx_errors, sts.t.sts.tx_errors);
stream->write_function(stream, "RX Dropped:\t%u\tTX Dropped:\t%u\tEvents Dropped:\t%u\n", sts.t.sts.rx_dropped, sts.t.sts.tx_dropped,sts.t.sts.rx_events_dropped);
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, " RX Errors Details");
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
stream->write_function(stream, "CRC:\t\t%u\tFrame:\t\t%u\tOverruns:\t%u\n", sts.t.sts.rx_crc_errors, sts.t.sts.rx_frame_errors, sts.t.sts.rx_over_errors);
stream->write_function(stream, "Fifo:\t\t%u\tAborts:\t\t%u\tMissed:\t\t%u\n", sts.t.sts.rx_fifo_errors, sts.t.sts.rx_hdlc_abort_counter, sts.t.sts.rx_missed_errors);
stream->write_function(stream, "Length:\t\t%u\n", sts.t.sts.rx_length_errors);
stream->write_function(stream, "\n---------------------------------------------------------------------\n");
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;
}
void sngisdn_print_span(ftdm_stream_handle_t *stream, ftdm_span_t *span)
{
ftdm_signaling_status_t sigstatus;
ftdm_alarm_flag_t alarmbits;
ftdm_channel_t *fchan;
alarmbits = FTDM_ALARM_NONE;
fchan = ftdm_span_get_channel(span, 1);
if (fchan) {
ftdm_channel_get_alarms(fchan, &alarmbits);
}
ftdm_span_get_sig_status(span, &sigstatus);
stream->write_function(stream, "span:%s physical:%s signalling:%s\n",
span->name, alarmbits ? "ALARMED" : "OK",
ftdm_signaling_status2str(sigstatus));
return;
}
void sngisdn_print_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);
}
}
return;
}
/* For Emacs:
* Local Variables:
* mode:c