diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index fb85b3515c..b4a40f0bad 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -1404,6 +1404,7 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session private_t *tech_pvt = NULL; switch_channel_t *channel = NULL; ftdm_iterator_t *iter = NULL; + ftdm_iterator_t *curr = NULL; const char *var_name = NULL; const char *var_value = NULL; uint32_t spanid, chanid; @@ -1515,13 +1516,14 @@ ftdm_status_t ftdm_channel_from_event(ftdm_sigmsg_t *sigmsg, switch_core_session switch_channel_set_variable_printf(channel, "freetdm_custom_call_data", "%s", channel_caller_data->raw_data); } /* Add any channel variable to the dial plan */ - iter = ftdm_channel_get_var_iterator(sigmsg->channel); - for ( ; iter; iter = ftdm_iterator_next(iter)) { - ftdm_channel_get_current_var(iter, &var_name, &var_value); + iter = ftdm_channel_get_var_iterator(sigmsg->channel, NULL); + for (curr = iter ; curr; curr = ftdm_iterator_next(curr)) { + ftdm_channel_get_current_var(curr, &var_name, &var_value); snprintf(name, sizeof(name), FREETDM_VAR_PREFIX "%s", var_name); switch_channel_set_variable_printf(channel, name, "%s", var_value); } - + ftdm_iterator_free(iter); + switch_channel_set_state(channel, CS_INIT); if (switch_core_session_thread_launch(session) != SWITCH_STATUS_SUCCESS) { switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Error spawning thread\n"); @@ -2180,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); } @@ -2371,6 +2372,121 @@ static int add_profile_parameters(switch_xml_t cfg, const char *profname, ftdm_c return paramindex; } +static void parse_bri_pri_spans(switch_xml_t cfg, switch_xml_t spans) +{ + switch_xml_t myspan, param; + + for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { + ftdm_status_t zstatus = FTDM_FAIL; + const char *context = "default"; + const char *dialplan = "XML"; + ftdm_conf_parameter_t spanparameters[30]; + char *id = (char *) switch_xml_attr(myspan, "id"); + char *name = (char *) switch_xml_attr(myspan, "name"); + char *configname = (char *) switch_xml_attr(myspan, "cfgprofile"); + ftdm_span_t *span = NULL; + uint32_t span_id = 0; + unsigned paramindex = 0; + + if (!name && !id) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sangoma isdn span missing required attribute 'id' or 'name', skipping ...\n"); + continue; + } + + if (name) { + zstatus = ftdm_span_find_by_name(name, &span); + } else { + if (switch_is_number(id)) { + span_id = atoi(id); + zstatus = ftdm_span_find(span_id, &span); + } + + if (zstatus != FTDM_SUCCESS) { + zstatus = ftdm_span_find_by_name(id, &span); + } + } + + if (zstatus != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); + continue; + } + + if (!span_id) { + span_id = ftdm_span_get_id(span); + } + + memset(spanparameters, 0, sizeof(spanparameters)); + paramindex = 0; + + if (configname) { + paramindex = add_profile_parameters(cfg, configname, spanparameters, ftdm_array_len(spanparameters)); + if (paramindex) { + ftdm_log(FTDM_LOG_DEBUG, "Added %d parameters from profile %s for span %d\n", paramindex, configname, span_id); + } + } + + /* some defaults first */ + SPAN_CONFIG[span_id].limit_backend = "hash"; + SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT; + + for (param = switch_xml_child(myspan, "param"); param; param = param->next) { + char *var = (char *) switch_xml_attr_soft(param, "name"); + char *val = (char *) switch_xml_attr_soft(param, "value"); + + if (ftdm_array_len(spanparameters) == paramindex) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for ss7 span, ignoring any parameter after %s\n", var); + break; + } + + if (!strcasecmp(var, "context")) { + context = val; + } else if (!strcasecmp(var, "dialplan")) { + dialplan = val; + } else if (!strcasecmp(var, "call_limit_backend")) { + SPAN_CONFIG[span_id].limit_backend = val; + ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id); + } else if (!strcasecmp(var, "call_limit_rate")) { + int calls; + int seconds; + if (sscanf(val, "%d/%d", &calls, &seconds) != 2) { + ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var); + } else { + if (calls < 1 || seconds < 1) { + ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, minimum call limit must be 1 per second\n", var); + } else { + SPAN_CONFIG[span_id].limit_calls = calls; + SPAN_CONFIG[span_id].limit_seconds = seconds; + } + } + } else if (!strcasecmp(var, "call_limit_reset_event")) { + if (!strcasecmp(val, "answer")) { + SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER; + } else { + ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, only accepted event is 'answer'\n", var); + } + } else { + spanparameters[paramindex].var = var; + spanparameters[paramindex].val = val; + paramindex++; + } + } + + if (ftdm_configure_span_signaling(span, + "sangoma_isdn", + on_clear_channel_signal, + spanparameters) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "Error configuring Sangoma ISDN FreeTDM span %d\n", span_id); + continue; + } + SPAN_CONFIG[span_id].span = span; + switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); + switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); + switch_copy_string(SPAN_CONFIG[span_id].type, "Sangoma (ISDN)", sizeof(SPAN_CONFIG[span_id].type)); + ftdm_log(FTDM_LOG_DEBUG, "Configured Sangoma ISDN FreeTDM span %d\n", span_id); + ftdm_span_start(span); + } +} + static switch_status_t load_config(void) { const char *cf = "freetdm.conf"; @@ -2381,7 +2497,8 @@ static switch_status_t load_config(void) unsigned boosti = 0; unsigned int i = 0; ftdm_channel_t *fchan = NULL; - unsigned int chancount = 0; + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *curr = NULL; memset(boost_spans, 0, sizeof(boost_spans)); memset(&globals, 0, sizeof(globals)); @@ -2410,116 +2527,12 @@ static switch_status_t load_config(void) } } - if ((spans = switch_xml_child(cfg, "sangoma_pri_spans")) || (spans = switch_xml_child(cfg, "sangoma_bri_spans"))) { - for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { - ftdm_status_t zstatus = FTDM_FAIL; - const char *context = "default"; - const char *dialplan = "XML"; - ftdm_conf_parameter_t spanparameters[30]; - char *id = (char *) switch_xml_attr(myspan, "id"); - char *name = (char *) switch_xml_attr(myspan, "name"); - char *configname = (char *) switch_xml_attr(myspan, "cfgprofile"); - ftdm_span_t *span = NULL; - uint32_t span_id = 0; - unsigned paramindex = 0; + if ((spans = switch_xml_child(cfg, "sangoma_pri_spans"))) { + parse_bri_pri_spans(cfg, spans); + } - if (!name && !id) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "sangoma isdn span missing required attribute 'id' or 'name', skipping ...\n"); - continue; - } - - if (name) { - zstatus = ftdm_span_find_by_name(name, &span); - } else { - if (switch_is_number(id)) { - span_id = atoi(id); - zstatus = ftdm_span_find(span_id, &span); - } - - if (zstatus != FTDM_SUCCESS) { - zstatus = ftdm_span_find_by_name(id, &span); - } - } - - if (zstatus != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span id:%s name:%s\n", switch_str_nil(id), switch_str_nil(name)); - continue; - } - - if (!span_id) { - span_id = ftdm_span_get_id(span); - } - - memset(spanparameters, 0, sizeof(spanparameters)); - paramindex = 0; - - if (configname) { - paramindex = add_profile_parameters(cfg, configname, spanparameters, ftdm_array_len(spanparameters)); - if (paramindex) { - ftdm_log(FTDM_LOG_DEBUG, "Added %d parameters from profile %s for span %d\n", paramindex, configname, span_id); - } - } - - /* some defaults first */ - SPAN_CONFIG[span_id].limit_backend = "hash"; - SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_TIMEOUT; - - for (param = switch_xml_child(myspan, "param"); param; param = param->next) { - char *var = (char *) switch_xml_attr_soft(param, "name"); - char *val = (char *) switch_xml_attr_soft(param, "value"); - - if (ftdm_array_len(spanparameters) == paramindex) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Too many parameters for ss7 span, ignoring any parameter after %s\n", var); - break; - } - - if (!strcasecmp(var, "context")) { - context = val; - } else if (!strcasecmp(var, "dialplan")) { - dialplan = val; - } else if (!strcasecmp(var, "call_limit_backend")) { - SPAN_CONFIG[span_id].limit_backend = val; - ftdm_log(FTDM_LOG_DEBUG, "Using limit backend %s for span %d\n", SPAN_CONFIG[span_id].limit_backend, span_id); - } else if (!strcasecmp(var, "call_limit_rate")) { - int calls; - int seconds; - if (sscanf(val, "%d/%d", &calls, &seconds) != 2) { - ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter, format example: 3/1 for 3 calls per second\n", var); - } else { - if (calls < 1 || seconds < 1) { - ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, minimum call limit must be 1 per second\n", var); - } else { - SPAN_CONFIG[span_id].limit_calls = calls; - SPAN_CONFIG[span_id].limit_seconds = seconds; - } - } - } else if (!strcasecmp(var, "call_limit_reset_event")) { - if (!strcasecmp(val, "answer")) { - SPAN_CONFIG[span_id].limit_reset_event = FTDM_LIMIT_RESET_ON_ANSWER; - } else { - ftdm_log(FTDM_LOG_ERROR, "Invalid %s parameter value, only accepted event is 'answer'\n", var); - } - } else { - spanparameters[paramindex].var = var; - spanparameters[paramindex].val = val; - paramindex++; - } - } - - if (ftdm_configure_span_signaling(span, - "sangoma_isdn", - on_clear_channel_signal, - spanparameters) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error configuring Sangoma ISDN FreeTDM span %d\n", span_id); - continue; - } - SPAN_CONFIG[span_id].span = span; - switch_copy_string(SPAN_CONFIG[span_id].context, context, sizeof(SPAN_CONFIG[span_id].context)); - switch_copy_string(SPAN_CONFIG[span_id].dialplan, dialplan, sizeof(SPAN_CONFIG[span_id].dialplan)); - switch_copy_string(SPAN_CONFIG[span_id].type, "Sangoma (ISDN)", sizeof(SPAN_CONFIG[span_id].type)); - ftdm_log(FTDM_LOG_DEBUG, "Configured Sangoma ISDN FreeTDM span %d\n", span_id); - ftdm_span_start(span); - } + if ((spans = switch_xml_child(cfg, "sangoma_bri_spans"))) { + parse_bri_pri_spans(cfg, spans); } switch_core_hash_init(&globals.ss7_configs, module_pool); @@ -2769,11 +2782,13 @@ static switch_status_t load_config(void) switch_set_string(SPAN_CONFIG[span_id].dialplan, dialplan); SPAN_CONFIG[span_id].analog_options = analog_options | globals.analog_options; - chancount = ftdm_span_get_chan_count(span); - for (i = 1; i <= chancount; i++) { - fchan = ftdm_span_get_channel(span, i); + chaniter = ftdm_span_get_chan_iterator(span, NULL); + curr = chaniter; + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + fchan = ftdm_iterator_current(curr); ftdm_channel_set_private(fchan, &SPAN_CONFIG[span_id].pvts[i]); } + ftdm_iterator_free(chaniter); if (dial_regex) { switch_set_string(SPAN_CONFIG[span_id].dial_regex, dial_regex); @@ -3581,6 +3596,8 @@ SWITCH_STANDARD_API(ft_function) { char *mycmd = NULL, *argv[10] = { 0 }; int argc = 0; + ftdm_iterator_t *chaniter = NULL; + ftdm_iterator_t *curr = NULL; if (!zstr(cmd) && (mycmd = strdup(cmd))) { argc = switch_separate_string(mycmd, ' ', argv, (sizeof(argv) / sizeof(argv[0]))); @@ -3626,11 +3643,11 @@ SWITCH_STANDARD_API(ft_function) dump_chan_xml(span, chan_id, stream); } } else { - uint32_t j; - uint32_t ccount = ftdm_span_get_chan_count(span); - for (j = 1; j <= ccount; j++) { - dump_chan_xml(span, j, stream); + chaniter = ftdm_span_get_chan_iterator(span, NULL); + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + dump_chan_xml(span, ftdm_channel_get_id(ftdm_iterator_current(curr)), stream); } + ftdm_iterator_free(chaniter); } } @@ -3646,12 +3663,12 @@ SWITCH_STANDARD_API(ft_function) dump_chan(span, chan_id, stream); } } else { - uint32_t j; - uint32_t ccount = ftdm_span_get_chan_count(span); stream->write_function(stream, "+OK\n"); - for (j = 1; j <= ccount; j++) { - dump_chan(span, j, stream); + chaniter = ftdm_span_get_chan_iterator(span, NULL); + for (curr = chaniter; curr; curr = ftdm_iterator_next(curr)) { + dump_chan(span, ftdm_channel_get_id(ftdm_iterator_current(curr)), stream); } + ftdm_iterator_free(chaniter); } } diff --git a/libs/freetdm/src/ftdm_io.c b/libs/freetdm/src/ftdm_io.c index b275403c85..6991e9ab9b 100644 --- a/libs/freetdm/src/ftdm_io.c +++ b/libs/freetdm/src/ftdm_io.c @@ -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); } @@ -3524,16 +3525,56 @@ done: return var; } -FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan) +static ftdm_iterator_t *get_iterator(ftdm_iterator_type_t type, ftdm_iterator_t *iter) { - ftdm_hash_iterator_t *iter = NULL; + int allocated = 0; + if (iter) { + if (iter->type != type) { + ftdm_log(FTDM_LOG_ERROR, "Cannot switch iterator types\n"); + return NULL; + } + allocated = iter->allocated; + memset(iter, 0, sizeof(*iter)); + iter->type = type; + iter->allocated = allocated; + return iter; + } + iter = ftdm_calloc(1, sizeof(*iter)); + if (!iter) { + return NULL; + } + iter->type = type; + iter->allocated = 1; + return iter; +} + +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); - - iter = ftdmchan->variable_hash == NULL ? NULL : hashtable_first(ftdmchan->variable_hash); - + 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; + } + iter->pvt.hashiter = hashiter; + return iter; +} + +FT_DECLARE(ftdm_iterator_t *) ftdm_span_get_chan_iterator(const ftdm_span_t *span, ftdm_iterator_t *iter) +{ + if (!(iter = get_iterator(FTDM_ITERATOR_CHANS, iter))) { + return NULL; + } + iter->pvt.chaniter.index = 1; + iter->pvt.chaniter.span = span; return iter; } @@ -3545,11 +3586,9 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, co *var_name = NULL; *var_val = NULL; - if (!iter) { - return FTDM_FAIL; - } + ftdm_assert_return(iter && (iter->type == FTDM_ITERATOR_VARS) && iter->pvt.hashiter, FTDM_FAIL, "Cannot get variable from invalid iterator!\n"); - hashtable_this(iter, &key, NULL, &val); + hashtable_this(iter->pvt.hashiter, &key, NULL, &val); *var_name = key; *var_val = val; @@ -3559,10 +3598,73 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, co FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter) { - if (!iter) { - return NULL; + ftdm_assert_return(iter && iter->type, NULL, "Invalid iterator\n"); + + switch (iter->type) { + case FTDM_ITERATOR_VARS: + if (!iter->pvt.hashiter) { + return NULL; + } + iter->pvt.hashiter = hashtable_next(iter->pvt.hashiter); + if (!iter->pvt.hashiter) { + return NULL; + } + return iter; + case FTDM_ITERATOR_CHANS: + ftdm_assert_return(iter->pvt.chaniter.index, NULL, "channel iterator index cannot be zero!\n"); + if (iter->pvt.chaniter.index == iter->pvt.chaniter.span->chan_count) { + return NULL; + } + iter->pvt.chaniter.index++; + return iter; + default: + break; } - return hashtable_next(iter); + + ftdm_assert_return(0, NULL, "Unknown iterator type\n"); + return NULL; +} + +FT_DECLARE(void *) ftdm_iterator_current(ftdm_iterator_t *iter) +{ + const void *key = NULL; + void *val = NULL; + + ftdm_assert_return(iter && iter->type, NULL, "Invalid iterator\n"); + + switch (iter->type) { + case FTDM_ITERATOR_VARS: + hashtable_this(iter->pvt.hashiter, &key, NULL, &val); + /* I decided to return the key instead of the value since the value can be retrieved using the key */ + return (void *)key; + case FTDM_ITERATOR_CHANS: + ftdm_assert_return(iter->pvt.chaniter.index, NULL, "channel iterator index cannot be zero!\n"); + ftdm_assert_return(iter->pvt.chaniter.index <= iter->pvt.chaniter.span->chan_count, NULL, "channel iterator index bigger than span chan count!\n"); + return iter->pvt.chaniter.span->channels[iter->pvt.chaniter.index]; + default: + break; + } + + ftdm_assert_return(0, NULL, "Unknown iterator type\n"); + return NULL; +} + +FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter) +{ + /* it's valid to pass a NULL iterator, do not return failure */ + if (!iter) { + return FTDM_SUCCESS; + } + + if (!iter->allocated) { + memset(iter, 0, sizeof(*iter)); + return FTDM_SUCCESS; + } + + ftdm_assert_return(iter->type, FTDM_FAIL, "Cannot free invalid iterator\n"); + ftdm_safe_free(iter); + + return FTDM_SUCCESS; } static struct { @@ -4744,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; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c index 9ffd7097a3..08f340dc83 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.c @@ -189,7 +189,8 @@ ftdm_state_map_t sangoma_isdn_state_map = { ZSD_OUTBOUND, ZSM_UNACCEPTABLE, {FTDM_CHANNEL_STATE_DIALING, FTDM_END}, - {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, FTDM_CHANNEL_STATE_DOWN, FTDM_END} + {FTDM_CHANNEL_STATE_TERMINATING, FTDM_CHANNEL_STATE_HANGUP, FTDM_CHANNEL_STATE_PROGRESS, + FTDM_CHANNEL_STATE_PROGRESS_MEDIA, FTDM_CHANNEL_STATE_UP, FTDM_CHANNEL_STATE_DOWN, FTDM_END} }, { ZSD_OUTBOUND, @@ -471,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); @@ -558,6 +556,9 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) /* We are hangup local call because there was a glare, we are waiting for a RELEASE on this call, before we can process the saved call */ ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Waiting for RELEASE on hungup glared call\n"); + } else if (sngisdn_test_flag(sngisdn_info, FLAG_SEND_DISC)) { + /* Remote side sent a PROGRESS message, but cause indicates disconnect or T310 expired*/ + sngisdn_snd_disconnect(ftdmchan); } else { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Hanging up call upon local request!\n"); @@ -568,16 +569,15 @@ static void ftdm_sangoma_isdn_process_state_change(ftdm_channel_t *ftdmchan) if (ftdmchan->last_state == FTDM_CHANNEL_STATE_RING || ftdmchan->last_state == FTDM_CHANNEL_STATE_DIALING) { + sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); + sngisdn_snd_release(ftdmchan, 0); + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP)) { sng_isdn_set_avail_rate(ftdmchan->span, SNGISDN_AVAIL_DOWN); } - - sngisdn_set_flag(sngisdn_info, FLAG_LOCAL_ABORT); - sngisdn_snd_release(ftdmchan, 0); } else { sngisdn_snd_disconnect(ftdmchan); } - } /* now go to the HANGUP complete state */ @@ -691,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; @@ -702,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 */ @@ -731,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 */ @@ -743,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); @@ -757,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); @@ -764,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"); @@ -789,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); @@ -852,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; @@ -920,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 \n"); + stream->write_function(stream, "Usage: ftdm sangoma_isdn l1_stats \n"); status = FTDM_FAIL; goto done; } status = ftdm_span_find_by_name(argv[1], &span); if (FTDM_SUCCESS != status) { - stream->write_function(stream, "-ERR failed to find span by name %s\n", argv[2]); + 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(); diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h index 3f63fbc1d4..cd96a18fce 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn.h @@ -68,6 +68,7 @@ typedef enum { FLAG_GLARE = (1 << 6), FLAG_DELAYED_REL = (1 << 7), FLAG_SENT_PROCEED = (1 << 8), + FLAG_SEND_DISC = (1 << 9), } sngisdn_flag_t; @@ -127,6 +128,13 @@ typedef enum { SNGISDN_EVENT_RST_IND, } ftdm_sngisdn_event_id_t; +/* Only timers that can be cancelled are listed here */ +#define SNGISDN_NUM_TIMERS 1 +/* Increase NUM_TIMERS as number of ftdm_sngisdn_timer_t increases */ +typedef enum { + SNGISDN_TIMER_FACILITY = 0, +} ftdm_sngisdn_timer_t; + typedef struct sngisdn_glare_data { int16_t suId; uint32_t suInstId; @@ -148,6 +156,7 @@ typedef struct sngisdn_chan_data { uint8_t globalFlg; sngisdn_glare_data_t glare; + ftdm_timer_t *timers[SNGISDN_NUM_TIMERS]; } sngisdn_chan_data_t; /* Span specific data */ @@ -165,6 +174,7 @@ typedef struct sngisdn_span_data { uint8_t overlap_dial; uint8_t setup_arb; uint8_t facility; + int8_t facility_timeout; ftdm_sched_t *sched; ftdm_queue_t *event_queue; } sngisdn_span_data_t; @@ -223,8 +233,8 @@ typedef struct sngisdn_cc { ftdm_trunk_type_t trunktype; uint32_t last_suInstId; ftdm_mutex_t *mutex; - sngisdn_chan_data_t *active_spInstIds[MAX_INSTID]; - sngisdn_chan_data_t *active_suInstIds[MAX_INSTID]; + sngisdn_chan_data_t *active_spInstIds[MAX_INSTID+1]; + sngisdn_chan_data_t *active_suInstIds[MAX_INSTID+1]; }sngisdn_cc_t; /* Global sngisdn data */ @@ -233,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; @@ -349,12 +360,16 @@ void sngisdn_set_span_sig_status(ftdm_span_t *ftdmspan, ftdm_signaling_status_t void sngisdn_delayed_release(void* p_sngisdn_info); void sngisdn_delayed_connect(void* p_sngisdn_info); void sngisdn_delayed_disconnect(void* p_sngisdn_info); +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__ */ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c index ec44142303..361b389f96 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cfg.c @@ -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 */ @@ -249,11 +253,16 @@ ftdm_status_t ftmod_isdn_parse_cfg(ftdm_conf_parameter_t *ftdm_parameters, ftdm_ ftdm_span_set_bearer_capability(val, &span->default_caller_data.bearer_capability); } else if (!strcasecmp(var, "outbound-bearer_layer1")) { ftdm_span_set_bearer_layer1(val, &span->default_caller_data.bearer_layer1); + } else if (!strcasecmp(var, "facility-timeout")) { + signal_data->facility_timeout = atoi(val); + if (signal_data->facility_timeout < 0) { + signal_data->facility_timeout = 0; + } } else { 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; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c index 7aba6a66ce..5060cb6bba 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_cntrl.c @@ -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 diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c index f84e018f1e..942c2e4531 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cfg.c @@ -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; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c index f92eceda5e..cea8ac0173 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_cntrl.c @@ -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"); } } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c index c3d97e5c5c..e2e67eed19 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_hndl.c @@ -78,14 +78,13 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) } sngisdn_info->suInstId = get_unique_suInstId(suId); - sngisdn_info->spInstId = spInstId; + sngisdn_info->spInstId = spInstId; /* If this is a glared call that was previously saved, we moved all the info to the current call, so clear the glared saved data */ - if (sngisdn_info->glare.spInstId == spInstId) { clear_call_glare_data(sngisdn_info); - } + } ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); g_sngisdn_data.ccs[suId].active_suInstIds[sngisdn_info->suInstId] = sngisdn_info; @@ -105,7 +104,15 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) ftdmchan->caller_data.hangup_cause = FTDM_CAUSE_NORMAL_TEMPORARY_FAILURE; ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_CANCEL); 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); @@ -142,6 +149,10 @@ void sngisdn_process_con_ind (sngisdn_event_data_t *sngisdn_event) if (ret_val == 1) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "Expecting Caller name in FACILITY\n"); ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_GET_CALLERID); + /* Launch timer in case we never get a FACILITY msg */ + if (signal_data->facility_timeout) { + ftdm_sched_timer(signal_data->sched, "facility_timeout", signal_data->facility_timeout, sngisdn_facility_timeout, (void*) sngisdn_info, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); + } break; } else if (ret_val == 0) { strcpy(ftdmchan->caller_data.cid_name, retrieved_str); @@ -263,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)); @@ -289,6 +303,8 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + CnStEvnt *cnStEvnt = &sngisdn_event->event.cnStEvnt; ftdm_assert(!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE), "State change flag pending\n"); @@ -302,19 +318,49 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) suId, suInstId, spInstId, ces); switch(evntType) { + case MI_PROGRESS: + if (signal_data->switchtype == SNGISDN_SWITCH_NI2 && + cnStEvnt->causeDgn[0].eh.pres && cnStEvnt->causeDgn[0].causeVal.pres) { + + switch(cnStEvnt->causeDgn[0].causeVal.val) { + case 17: /* User Busy */ + case 18: /* No User responding */ + case 19: /* User alerting, no answer */ + case 21: /* Call rejected, the called party does not with to accept this call */ + case 27: /* Destination out of order */ + case 31: /* Normal, unspecified */ + case 34: /* Circuit/Channel congestion */ + case 41: /* Temporary failure */ + case 42: /* Switching equipment is experiencing a period of high traffic */ + case 47: /* Resource unavailable */ + case 58: /* Bearer Capability not available */ + case 63: /* Service or option not available */ + case 65: /* Bearer Cap not implemented, not supported */ + case 79: /* Service or option not implemented, unspecified */ + ftdm_log_chan(ftdmchan, FTDM_LOG_DEBUG, "Cause requires disconnect (cause:%d)\n", cnStEvnt->causeDgn[0].causeVal.val); + ftdmchan->caller_data.hangup_cause = cnStEvnt->causeDgn[0].causeVal.val; + + sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + goto sngisdn_process_cnst_ind_end; + } + } + /* fall-through */ case MI_ALERTING: case MI_CALLPROC: - case MI_PROGRESS: + switch(ftdmchan->state) { - case FTDM_CHANNEL_STATE_DIALING: - if (evntType == MI_PROGRESS) { + case FTDM_CHANNEL_STATE_DIALING: + if (evntType == MI_PROGRESS || + (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } else { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS); } break; case FTDM_CHANNEL_STATE_PROGRESS: - if (evntType == MI_PROGRESS) { + if (evntType == MI_PROGRESS || + (cnStEvnt->progInd.eh.pres && cnStEvnt->progInd.progDesc.val == IN_PD_IBAVAIL)) { ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_PROGRESS_MEDIA); } break; @@ -371,6 +417,7 @@ void sngisdn_process_cnst_ind (sngisdn_event_data_t *sngisdn_event) break; } +sngisdn_process_cnst_ind_end: ISDN_FUNC_TRACE_EXIT(__FUNCTION__); return; } @@ -638,12 +685,14 @@ void sngisdn_process_flc_ind (sngisdn_event_data_t *sngisdn_event) void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); + int16_t suId = sngisdn_event->suId; uint32_t suInstId = sngisdn_event->suInstId; uint32_t spInstId = sngisdn_event->spInstId; sngisdn_chan_data_t *sngisdn_info = sngisdn_event->sngisdn_info; ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; FacEvnt *facEvnt = &sngisdn_event->event.facEvnt; @@ -659,10 +708,16 @@ void sngisdn_process_fac_ind (sngisdn_event_data_t *sngisdn_event) if (sng_isdn_retrieve_facility_caller_name(facility_str, facEvnt->facElmt.facStr.len, retrieved_str) != FTDM_SUCCESS) { ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "Failed to retrieve Caller Name from Facility IE\n"); } + /* Cancel facility timeout */ + ftdm_sched_cancel_timer(signal_data->sched, &sngisdn_info->timers[SNGISDN_TIMER_FACILITY]); } ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); break; + case FTDM_CHANNEL_STATE_RING: + /* We received the caller ID Name in FACILITY, but its too late, facility-timeout already occurred */ + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_WARNING, "FACILITY received, but we already proceeded with call\n"); + break; default: /* We do not support other FACILITY types for now, so do nothing */ break; @@ -794,6 +849,14 @@ void sngisdn_process_sta_cfm (sngisdn_event_data_t *sngisdn_event) break; case 3: switch (ftdmchan->state) { + case FTDM_CHANNEL_STATE_PROGRESS: + /* T310 timer has expired */ + ftdmchan->caller_data.hangup_cause = staEvnt->causeDgn[0].causeVal.val; + ftdm_log_chan_msg(ftdmchan, FTDM_LOG_DEBUG, "T310 Timer expired, hanging up call\n"); + sngisdn_set_flag(sngisdn_info, FLAG_SEND_DISC); + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_TERMINATING); + + break; case FTDM_CHANNEL_STATE_UP: /* Remote side is still waiting for our CONNECT message */ if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_OUTBOUND)) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c index 6e8e0e81fd..80a85ceec8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_out.c @@ -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)) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c index 29cfb2330e..791c6b7d8c 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_stack_rcv.c @@ -45,8 +45,8 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); uint8_t bchan_no = 0; - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_chan_data_t *sngisdn_info = NULL; + sngisdn_event_data_t *sngisdn_event = NULL; ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Ind on unconfigured cc\n"); ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Ind on unconfigured dchan\n"); @@ -96,7 +96,7 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); memcpy(&sngisdn_event->event.conEvnt, conEvnt, sizeof(*conEvnt)); - + ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } @@ -104,8 +104,8 @@ void sngisdn_rcv_con_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Co void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, int16_t dChan, uint8_t ces) { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_chan_data_t *sngisdn_info = NULL; + sngisdn_event_data_t *sngisdn_event = NULL; ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Con Cfm on unconfigured cc\n"); ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Con Cfm on unconfigured dchan\n"); @@ -118,6 +118,7 @@ void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, Cn if (!sngisdn_info->spInstId) { ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); + sngisdn_info->spInstId = spInstId; g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); @@ -146,8 +147,8 @@ void sngisdn_rcv_con_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, Cn void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, CnStEvnt *cnStEvnt, uint8_t evntType, int16_t dChan, uint8_t ces) { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_chan_data_t *sngisdn_info = NULL; + sngisdn_event_data_t *sngisdn_event = NULL; ftdm_assert(g_sngisdn_data.ccs[suId].activation_done != 0, "Cnst Ind on unconfigured cc\n"); ftdm_assert(g_sngisdn_data.dchans[dChan].num_spans != 0, "Cnst Ind on unconfigured dchan\n"); @@ -160,6 +161,7 @@ void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, C if (!sngisdn_info->spInstId) { ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); + sngisdn_info->spInstId = spInstId; g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); @@ -188,15 +190,15 @@ void sngisdn_rcv_cnst_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, C memcpy(&sngisdn_event->event.cnStEvnt, cnStEvnt, sizeof(*cnStEvnt)); - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); + ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, DiscEvnt *discEvnt) { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_chan_data_t *sngisdn_info = NULL; + sngisdn_event_data_t *sngisdn_event = NULL; ftdm_assert(spInstId != 0, "Received DISCONNECT with invalid id"); @@ -207,13 +209,6 @@ void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, D ftdm_assert(0, "Inconsistent call states\n"); return; } - - if (!sngisdn_info->spInstId) { - ftdm_mutex_lock(g_sngisdn_data.ccs[suId].mutex); - sngisdn_info->spInstId = spInstId; - g_sngisdn_data.ccs[suId].active_spInstIds[spInstId] = sngisdn_info; - ftdm_mutex_unlock(g_sngisdn_data.ccs[suId].mutex); - } ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DISCONNECT (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); @@ -229,7 +224,7 @@ void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, D memcpy(&sngisdn_event->event.discEvnt, discEvnt, sizeof(*discEvnt)); - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); + ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } @@ -237,21 +232,22 @@ void sngisdn_rcv_disc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, D void sngisdn_rcv_rel_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RelEvnt *relEvnt) { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); - sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_chan_data_t *sngisdn_info = NULL; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { ftdm_log(FTDM_LOG_CRIT, "Could not find matching call suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); - ftdm_assert(0, "Inconsistent call states\n"); + /* 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; } ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RELEASE/RELEASE COMPLETE (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_REL_IND; @@ -270,7 +266,7 @@ void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, In { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { @@ -283,7 +279,7 @@ void sngisdn_rcv_dat_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, In ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received DATA IND suId:%u suInstId:%u spInstId:%u\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_DAT_IND; @@ -302,7 +298,7 @@ void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, S { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { @@ -315,7 +311,7 @@ void sngisdn_rcv_sshl_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, S ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_SSHL_IND; @@ -335,7 +331,7 @@ void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, S { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { @@ -348,7 +344,7 @@ void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, S ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received SSHL CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_SSHL_CFM; @@ -360,14 +356,14 @@ void sngisdn_rcv_sshl_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, S memcpy(&sngisdn_event->event.ssHlEvnt, ssHlEvnt, sizeof(*ssHlEvnt)); - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); + ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, RmRtEvnt *rmRtEvnt, uint8_t action) { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { @@ -380,7 +376,7 @@ void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, R ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RMRT IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_RMRT_IND; @@ -392,7 +388,7 @@ void sngisdn_rcv_rmrt_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, R memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt)); - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); + ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } @@ -400,7 +396,7 @@ void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, R { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { @@ -413,7 +409,7 @@ void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, R ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received RESUME/RETRIEVE CFM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_RMRT_CFM; @@ -425,7 +421,7 @@ void sngisdn_rcv_rmrt_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, R memcpy(&sngisdn_event->event.rmRtEvnt, rmRtEvnt, sizeof(*rmRtEvnt)); - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); + ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } @@ -433,7 +429,7 @@ void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, St { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { @@ -446,7 +442,7 @@ void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, St ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FLOW CONTROL IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_FLC_IND; @@ -457,7 +453,7 @@ void sngisdn_rcv_flc_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, St memcpy(&sngisdn_event->event.staEvnt, staEvnt, sizeof(*staEvnt)); - ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); + ftdm_queue_enqueue(((sngisdn_span_data_t*)sngisdn_info->ftdmchan->span->signal_data)->event_queue, sngisdn_event); ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } @@ -466,7 +462,7 @@ void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Fa { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { @@ -478,7 +474,7 @@ void sngisdn_rcv_fac_ind (int16_t suId, uint32_t suInstId, uint32_t spInstId, Fa ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received FACILITY IND (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_FAC_IND; @@ -499,7 +495,7 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); sngisdn_chan_data_t *sngisdn_info; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; if (!(spInstId && get_ftdmchan_by_spInstId(suId, spInstId, &sngisdn_info) == FTDM_SUCCESS) && !(suInstId && get_ftdmchan_by_suInstId(suId, suInstId, &sngisdn_info) == FTDM_SUCCESS)) { @@ -512,7 +508,7 @@ void sngisdn_rcv_sta_cfm (int16_t suId, uint32_t suInstId, uint32_t spInstId, St ftdm_log_chan(sngisdn_info->ftdmchan, FTDM_LOG_INFO, "Received STATUS CONFIRM (suId:%u suInstId:%u spInstId:%u)\n", suId, suInstId, spInstId); sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_STA_CFM; @@ -532,7 +528,7 @@ void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces ISDN_FUNC_TRACE_ENTER(__FUNCTION__); unsigned i; sngisdn_span_data_t *signal_data; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; ftdm_log(FTDM_LOG_INFO, "Received SERVICE IND (dChan:%d ces:%u)\n", dChan, ces); @@ -540,7 +536,7 @@ void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) { signal_data = g_sngisdn_data.dchans[dChan].spans[i]; sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_SRV_IND; @@ -550,7 +546,7 @@ void sngisdn_rcv_srv_ind (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces sngisdn_event->signal_data = signal_data; memcpy(&sngisdn_event->event.srvEvnt, srvEvnt, sizeof(*srvEvnt)); - ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event); + ftdm_queue_enqueue((signal_data)->event_queue, sngisdn_event); } ISDN_FUNC_TRACE_EXIT(__FUNCTION__); } @@ -560,8 +556,8 @@ void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); unsigned i; - sngisdn_span_data_t *signal_data; - sngisdn_event_data_t *sngisdn_event; + sngisdn_span_data_t *signal_data = NULL; + sngisdn_event_data_t *sngisdn_event = NULL; ftdm_log(FTDM_LOG_INFO, "Received SERVICE CFM (dChan:%d ces:%u)\n", dChan, ces); @@ -569,7 +565,7 @@ void sngisdn_rcv_srv_cfm (int16_t suId, Srv *srvEvnt, int16_t dChan, uint8_t ces for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) { signal_data = g_sngisdn_data.dchans[dChan].spans[i]; sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_SRV_CFM; @@ -588,16 +584,17 @@ void sngisdn_rcv_rst_ind (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces { ISDN_FUNC_TRACE_ENTER(__FUNCTION__); unsigned i; - sngisdn_span_data_t *signal_data; - sngisdn_event_data_t *sngisdn_event; + sngisdn_span_data_t *signal_data = NULL; + sngisdn_event_data_t *sngisdn_event = NULL; ftdm_log(FTDM_LOG_INFO, "Received RESTART IND (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType); /* Enqueue the event to each span within the dChan */ for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) { signal_data = g_sngisdn_data.dchans[dChan].spans[i]; + sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_RST_IND; @@ -618,7 +615,7 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces ISDN_FUNC_TRACE_ENTER(__FUNCTION__); unsigned i; sngisdn_span_data_t *signal_data; - sngisdn_event_data_t *sngisdn_event; + sngisdn_event_data_t *sngisdn_event = NULL; ftdm_log(FTDM_LOG_INFO, "Received RESTART CFM (dChan:%d ces:%u type:%u)\n", dChan, ces, evntType); @@ -626,7 +623,7 @@ void sngisdn_rcv_rst_cfm (int16_t suId, Rst *rstEvnt, int16_t dChan, uint8_t ces for(i=1; i<=g_sngisdn_data.dchans[dChan].num_spans; i++) { signal_data = g_sngisdn_data.dchans[dChan].spans[i]; sngisdn_event = ftdm_malloc(sizeof(*sngisdn_event)); - ftdm_assert(sngisdn_event, "Failed to allocate memory\n"); + ftdm_assert(sngisdn_event != NULL, "Failed to allocate memory\n"); memset(sngisdn_event, 0, sizeof(*sngisdn_event)); sngisdn_event->event_id = SNGISDN_EVENT_RST_CFM; @@ -645,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; } @@ -699,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; } @@ -907,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; } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c index 29e7994c87..db22fe5ce8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_isdn/ftmod_sangoma_isdn_support.c @@ -73,8 +73,10 @@ void __inline__ clear_call_glare_data(sngisdn_chan_data_t *sngisdn_info) sngisdn_info->glare.suInstId, sngisdn_info->glare.spInstId, sngisdn_info->suInstId, sngisdn_info->spInstId); - ftdm_mutex_lock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex); - g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_spInstIds[sngisdn_info->glare.spInstId]=NULL; + ftdm_mutex_lock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex); + if (sngisdn_info->glare.spInstId != sngisdn_info->spInstId) { + g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_spInstIds[sngisdn_info->glare.spInstId]=NULL; + } g_sngisdn_data.ccs[sngisdn_info->glare.suId].active_suInstIds[sngisdn_info->glare.suInstId]=NULL; ftdm_mutex_unlock(g_sngisdn_data.ccs[sngisdn_info->glare.suId].mutex); @@ -132,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; } @@ -427,6 +435,24 @@ void sngisdn_delayed_disconnect(void* p_sngisdn_info) return; } +void sngisdn_facility_timeout(void* p_sngisdn_info) +{ + sngisdn_chan_data_t *sngisdn_info = (sngisdn_chan_data_t*)p_sngisdn_info; + ftdm_channel_t *ftdmchan = sngisdn_info->ftdmchan; + sngisdn_span_data_t *signal_data = (sngisdn_span_data_t*) ftdmchan->span->signal_data; + + ftdm_mutex_lock(ftdmchan->mutex); + if (ftdmchan->state == FTDM_CHANNEL_STATE_GET_CALLERID) { + ftdm_log_chan(ftdmchan, FTDM_LOG_INFO, "Facility timeout reached proceeding with call (suId:%d suInstId:%u spInstId:%u)\n", + signal_data->cc_id, sngisdn_info->spInstId, sngisdn_info->suInstId); + + ftdm_set_state(ftdmchan, FTDM_CHANNEL_STATE_RING); + } + + ftdm_mutex_unlock(ftdmchan->mutex); + return; +} + ftdm_status_t sngisdn_check_free_ids(void) { unsigned i; @@ -534,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 diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c index c8c8bc3dd1..21ab1d32d2 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cfg.c @@ -213,7 +213,7 @@ int ft_to_sngss7_cfg_all(void) SS7_CRITICAL("MTP3 ROUTE %d configuration FAILED!\n", x); SS7_ASSERT } else { - SS7_INFO("MTP3 ROUTE %d configuration DONE!\n"); + SS7_INFO("MTP3 ROUTE %d configuration DONE!\n",x); } /* set the CONFIGURED flag */ @@ -229,7 +229,7 @@ int ft_to_sngss7_cfg_all(void) SS7_CRITICAL("MTP3 ROUTE 0 configuration FAILED!\n"); SS7_ASSERT } else { - SS7_INFO("MTP3 ROUTE %d configuration DONE!\n"); + SS7_INFO("MTP3 ROUTE 0 configuration DONE!\n"); } /* set the CONFIGURED flag */ @@ -444,8 +444,8 @@ int ftmod_ss7_mtp3_gen_config(void) cfg.t.cfg.s.snGen.tmr.t21.enb = TRUE; /* t21 - waiting to restart traffic routed through adjacent SP */ cfg.t.cfg.s.snGen.tmr.t21.val = 650; # if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || defined(TDS_ROLL_UPGRADE_SUPPORT)) - cfg.t.cfg.s.snGen.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */ - cfg.t.cfg.s.snGen.t26.val = 600; + cfg.t.cfg.s.snGen.tmr.t26.enb = TRUE; /* t26 - waiting to repeat traffic restart waiting message for ANSI */ + cfg.t.cfg.s.snGen.tmr.t26.val = 600; # endif #endif @@ -644,7 +644,7 @@ int ftmod_ss7_mtp2_dlsap_config(int id) cfg.t.cfg.s.sdDLSAP.memMac.region = S_REG; /* memory region and pool id for MAC */ cfg.t.cfg.s.sdDLSAP.memMac.pool = S_POOL; cfg.t.cfg.s.sdDLSAP.maxOutsFrms = MAX_SD_OUTSTANDING; /* maximum outstanding frames */ - cfg.t.cfg.s.sdDLSAP.errType = SD_ERR_NRM; + cfg.t.cfg.s.sdDLSAP.errType = k->mtp2.errorType; cfg.t.cfg.s.sdDLSAP.t1.enb = TRUE; /* timer 1 - Alignment Ready Timer */ cfg.t.cfg.s.sdDLSAP.t1.val = k->mtp2.t1; cfg.t.cfg.s.sdDLSAP.t2.enb = TRUE; /* timer 2 - Not Aligned Timer */ @@ -744,10 +744,6 @@ int ftmod_ss7_mtp3_dlsap_config(int id) cfg.t.cfg.s.snDLSAP.msgPrior = 0; /* management message priority */ cfg.t.cfg.s.snDLSAP.lnkType = k->mtp3.linkType; /* link type ANSI, ITU, BICI or CHINA */ cfg.t.cfg.s.snDLSAP.upSwtch = k->mtp3.switchType; /* user part switch type */ -# if (SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA) - cfg.t.cfg.s.snDLSAP.l2Type = LSN_MTP2_56KBPS; /* layer 2 type - 56kbps MTP2 link, 1.536Mbps MTP2 link or QSAAL link */ - cfg.t.cfg.s.snDLSAP.isCLink = FALSE; /* identifies if the link is a C type link.Required to check if sls has to be rotated.*/ -# endif cfg.t.cfg.s.snDLSAP.maxSLTtry = MAX_SLTM_RETRIES; /* maximun times to retry SLTM */ cfg.t.cfg.s.snDLSAP.p0QLen = 32; /* size of the priority 0 Q */ cfg.t.cfg.s.snDLSAP.p1QLen = 32; /* size of the priority 1 Q */ @@ -775,17 +771,46 @@ int ftmod_ss7_mtp3_dlsap_config(int id) cfg.t.cfg.s.snDLSAP.selector = 0; /* lower layer selector */ cfg.t.cfg.s.snDLSAP.mem.region = S_REG; /* memory region id */ cfg.t.cfg.s.snDLSAP.mem.pool = S_POOL; /* memory pool id */ -#if( SS7_ANS92 || SS7_ANS88 || SS7_ANS96 || SS7_CHINA ) - cfg.t.cfg.s.snDLSAP.dpcLen = DPC24; /* dpc length 24 bits */ -#else - cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */ -#endif cfg.t.cfg.s.snDLSAP.spId = k->mtp3.mtp2Id ;/* service provider id */ -#if (SS7_ITU88 || SS7_CHINA || SS7_TTC || SS7_NTT || SS7_BICI ) - cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */ -#else - cfg.t.cfg.s.snDLSAP.flushContFlag = TRUE; /* flush continue handling */ -#endif + + switch (k->mtp3.linkType) { + /**************************************************************************/ + case (LSN_SW_ANS): + case (LSN_SW_ANS96): + case (LSN_SW_CHINA): + cfg.t.cfg.s.snDLSAP.dpcLen = DPC24; /* dpc length 24 bits */ + cfg.t.cfg.s.snDLSAP.l2Type = LSN_MTP2_56KBPS; /* layer 2 type - 56kbps MTP2 link, 1.536Mbps MTP2 link or QSAAL link */ + cfg.t.cfg.s.snDLSAP.isCLink = FALSE; /* identifies if the link is a C type link.Required to check if sls has to be rotated.*/ + break; + /**************************************************************************/ + case (LSN_SW_ITU): + cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */ + break; + /**************************************************************************/ + default: + cfg.t.cfg.s.snDLSAP.dpcLen = DPC14; /* dpc length 14 bits */ + break; + /**************************************************************************/ + } /* switch (k->mtp3.linkType) */ + + switch (k->mtp3.linkType) { + /**************************************************************************/ + case (LSN_SW_ANS): + case (LSN_SW_ANS96): + cfg.t.cfg.s.snDLSAP.flushContFlag = TRUE; /* flush continue handling */ + break; + /**************************************************************************/ + case (LSN_SW_ITU): + case (LSN_SW_CHINA): + cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */ + break; + /**************************************************************************/ + default: + cfg.t.cfg.s.snDLSAP.flushContFlag = FALSE; /* flush continue handling */ + break; + /**************************************************************************/ + } /* switch (k->mtp3.linkType) */ + cfg.t.cfg.s.snDLSAP.tmr.t1.enb = TRUE; /* t1 - delay to avoid missequencing on changeover */ cfg.t.cfg.s.snDLSAP.tmr.t1.val = k->mtp3.t1; cfg.t.cfg.s.snDLSAP.tmr.t2.enb = TRUE; /* t2 - waiting for changeover ack */ @@ -900,7 +925,7 @@ int ftmod_ss7_mtp3_linkset_config(int id) { Pst pst; SnMngmt cfg; - U16 c; + int c; sng_link_set_t *k = &g_ftdm_sngss7_data.cfg.mtpLinkSet[id]; /* initalize the post structure */ @@ -927,12 +952,13 @@ int ftmod_ss7_mtp3_linkset_config(int id) cfg.t.cfg.s.snLnkSet.lnkSetType = k->linkType; /* link type */ cfg.t.cfg.s.snLnkSet.adjDpc = k->apc; /* adjacent DPC */ cfg.t.cfg.s.snLnkSet.nmbActLnkReqd = k->minActive; /* minimum number of active links */ - cfg.t.cfg.s.snLnkSet.nmbCmbLnkSet = 1; /* number of combined link sets */ - for (c = 0; c < LSN_MAXCMBLNK; c++) { - cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].cmbLnkSetId = c+1; + cfg.t.cfg.s.snLnkSet.nmbCmbLnkSet = k->numLinks; /* number of combined link sets */ + for(c = 0; c < k->numLinks;c++) { + cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].cmbLnkSetId = k->links[c]; cfg.t.cfg.s.snLnkSet.cmbLnkSet[c].lnkSetPrior = 0; } + return(sng_cfg_mtp3(&pst, &cfg)); } @@ -1209,12 +1235,12 @@ int ftmod_ss7_isup_ckt_config(int id) cfg.t.cfg.s.siCir.typeCntrl = k->typeCntrl; /* type of control */ cfg.t.cfg.s.siCir.contReq = FALSE; /* continuity check required */ #if (SI_218_COMP || SS7_ANS88 || SS7_ANS92 || SS7_ANS95 || SS7_BELL) - cfg.t.cfg.s.siCir.firstCic =; /* First cic in the circuit group */ - cfg.t.cfg.s.siCir.numCir =; /* Number of circuits in the circuit group */ + cfg.t.cfg.s.siCir.firstCic = 1; /* First cic in the circuit group */ + cfg.t.cfg.s.siCir.numCir = 24; /* Number of circuits in the circuit group */ cfg.t.cfg.s.siCir.nonSS7Con = TRUE; /* connecting to non SS7 network */ - cfg.t.cfg.s.siCir.outTrkGrpN =; /* outgoing trunk group number (For EXM) */ - cfg.t.cfg.s.siCir.cvrTrkClli =; /* Trunk Group number (For CVR validation) */ - cfg.t.cfg.s.siCir.clli =; /* common language location identifier */ + cfg.t.cfg.s.siCir.outTrkGrpN.length = 0; /* outgoing trunk group number (For EXM) */ + cfg.t.cfg.s.siCir.cvrTrkClli.length = 0; /* Trunk Group number (For CVR validation) */ + cfg.t.cfg.s.siCir.clli.length = 0; /* common language location identifier */ #endif cfg.t.cfg.s.siCir.cirTmr.t3.enb = TRUE; /* t3 timer - overload received */ cfg.t.cfg.s.siCir.cirTmr.t3.val = k->t3; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c index edb15604e5..20e1f27c9b 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cli.c @@ -48,8 +48,6 @@ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream); static ftdm_status_t handle_set_function_trace(ftdm_stream_handle_t *stream, int on, int level); static ftdm_status_t handle_set_message_trace(ftdm_stream_handle_t *stream, int on, int level); -static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose); -static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, int chan, int verbose); static ftdm_status_t handle_set_inhibit(ftdm_stream_handle_t *stream, char *name); static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *name); @@ -63,6 +61,21 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose); static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose); +static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int chan, int verbose); +static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int chan, int verbose); + +static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose); +static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose); + +static ftdm_status_t handle_activate_link(ftdm_stream_handle_t *stream, char *name); +static ftdm_status_t handle_deactivate_link(ftdm_stream_handle_t *stream, char *name); + +static ftdm_status_t handle_activate_linkset(ftdm_stream_handle_t *stream, char *name); +static ftdm_status_t handle_deactivate_linkset(ftdm_stream_handle_t *stream, char *name); + +static ftdm_status_t handle_tx_lpo(ftdm_stream_handle_t *stream, char *name); +static ftdm_status_t handle_tx_lpr(ftdm_stream_handle_t *stream, char *name); + static ftdm_status_t handle_status_link(ftdm_stream_handle_t *stream, char *name); static ftdm_status_t handle_status_linkset(ftdm_stream_handle_t *stream, char *name); @@ -282,20 +295,12 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha /**********************************************************************/ } /**************************************************************************/ - } else if (!strcasecmp(argv[c], "block")) { + } else if (!strcasecmp(argv[c], "inhibit")) { /**************************************************************************/ if (check_arg_count(argc, 2)) goto handle_cli_error_argc; c++; - if (!strcasecmp(argv[c], "span")) { - /**********************************************************************/ - if (check_arg_count(argc, 5)) goto handle_cli_error_argc; - - if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - - handle_set_blocks(stream, span, chan, verbose); - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "link")) { + if (!strcasecmp(argv[c], "link")) { /**********************************************************************/ if (check_arg_count(argc, 3)) goto handle_cli_error_argc; c++; @@ -309,7 +314,26 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha /**********************************************************************/ } /**************************************************************************/ - } else if (!strcasecmp(argv[c], "unblock")) { + } else if (!strcasecmp(argv[c], "uninhibit")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "link")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_set_uninhibit(stream, argv[c]); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"unblock\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "blo")) { /**************************************************************************/ if (check_arg_count(argc, 2)) goto handle_cli_error_argc; c++; @@ -320,18 +344,101 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; - handle_set_unblks(stream, span, chan, verbose); - /**********************************************************************/ - } else if (!strcasecmp(argv[c], "link")) { - /**********************************************************************/ - if (check_arg_count(argc, 3)) goto handle_cli_error_argc; - c++; - - handle_set_uninhibit(stream, argv[c]); + handle_tx_blo(stream, span, chan, verbose); /**********************************************************************/ } else { /**********************************************************************/ - stream->write_function(stream, "Unknown \"unblock\" command\n"); + stream->write_function(stream, "Unknown \"block\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "ubl")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + + handle_tx_ubl(stream, span, chan, verbose); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"ubl\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "cgb")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + c = c + 4; + + if (check_arg_count(argc, 7)) goto handle_cli_error_argc; + + if (!strcasecmp(argv[c], "range")) { + /******************************************************************/ + c++; + range = atoi(argv[c]); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"cgb range\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + + handle_tx_cgb(stream, span, chan, range, verbose); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"cgb\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "cgu")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "span")) { + /**********************************************************************/ + if (check_arg_count(argc, 5)) goto handle_cli_error_argc; + + if (extract_span_chan(argv, c, &span, &chan)) goto handle_cli_error_span_chan; + c = c + 4; + + if (check_arg_count(argc, 7)) goto handle_cli_error_argc; + + if (!strcasecmp(argv[c], "range")) { + /******************************************************************/ + c++; + range = atoi(argv[c]); + /******************************************************************/ + } else { + /******************************************************************/ + stream->write_function(stream, "Unknown \"cgu range\" command\n"); + goto handle_cli_error; + /******************************************************************/ + } + + handle_tx_cgu(stream, span, chan, range, verbose); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"cgu\" command\n"); goto handle_cli_error; /**********************************************************************/ } @@ -389,7 +496,97 @@ ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const cha stream->write_function(stream, "Unknown \"grs\" command\n"); goto handle_cli_error; /**********************************************************************/ - } + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "lpo")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "link")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_tx_lpo(stream, argv[c]); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"lpo\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "lpr")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "link")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_tx_lpr(stream, argv[c]); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"lpr\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "activate")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "link")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_activate_link(stream, argv[c]); + /**********************************************************************/ + }else if (!strcasecmp(argv[c], "linkset")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_activate_linkset(stream, argv[c]); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"activate\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } + /**************************************************************************/ + } else if (!strcasecmp(argv[c], "deactivate")) { + /**************************************************************************/ + if (check_arg_count(argc, 2)) goto handle_cli_error_argc; + c++; + + if (!strcasecmp(argv[c], "link")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_deactivate_link(stream, argv[c]); + /**********************************************************************/ + }else if (!strcasecmp(argv[c], "linkset")) { + /**********************************************************************/ + if (check_arg_count(argc, 3)) goto handle_cli_error_argc; + c++; + + handle_deactivate_linkset(stream, argv[c]); + /**********************************************************************/ + } else { + /**********************************************************************/ + stream->write_function(stream, "Unknown \"deactivate\" command\n"); + goto handle_cli_error; + /**********************************************************************/ + } /**************************************************************************/ } else { /**************************************************************************/ @@ -433,10 +630,22 @@ static ftdm_status_t handle_print_usuage(ftdm_stream_handle_t *stream) stream->write_function(stream, "ftdm ss7 show inreset span X chan Y\n"); stream->write_function(stream, "\n"); stream->write_function(stream, "Ftmod_sangoma_ss7 circuit control:\n"); - stream->write_function(stream, "ftdm ss7 block span X chan Y\n"); - stream->write_function(stream, "ftdm ss7 unblk span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 blo span X chan Y\n"); + stream->write_function(stream, "ftdm ss7 ubl span X chan Y\n"); stream->write_function(stream, "ftdm ss7 rsc span X chan Y\n"); stream->write_function(stream, "ftdm ss7 grs span X chan Y range Z\n"); + stream->write_function(stream, "ftdm ss7 cgb span X chan Y range Z\n"); + stream->write_function(stream, "ftdm ss7 cgu span X chan Y range Z\n"); + stream->write_function(stream, "\n"); + stream->write_function(stream, "Ftmod_sangoma_ss7 link control:\n"); + stream->write_function(stream, "ftdm ss7 inhibit link X\n"); + stream->write_function(stream, "ftdm ss7 uninhibit link X\n"); + stream->write_function(stream, "ftdm ss7 activate link X\n"); + stream->write_function(stream, "ftdm ss7 deactivate link X\n"); + stream->write_function(stream, "ftdm ss7 activate linkset X\n"); + stream->write_function(stream, "ftdm ss7 deactivate linkset X\n"); + stream->write_function(stream, "ftdm ss7 lpo link X\n"); + stream->write_function(stream, "ftdm ss7 lpr link X\n"); stream->write_function(stream, "\n"); return FTDM_SUCCESS; @@ -811,87 +1020,100 @@ static ftdm_status_t handle_show_blocks(ftdm_stream_handle_t *stream, int span, /******************************************************************************/ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; - ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; + int x; + sngss7_chan_data_t *ss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; + ftdm_signaling_status_t sigstatus = FTDM_SIG_STATE_DOWN; + sng_isup_ckt_t *ckt; x=1; while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; + /* extract the circuit to make it easier to work with */ + ckt = &g_ftdm_sngss7_data.cfg.isupCkt[x]; /* if span == 0 then all spans should be printed */ if (span == 0) { - lspan = ftdmchan->physical_span_id; + lspan = ckt->span; } else { lspan = span; } /* if chan == 0 then all chans should be printed */ if (chan == 0) { - lchan = ftdmchan->physical_chan_id; + lchan = ckt->chan; } else { lchan = chan; } - if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - /* grab the signaling_status */ - ftdm_channel_get_sig_status(ftdmchan, &sigstatus); + /* check if this circuit is one of the circuits we're interested in */ + if ((ckt->span == lspan) && (ckt->chan == lchan)) { + if (ckt->type == HOLE) { + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|NOT USED\n", + ckt->span, + ckt->chan, + ckt->cic); + } else if (ckt->type == SIG) { + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|SIGNALING LINK\n", + ckt->span, + ckt->chan, + ckt->cic); + } else { + ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = ss7_info->ftdmchan; - stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%s|state=%s|", - ftdmchan->physical_span_id, - ftdmchan->physical_chan_id, - ss7_info->circuit->cic, - ftdm_signaling_status2str(sigstatus), - ftdm_channel_state2str(ftdmchan->state)); - - if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { - stream->write_function(stream, "l_mn=Y|"); - }else { - stream->write_function(stream, "l_mn=N|"); - } - - if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { - stream->write_function(stream, "r_mn=Y|"); - }else { - stream->write_function(stream, "r_mn=N|"); - } - - if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { - stream->write_function(stream, "l_hw=Y|"); - }else { - stream->write_function(stream, "l_hw=N|"); - } - - if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { - stream->write_function(stream, "r_hw=Y|"); - }else { - stream->write_function(stream, "r_hw=N|"); - } - - if(sngss7_test_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) { - stream->write_function(stream, "l_mngmt=Y|"); - }else { - stream->write_function(stream, "l_mngmt=N|"); - } - - if(sngss7_test_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) { - stream->write_function(stream, "l_ucic=Y|"); - }else { - stream->write_function(stream, "l_ucic=N|"); - } - - stream->write_function(stream, "flags=0x%X",ss7_info->flags); - - stream->write_function(stream, "\n"); + /* grab the signaling_status */ + ftdm_channel_get_sig_status(ftdmchan, &sigstatus); + + stream->write_function(stream, "span=%2d|chan=%2d|cic=%4d|sig_status=%s|state=%s|", + ckt->span, + ckt->chan, + ckt->cic, + ftdm_signaling_status2str(sigstatus), + ftdm_channel_state2str(ftdmchan->state)); + + if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_TX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_TX))) { + stream->write_function(stream, "l_mn=Y|"); + }else { + stream->write_function(stream, "l_mn=N|"); + } + + if((sngss7_test_flag(ss7_info, FLAG_CKT_MN_BLOCK_RX)) || (sngss7_test_flag(ss7_info, FLAG_GRP_MN_BLOCK_RX))) { + stream->write_function(stream, "r_mn=Y|"); + }else { + stream->write_function(stream, "r_mn=N|"); + } + + if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_TX)) { + stream->write_function(stream, "l_hw=Y|"); + }else { + stream->write_function(stream, "l_hw=N|"); + } + + if(sngss7_test_flag(ss7_info, FLAG_GRP_HW_BLOCK_RX)) { + stream->write_function(stream, "r_hw=Y|"); + }else { + stream->write_function(stream, "r_hw=N|"); + } + + if(sngss7_test_flag(ss7_info, FLAG_CKT_LC_BLOCK_RX)) { + stream->write_function(stream, "l_mngmt=Y|"); + }else { + stream->write_function(stream, "l_mngmt=N|"); + } + + if(sngss7_test_flag(ss7_info, FLAG_CKT_UCIC_BLOCK)) { + stream->write_function(stream, "l_ucic=Y|"); + }else { + stream->write_function(stream, "l_ucic=N|"); + } + + stream->write_function(stream, "flags=0x%X",ss7_info->flags); + + stream->write_function(stream, "\n"); + } /* if ( hole, sig, voice) */ } /* if ( span and chan) */ - - } /* if ( cic != 0) */ - /* go the next circuit */ x++; } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ @@ -899,7 +1121,7 @@ static ftdm_status_t handle_show_status(ftdm_stream_handle_t *stream, int span, return FTDM_SUCCESS; } /******************************************************************************/ -static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, int chan, int verbose) +static ftdm_status_t handle_tx_blo(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { int x; sngss7_chan_data_t *ss7_info; @@ -960,7 +1182,7 @@ static ftdm_status_t handle_set_blocks(ftdm_stream_handle_t *stream, int span, i } /******************************************************************************/ -static ftdm_status_t handle_set_unblks(ftdm_stream_handle_t *stream, int span, int chan, int verbose) +static ftdm_status_t handle_tx_ubl(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { int x; sngss7_chan_data_t *ss7_info; @@ -1154,17 +1376,17 @@ static ftdm_status_t handle_set_uninhibit(ftdm_stream_handle_t *stream, char *na /******************************************************************************/ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int chan, int verbose) { - int x; - sngss7_chan_data_t *ss7_info; - ftdm_channel_t *ftdmchan; - int lspan; - int lchan; + int x; + sngss7_chan_data_t *sngss7_info; + ftdm_channel_t *ftdmchan; + int lspan; + int lchan; x=1; while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { - ss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; - ftdmchan = ss7_info->ftdmchan; + sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = sngss7_info->ftdmchan; /* if span == 0 then all spans should be printed */ if (span == 0) { @@ -1181,27 +1403,31 @@ static ftdm_status_t handle_tx_rsc(ftdm_stream_handle_t *stream, int span, int c } if ((ftdmchan->physical_span_id == lspan) && (ftdmchan->physical_chan_id == lchan)) { - /* now that we have the right channel...put a lock on it so no-one else can use it */ + /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); - /* check if there is a pending state change|give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", ss7_info->circuit->cic); - SS7_ASSERT; - } else { - /* throw the ckt block flag */ - sngss7_set_flag(ss7_info, FLAG_RESET_TX); + /* throw the reset flag */ + sngss7_set_flag(sngss7_info, FLAG_RESET_TX); - /* set the channel to suspended state */ + switch (ftdmchan->state) { + /**************************************************************************/ + case FTDM_CHANNEL_STATE_RESTART: + /* go to idle so that we can redo the restart state*/ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_IDLE); + break; + /**************************************************************************/ + default: + /* set the state of the channel to restart...the rest is done by the chan monitor */ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_RESTART); + break; + /**************************************************************************/ } - + /* unlock the channel again before we exit */ ftdm_mutex_unlock(ftdmchan->mutex); - } /* if ( span and chan) */ - } /* if ( cic != 0) */ + } /* if ( cic == voice) */ /* go the next circuit */ x++; @@ -1270,6 +1496,331 @@ static ftdm_status_t handle_tx_grs(ftdm_stream_handle_t *stream, int span, int c return FTDM_SUCCESS; } +/******************************************************************************/ +static ftdm_status_t handle_tx_cgb(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose) +{ + int x; + sngss7_chan_data_t *sngss7_info; + ftdm_channel_t *ftdmchan; + ftdm_channel_t *main_chan = NULL; + sngss7_span_data_t *sngss7_span; + int byte = 0; + int bit = 0; + + if (range > 31) { + stream->write_function(stream, "Invalid range value %d", range); + return FTDM_SUCCESS; + } + + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + + /* extract the channel and span info for this circuit */ + sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = sngss7_info->ftdmchan; + sngss7_span = ftdmchan->span->mod_data; + + /* check if this circuit is part of the block */ + if ((ftdmchan->physical_span_id == span) && + ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* throw the grp maint. block flag */ + sngss7_set_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX); + + /* if this is the first channel in the range */ + if (ftdmchan->physical_chan_id == chan) { + /* attach the cgb information */ + main_chan = ftdmchan; + sngss7_span->tx_cgb.circuit = sngss7_info->circuit->id; + sngss7_span->tx_cgb.range = range-1; + sngss7_span->tx_cgb.type = 0; /* maintenace block */ + } /* if (ftdmchan->physical_chan_id == chan) */ + + /* update the status field */ + sngss7_span->tx_cgb.status[byte] = (sngss7_span->tx_cgb.status[byte] | (1 << bit)); + + /* update the bit and byte counter*/ + bit ++; + if (bit == 8) { + byte++; + bit = 0; + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + } /* if ( span and chan) */ + } /* if ( cic == voice) */ + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + + /* send the circuit group block */ + ft_to_sngss7_cgb(main_chan); + + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_tx_cgu(ftdm_stream_handle_t *stream, int span, int chan, int range, int verbose) +{ + int x; + sngss7_chan_data_t *sngss7_info; + ftdm_channel_t *ftdmchan; + ftdm_channel_t *main_chan = NULL; + sngss7_span_data_t *sngss7_span; + int byte = 0; + int bit = 0; + + if (range > 31) { + stream->write_function(stream, "Invalid range value %d", range); + return FTDM_SUCCESS; + } + + x=1; + while (g_ftdm_sngss7_data.cfg.isupCkt[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type == VOICE) { + + /* extract the channel and span info for this circuit */ + sngss7_info = (sngss7_chan_data_t *)g_ftdm_sngss7_data.cfg.isupCkt[x].obj; + ftdmchan = sngss7_info->ftdmchan; + sngss7_span = ftdmchan->span->mod_data; + + /* check if this circuit is part of the block */ + if ((ftdmchan->physical_span_id == span) && + ((ftdmchan->physical_chan_id >= chan) && (ftdmchan->physical_chan_id < (chan+range)))) { + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* throw the grp maint. block flag */ + sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_TX); + + /* if this is the first channel in the range */ + if (ftdmchan->physical_chan_id == chan) { + /* attach the cgb information */ + main_chan = ftdmchan; + sngss7_span->tx_cgu.circuit = sngss7_info->circuit->id; + sngss7_span->tx_cgu.range = range-1; + sngss7_span->tx_cgu.type = 0; /* maintenace block */ + } /* if (ftdmchan->physical_chan_id == chan) */ + + /* update the status field */ + sngss7_span->tx_cgu.status[byte] = (sngss7_span->tx_cgu.status[byte] | (1 << bit)); + + /* update the bit and byte counter*/ + bit ++; + if (bit == 8) { + byte++; + bit = 0; + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + } /* if ( span and chan) */ + } /* if ( cic == voice) */ + /* go the next circuit */ + x++; + } /* while (g_ftdm_sngss7_data.cfg.isupCkt[x]id != 0) */ + + /* send the circuit group block */ + ft_to_sngss7_cgu(main_chan); + + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_activate_link(ftdm_stream_handle_t *stream, char *name) +{ + int x = 0; + + /* find the link request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) { + + /* send the uninhibit request */ + if (ftmod_ss7_activate_mtplink(x)) { + stream->write_function(stream, "Failed to activate link=%s\n", name); + return FTDM_FAIL; + } + + /* print the new status of the link */ + handle_status_link(stream, &name[0]); + goto success; + } + + /* move to the next link */ + x++; + } /* while (id != 0) */ + + stream->write_function(stream, "Could not find link=%s\n", name); + +success: + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_deactivate_link(ftdm_stream_handle_t *stream, char *name) +{ + int x = 0; + + /* find the link request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) { + + /* send the deactivate request */ + if (ftmod_ss7_deactivate2_mtplink(x)) { + stream->write_function(stream, "Failed to deactivate link=%s\n", name); + return FTDM_FAIL; + } + + /* print the new status of the link */ + handle_status_link(stream, &name[0]); + goto success; + } + + /* move to the next link */ + x++; + } /* while (id != 0) */ + + stream->write_function(stream, "Could not find link=%s\n", name); + +success: + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_activate_linkset(ftdm_stream_handle_t *stream, char *name) +{ + int x = 0; + + /* find the linkset request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, name)) { + + /* send the activate request */ + if (ftmod_ss7_activate_mtplinkSet(x)) { + stream->write_function(stream, "Failed to activate linkset=%s\n", name); + return FTDM_FAIL; + } + + /* print the new status of the linkset */ + handle_status_linkset(stream, &name[0]); + goto success; + } + + /* move to the next linkset */ + x++; + } /* while (id != 0) */ + + stream->write_function(stream, "Could not find linkset=%s\n", name); + +success: + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_deactivate_linkset(ftdm_stream_handle_t *stream, char *name) +{ + int x = 0; + + /* find the linkset request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, name)) { + + /* send the deactivate request */ + if (ftmod_ss7_deactivate2_mtplinkSet(x)) { + stream->write_function(stream, "Failed to deactivate linkset=%s\n", name); + return FTDM_FAIL; + } + + /* print the new status of the linkset */ + handle_status_linkset(stream, &name[0]); + goto success; + } + + /* move to the next linkset */ + x++; + } /* while (id != 0) */ + + stream->write_function(stream, "Could not find linkset=%s\n", name); + +success: + return FTDM_SUCCESS; +} + +/******************************************************************************/ + +static ftdm_status_t handle_tx_lpo(ftdm_stream_handle_t *stream, char *name) +{ + int x = 0; + + /* find the link request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) { + + /* send the uninhibit request */ + if (ftmod_ss7_lpo_mtplink(x)) { + stream->write_function(stream, "Failed set LPO link=%s\n", name); + return FTDM_FAIL; + } + + /* print the new status of the link */ + handle_status_link(stream, &name[0]); + goto success; + } + + /* move to the next link */ + x++; + } /* while (id != 0) */ + + stream->write_function(stream, "Could not find link=%s\n", name); + +success: + return FTDM_SUCCESS; +} + +/******************************************************************************/ +static ftdm_status_t handle_tx_lpr(ftdm_stream_handle_t *stream, char *name) +{ + int x = 0; + + /* find the link request by it's name */ + x = 1; + while(g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpLink[x].name, name)) { + + /* send the uninhibit request */ + if (ftmod_ss7_lpr_mtplink(x)) { + stream->write_function(stream, "Failed set LPR link=%s\n", name); + return FTDM_FAIL; + } + + /* print the new status of the link */ + handle_status_link(stream, &name[0]); + goto success; + } + + /* move to the next link */ + x++; + } /* while (id != 0) */ + + stream->write_function(stream, "Could not find link=%s\n", name); + +success: + return FTDM_SUCCESS; +} + /******************************************************************************/ static ftdm_status_t extract_span_chan(char *argv[10], int pos, int *span, int *chan) { diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c index 52b3860375..0d76329d25 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_cntrl.c @@ -50,6 +50,17 @@ static int ftmod_ss7_enable_mtpLinkSet(int lnkSetId); int ftmod_ss7_inhibit_mtplink(uint32_t id); int ftmod_ss7_uninhibit_mtplink(uint32_t id); + +int ftmod_ss7_activate_mtplink(uint32_t id); +int ftmod_ss7_deactivate_mtplink(uint32_t id); +int ftmod_ss7_deactivate2_mtplink(uint32_t id); + +int ftmod_ss7_activate_mtplinkSet(uint32_t id); +int ftmod_ss7_deactivate_mtplinkSet(uint32_t id); +int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id); + +int ftmod_ss7_lpo_mtplink(uint32_t id); +int ftmod_ss7_lpr_mtplink(uint32_t id); /******************************************************************************/ /* FUNCTIONS ******************************************************************/ @@ -271,6 +282,248 @@ int ftmod_ss7_uninhibit_mtplink(uint32_t id) return (sng_cntrl_mtp3(&pst, &cntrl)); } +/******************************************************************************/ +int ftmod_ss7_activate_mtplink(uint32_t id) +{ + SnMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SnMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSN; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STDLSAP; + cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id; + + cntrl.t.cntrl.action = AENA; /* Activate */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_mtp3(&pst, &cntrl)); +} + +/******************************************************************************/ +int ftmod_ss7_deactivate_mtplink(uint32_t id) +{ + SnMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SnMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSN; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STDLSAP; + cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id; + + cntrl.t.cntrl.action = ADISIMM; /* Deactivate */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_mtp3(&pst, &cntrl)); +} + +/******************************************************************************/ +int ftmod_ss7_deactivate2_mtplink(uint32_t id) +{ + SnMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SnMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSN; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STDLSAP; + cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id; + + cntrl.t.cntrl.action = ADISIMM_L2; /* Deactivate...layer 2 only */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_mtp3(&pst, &cntrl)); +} + +/******************************************************************************/ +int ftmod_ss7_activate_mtplinkSet(uint32_t id) +{ + SnMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SnMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSN; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STLNKSET; + cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id; + + cntrl.t.cntrl.action = AACTLNKSET; /* Activate */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_mtp3(&pst, &cntrl)); +} + +/******************************************************************************/ +int ftmod_ss7_deactivate_mtplinkSet(uint32_t id) +{ + SnMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SnMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSN; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STLNKSET; + cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id; + + cntrl.t.cntrl.action = ADEACTLNKSET; /* Activate */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_mtp3(&pst, &cntrl)); +} + +/******************************************************************************/ +int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id) +{ + SnMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SnMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSN; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STLNKSET; + cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id; + + cntrl.t.cntrl.action = ADEACTLNKSET_L2; /* Activate */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_mtp3(&pst, &cntrl)); +} + +/******************************************************************************/ +int ftmod_ss7_lpo_mtplink(uint32_t id) +{ + SnMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SnMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSN; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STDLSAP; + cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id; + + cntrl.t.cntrl.action = ACTION_LPO; /* Activate */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_mtp3(&pst, &cntrl)); +} + +/******************************************************************************/ +int ftmod_ss7_lpr_mtplink(uint32_t id) +{ + SnMngmt cntrl; + Pst pst; + + /* initalize the post structure */ + smPstInit(&pst); + + /* insert the destination Entity */ + pst.dstEnt = ENTSN; + + /* initalize the control structure */ + memset(&cntrl, 0x0, sizeof(SnMngmt)); + + /* initalize the control header */ + smHdrInit(&cntrl.hdr); + + cntrl.hdr.msgType = TCNTRL; /* this is a control request */ + cntrl.hdr.entId.ent = ENTSN; + cntrl.hdr.entId.inst = S_INST; + cntrl.hdr.elmId.elmnt = STDLSAP; + cntrl.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLink[id].id; + + cntrl.t.cntrl.action = ACTION_LPR; /* Activate */ + cntrl.t.cntrl.subAction = SAELMNT; /* specificed element */ + + return (sng_cntrl_mtp3(&pst, &cntrl)); +} + +/******************************************************************************/ + /******************************************************************************/ /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c index f0cfa0237a..263b599ddc 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_handle.c @@ -71,6 +71,8 @@ ftdm_status_t handle_ubl_rsp(uint32_t suInstId, uint32_t spInstId, uint32_t circ ftdm_status_t handle_local_blk(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); ftdm_status_t handle_local_ubl(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); +ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); /******************************************************************************/ /* FUNCTIONS ******************************************************************/ @@ -80,6 +82,9 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ sngss7_chan_data_t *sngss7_info = NULL; ftdm_channel_t *ftdmchan = NULL; + char nadi[2]; + + memset(nadi, '\0', sizeof(nadi)); /* get the ftdmchan and ss7_chan_data from the circuit */ if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { @@ -210,7 +215,8 @@ ftdm_status_t handle_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ } /* add any special variables for the dialplan */ - /*ftdm_channel_add_var(ftdmchan, "ss7_stuff", "s");*/ + sprintf(nadi, "%d", siConEvnt->cgPtyNum.natAddrInd.val); + ftdm_channel_add_var(ftdmchan, "ss7_nadi", nadi); /* set the state of the channel to collecting...the rest is done by the chan monitor */ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_COLLECT); @@ -898,12 +904,12 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ /**************************************************************************/ case SIT_STA_CGBREQ: /* CGB request */ SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CGUREQ: /* CGU request */ SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGU\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + handle_cgu_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt); break; /**************************************************************************/ case SIT_STA_CGQRYREQ: /* circuit group query request */ @@ -913,12 +919,12 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ /**************************************************************************/ case SIT_STA_CGBRSP: /* mntc. oriented CGB response */ SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGB\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + /*handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/ break; /**************************************************************************/ case SIT_STA_CGURSP: /* mntc. oriented CGU response */ SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx mntc CGU\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + /*SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType));*/ break; /**************************************************************************/ case SIT_STA_GRSREQ: /* circuit group reset request */ @@ -1012,13 +1018,13 @@ ftdm_status_t handle_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circ break; /**************************************************************************/ case SIT_STA_CGBINFOIND: /* circuit grp blking ind , no resp req */ - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); + /*SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx CGB no resp req\n");*/ +/* handle_cgb_req(suInstId, spInstId, circuit, globalFlg, evntType, siStaEvnt);*/ break; /**************************************************************************/ case SIT_STA_LMCQMINFOREQ: /* when LM requests ckt grp query */ SS7_MSG_TRACE(ftdmchan, sngss7_info, "Rx LM CQM\n"); - SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); +// SS7_WARN(" %s indication not currently supported\n", DECODE_LCC_EVENT(evntType)); break; /**************************************************************************/ case SIT_STA_CIRLOCGRS: /* group reset initiated locally by the software */ @@ -1121,21 +1127,10 @@ ftdm_status_t handle_pause(uint32_t suInstId, uint32_t spInstId, uint32_t circui /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - i++; - SS7_ASSERT; - }; - /* check if the circuit is fully started */ if (ftdm_test_flag(ftdmchan->span, FTDM_SPAN_IN_THREAD)) { /* set the pause flag on the channel */ sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED); - - /* set the statet o SUSPENDED to bring the sig status down */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); } /* unlock the channel again before we exit */ @@ -1183,14 +1178,6 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu /* lock the channel */ ftdm_mutex_lock(ftdmchan->mutex); - /* check if there is a pending state change, give it a bit to clear */ - if (check_for_state_change(ftdmchan)) { - SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); - ftdm_mutex_unlock(ftdmchan->mutex); - i++; - SS7_ASSERT; - }; - /* only resume if we are paused */ if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { /* set the resume flag on the channel */ @@ -1198,9 +1185,6 @@ ftdm_status_t handle_resume(uint32_t suInstId, uint32_t spInstId, uint32_t circu /* clear the paused flag */ sngss7_clear_flag(sngss7_info, FLAG_INFID_PAUSED); - - /* set the statet to SUSPENDED to bring the sig status up */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); } /* unlock the channel again before we exit */ @@ -1713,6 +1697,7 @@ ftdm_status_t handle_grs_req(uint32_t suInstId, uint32_t spInstId, uint32_t circ /* loop over the cics starting from circuit until range+1 */ for (x = circuit; x < (circuit + range + 1); x++) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != VOICE) continue; /* grab the circuit in question */ if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x); @@ -1989,6 +1974,267 @@ ftdm_status_t handle_ucic(uint32_t suInstId, uint32_t spInstId, uint32_t circuit return FTDM_SUCCESS; } +/******************************************************************************/ +ftdm_status_t handle_cgb_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_span_data_t *sngss7_span = NULL; + ftdm_channel_t *ftdmchan = NULL; + int range; + uint8_t status[255]; + int blockType = 0; + int byte = 0; + int bit = 0; + int x; + + memset(&status[0], '\0', sizeof(status)); + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* grab the span info */ + sngss7_span = ftdmchan->span->mod_data; + + /* figure out what type of block needs to be applied */ + if ((siStaEvnt->cgsmti.eh.pres == PRSNT_NODEF) && (siStaEvnt->cgsmti.typeInd.pres == PRSNT_NODEF)) { + blockType = siStaEvnt->cgsmti.typeInd.val; + } else { + SS7_ERROR("Received CGB with no circuit group supervision value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* pull out the range value */ + if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { + range = siStaEvnt->rangStat.range.val; + } else { + SS7_ERROR("Received CGB with no range value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* pull out the status field */ + if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.status.pres == PRSNT_NODEF)) { + for (x = 0; x < siStaEvnt->rangStat.status.len; x++) { + status[x] = siStaEvnt->rangStat.status.val[x]; + } + } else { + SS7_ERROR("Received CGB with no status value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* save the circuit, range and status */ + sngss7_span->rx_cgb.circuit = circuit; + sngss7_span->rx_cgb.range = range; + sngss7_span->rx_cgb.type = blockType; + for (x = 0; x < siStaEvnt->rangStat.status.len; x++) { + sngss7_span->rx_cgb.status[x] = status[x]; + } + + /* loop over the cics starting from circuit until range+1 */ + for (x = circuit; x < (circuit + range + 1); x++) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != VOICE) continue; + /* grab the circuit in question */ + if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x); + break; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_ASSERT; + }; + +#if 0 + SS7_ERROR("KONRAD -> circuit=%d, byte=%d, bit=%d, status[byte]=%d, math=%d\n", + x, + byte, + bit, + status[byte], + (status[byte] & (1 << bit))); +#endif + if (status[byte] & (1 << bit)) { + switch (blockType) { + /**********************************************************************/ + case 0: /* maintenance oriented */ + sngss7_set_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); + break; + /**********************************************************************/ + case 1: /* hardware failure oriented */ + sngss7_set_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); + break; + /**********************************************************************/ + case 2: /* reserved for national use */ + break; + /**********************************************************************/ + default: + break; + /**********************************************************************/ + } /* switch (blockType) */ + } + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + /* update the bit and byte counter*/ + bit ++; + if (bit == 8) { + byte++; + bit = 0; + } + + } /* for (x = circuit; x < (circuit + range + 1); x++) */ + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + ft_to_sngss7_cgba(ftdmchan); + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t handle_cgu_req(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt) +{ + SS7_FUNC_TRACE_ENTER(__FUNCTION__); + + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_span_data_t *sngss7_span = NULL; + ftdm_channel_t *ftdmchan = NULL; + int range; + uint8_t status[255]; + int blockType = 0; + int byte = 0; + int bit = 0; + int x; + + memset(&status[0], '\0', sizeof(status)); + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* grab the span info */ + sngss7_span = ftdmchan->span->mod_data; + + /* figure out what type of block needs to be applied */ + if ((siStaEvnt->cgsmti.eh.pres == PRSNT_NODEF) && (siStaEvnt->cgsmti.typeInd.pres == PRSNT_NODEF)) { + blockType = siStaEvnt->cgsmti.typeInd.val; + } else { + SS7_ERROR("Received CGB with no circuit group supervision value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* pull out the range value */ + if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.range.pres == PRSNT_NODEF)) { + range = siStaEvnt->rangStat.range.val; + } else { + SS7_ERROR("Received CGB with no range value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* pull out the status field */ + if ((siStaEvnt->rangStat.eh.pres == PRSNT_NODEF) && (siStaEvnt->rangStat.status.pres == PRSNT_NODEF)) { + for (x = 0; x < siStaEvnt->rangStat.status.len; x++) { + status[x] = siStaEvnt->rangStat.status.val[x]; + } + } else { + SS7_ERROR("Received CGB with no status value on CIC = %d\n", sngss7_info->circuit->cic); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + /* save the circuit, range and status */ + sngss7_span->rx_cgu.circuit = circuit; + sngss7_span->rx_cgu.range = range; + sngss7_span->rx_cgu.type = blockType; + for (x = 0; x < siStaEvnt->rangStat.status.len; x++) { + sngss7_span->rx_cgu.status[x] = status[x]; + } + + /* loop over the cics starting from circuit until range+1 */ + for (x = circuit; x < (circuit + range + 1); x++) { + if (g_ftdm_sngss7_data.cfg.isupCkt[x].type != VOICE) continue; + /* grab the circuit in question */ + if (extract_chan_data(x, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", x); + break; + } + + /* now that we have the right channel...put a lock on it so no-one else can use it */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a pending state change, give it a bit to clear */ + if (check_for_state_change(ftdmchan)) { + SS7_ERROR("Failed to wait for pending state change on CIC = %d\n", sngss7_info->circuit->cic); + ftdm_mutex_unlock(ftdmchan->mutex); + SS7_ASSERT; + }; + + if (status[byte] & (1 << bit)) { + switch (blockType) { + /**********************************************************************/ + case 0: /* maintenance oriented */ + sngss7_clear_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX); + break; + /**********************************************************************/ + case 1: /* hardware failure oriented */ + sngss7_clear_flag(sngss7_info, FLAG_GRP_HW_BLOCK_RX); + break; + /**********************************************************************/ + case 2: /* reserved for national use */ + break; + /**********************************************************************/ + default: + break; + /**********************************************************************/ + } /* switch (blockType) */ + } /* */ + + /* unlock the channel again before we exit */ + ftdm_mutex_unlock(ftdmchan->mutex); + + /* update the bit and byte counter*/ + bit ++; + if (bit == 8) { + byte++; + bit = 0; + } + + } /* for (x = circuit; x < (circuit + range + 1); x++) */ + + /* get the ftdmchan and ss7_chan_data from the circuit */ + if (extract_chan_data(circuit, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", circuit); + SS7_FUNC_TRACE_EXIT(__FUNCTION__); + return FTDM_FAIL; + } + + ft_to_sngss7_cgua(ftdmchan); + + return FTDM_SUCCESS; +} /******************************************************************************/ /* For Emacs: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c index b666f726a1..03f0beb090 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_logger.c @@ -109,6 +109,10 @@ void handle_sng_mtp1_alarm(Pst *pst, L1Mngmt *sta) /******************************************************************************/ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta) { + char buf[50]; + int x = 1; + + memset(buf, '\0', sizeof(buf)); switch (sta->t.usta.alarm.category) { /**************************************************************************/ @@ -126,23 +130,39 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta) case (LSD_EVENT_REMOTE_CONG_END): case (LSD_EVENT_RX_REMOTE_SIPO): + /* find the name for the sap in question */ + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) { + break; + } + x++; + } + + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) { + sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); + } else { + sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name); + } + + switch (sta->t.usta.alarm.cause) { /******************************************************************/ case (LCM_CAUSE_UNKNOWN): - ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s\n", - sta->t.usta.evntParm[0], + ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s\n", + buf, DECODE_LSD_EVENT(sta->t.usta.alarm.event)); break; /******************************************************************/ case (LCM_CAUSE_MGMT_INITIATED): - ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d][MGMT] %s\n", - sta->t.usta.evntParm[0], + ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s[MGMT] %s\n", + buf, DECODE_LSD_EVENT(sta->t.usta.alarm.event)); break; /******************************************************************/ default: - ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s (***unknown cause***)\n", - sta->t.usta.evntParm[0], + ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s (***unknown cause***)\n", + buf, DECODE_LSD_EVENT(sta->t.usta.alarm.event)); break; /******************************************************************/ @@ -150,23 +170,71 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta) break; /**********************************************************************/ case (LSD_EVENT_PROT_ERR): - ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n", - sta->t.usta.evntParm[0], + + /* find the name for the sap in question */ + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) { + break; + } + x++; + } + + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) { + sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); + } else { + sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name); + } + + ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %s\n", + buf, DECODE_LSD_EVENT(sta->t.usta.alarm.event), DECODE_LSD_CAUSE(sta->t.usta.alarm.cause)); break; /**********************************************************************/ case (LSD_EVENT_ALIGN_LOST): - ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %s\n", - sta->t.usta.evntParm[0], + + /* find the name for the sap in question */ + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) { + break; + } + x++; + } + + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) { + sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); + } else { + sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name); + } + + ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %s\n", + buf, DECODE_LSD_EVENT(sta->t.usta.alarm.event), DECODE_DISC_REASON(sta->t.usta.evntParm[1])); break; /**********************************************************************/ case (LSD_EVENT_RTB_FULL): case (LSD_EVENT_RTB_FULL_OVER): - ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n", - sta->t.usta.evntParm[0], + + /* find the name for the sap in question */ + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) { + break; + } + x++; + } + + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) { + sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); + } else { + sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name); + } + + ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : RTB Queue Len(%d)|Oldest BSN(%d)|Tx Queue Len(%d)|Outstanding Frames(%d)\n", + buf, DECODE_LSD_EVENT(sta->t.usta.alarm.event), sta->t.usta.evntParm[1], sta->t.usta.evntParm[2], @@ -175,15 +243,47 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta) break; /**********************************************************************/ case (LSD_EVENT_NEG_ACK): - ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : RTB Queue Len(%d)\n", - sta->t.usta.evntParm[0], + + /* find the name for the sap in question */ + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) { + break; + } + x++; + } + + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) { + sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); + } else { + sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name); + } + + ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : RTB Queue Len(%d)\n", + buf, DECODE_LSD_EVENT(sta->t.usta.alarm.event), sta->t.usta.evntParm[1]); break; /**********************************************************************/ case (LSD_EVENT_DAT_CFM_SDT): - ftdm_log(FTDM_LOG_ERROR,"[MTP2][SAPID:%d] %s : %d\n", - sta->t.usta.evntParm[0], + + /* find the name for the sap in question */ + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->t.usta.evntParm[0]) { + break; + } + x++; + } + + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) { + sprintf(buf, "[SAPID:%d]", sta->t.usta.evntParm[0]); + } else { + sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name); + } + + ftdm_log(FTDM_LOG_ERROR,"[MTP2]%s %s : %d\n", + buf, DECODE_LSD_EVENT(sta->t.usta.alarm.event), DECODE_DISC_REASON(sta->t.usta.evntParm[1])); break; @@ -251,15 +351,35 @@ void handle_sng_mtp2_alarm(Pst *pst, SdMngmt *sta) /******************************************************************************/ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta) { + char buf[50]; + int x = 1; + + memset(buf, '\0', sizeof(buf)); switch (sta->hdr.elmId.elmnt) { /**************************************************************************/ case (STDLSAP): + + /* find the name for the sap in question */ + x = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[x].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == sta->hdr.elmId.elmntInst1) { + break; + } + x++; + } + + if (g_ftdm_sngss7_data.cfg.mtpLink[x].id == 0) { + sprintf(buf, "[SAPID:%d]", sta->hdr.elmId.elmntInst1); + } else { + sprintf(buf, "[%s]", g_ftdm_sngss7_data.cfg.mtpLink[x].name); + } + switch (sta->t.usta.alarm.event) { /**********************************************************************/ case (LSN_EVENT_INV_OPC_OTHER_END): - ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : OPC(0x%X%X%X%X)\n", - sta->hdr.elmId.elmntInst1, + ftdm_log(FTDM_LOG_ERROR,"[MTP3]%s %s : %s : OPC(0x%X%X%X%X)\n", + buf, DECODE_LSN_EVENT(sta->t.usta.alarm.event), DECODE_LSN_CAUSE(sta->t.usta.alarm.cause), sta->t.usta.evntParm[3], @@ -269,16 +389,16 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta) break; /**********************************************************************/ case (LSN_EVENT_INV_SLC_OTHER_END): - ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s : %s : SLC(%d)\n", - sta->hdr.elmId.elmntInst1, + ftdm_log(FTDM_LOG_ERROR,"[MTP3]%s %s : %s : SLC(%d)\n", + buf, DECODE_LSN_EVENT(sta->t.usta.alarm.event), DECODE_LSN_CAUSE(sta->t.usta.alarm.cause), sta->t.usta.evntParm[0]); break; /**********************************************************************/ default: - ftdm_log(FTDM_LOG_ERROR,"[MTP3][SAPID:%d] %s(%d) : %s(%d)\n", - sta->hdr.elmId.elmntInst1, + ftdm_log(FTDM_LOG_ERROR,"[MTP3]%s %s(%d) : %s(%d)\n", + buf, DECODE_LSN_EVENT(sta->t.usta.alarm.event), sta->t.usta.alarm.event, DECODE_LSN_CAUSE(sta->t.usta.alarm.cause), @@ -303,13 +423,53 @@ void handle_sng_mtp3_alarm(Pst *pst, SnMngmt *sta) break; /**************************************************************************/ case (STROUT): - ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%d%d%d%d] %s : %s\n", - sta->t.usta.evntParm[0], - sta->t.usta.evntParm[1], - sta->t.usta.evntParm[2], - sta->t.usta.evntParm[3], - DECODE_LSN_EVENT(sta->t.usta.alarm.event), - DECODE_LSN_CAUSE(sta->t.usta.alarm.cause)); + switch (sta->t.usta.alarm.event) { + /**********************************************************************/ + case (LSN_EVENT_RX_TRANSFER_MSG): + switch (sta->t.usta.evntParm[5]) { + /******************************************************************/ + case (0x23): + ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFC\n"); + break; + /******************************************************************/ + case (0x34): + ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFR\n"); + break; + /******************************************************************/ + case (0x54): + ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFA\n"); + break; + /******************************************************************/ + case (0x14): + ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFP\n"); + break; + /******************************************************************/ + case (0x24): + ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFP (cluster)\n"); + break; + /******************************************************************/ + case (0x64): + ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFA (cluster)\n"); + break; + /******************************************************************/ + case (0x44): + ftdm_log(FTDM_LOG_INFO,"[MTP3] Rx SNM TFR (cluster)\n"); + break; + /******************************************************************/ + } /* switch (sta->t.usta.evntParm[5]) */ + break; + /**********************************************************************/ + default: + ftdm_log(FTDM_LOG_ERROR,"[MTP3][DPC:0x%d%d%d%d] %s : %s\n", + sta->t.usta.evntParm[0], + sta->t.usta.evntParm[1], + sta->t.usta.evntParm[2], + sta->t.usta.evntParm[3], + DECODE_LSN_EVENT(sta->t.usta.alarm.event), + DECODE_LSN_CAUSE(sta->t.usta.alarm.cause)); + break; + /**********************************************************************/ + } /* switch (sta->t.usta.alarm.event) */ break; /**************************************************************************/ default: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c index 66efe1ab12..a4fee0f862 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.c @@ -272,10 +272,8 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) ftdm_interrupt_t *ftdm_sangoma_ss7_int[2]; ftdm_span_t *ftdmspan = (ftdm_span_t *) obj; ftdm_channel_t *ftdmchan = NULL; - sngss7_chan_data_t *sngss7_info = NULL; sngss7_event_data_t *sngss7_event = NULL; sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data; - int i; ftdm_log (FTDM_LOG_INFO, "ftmod_sangoma_ss7 monitor thread for span=%u started.\n", ftdmspan->span_id); @@ -344,73 +342,14 @@ static void *ftdm_sangoma_ss7_run(ftdm_thread_t * me, void *obj) /**********************************************************************/ } /* switch ((ftdm_interrupt_wait(ftdm_sangoma_ss7_int, 100))) */ - /* extract the span data structure */ - sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data; - /* check if there is a GRS being processed on the span */ if (sngss7_span->rx_grs.range > 0) { - ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id); - /*SS7_DEBUG("Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id);*/ + /* check if the rx_grs has cleared */ + check_if_rx_grs_processed(ftdmspan); + } /* if (sngss7_span->rx_grs.range > 0) */ - /* check all the circuits in the range to see if they are done resetting */ - for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - SS7_ASSERT; - } - - /* lock the channel */ - ftdm_mutex_lock(ftdmchan->mutex); - - /* check if there is a state change pending on the channel */ - if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { - /* check the state to the GRP_RESET_RX_DN flag */ - if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) { - /* this channel is still resetting...do nothing */ - goto GRS_UNLOCK_ALL; - } /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */ - } else { - /* state change pending */ - goto GRS_UNLOCK_ALL; - } - } /* for ( i = circuit; i < (circuit + range + 1); i++) */ - - SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", - sngss7_span->rx_grs.circuit, - sngss7_span->rx_grs.range); - - /* check all the circuits in the range to see if they are done resetting */ - for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { - - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i); - SS7_ASSERT; - } - - /* throw the GRP reset flag complete flag */ - sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); - - /* move the channel to the down state */ - ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); - - } /* for ( i = circuit; i < (circuit + range + 1); i++) */ - -GRS_UNLOCK_ALL: - for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { - /* extract the channel in question */ - if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { - SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); - SS7_ASSERT; - } - - /* unlock the channel */ - ftdm_mutex_unlock(ftdmchan->mutex); - } - - } /* if (ftdmspan->grs.range > 0) */ + /* check each channel on the span to see if there is an un-procressed SUS/RES flag */ + check_for_res_sus_flag(ftdmspan); } /* master while loop */ /* clear the IN_THREAD flag so that we know the thread is done */ @@ -544,14 +483,17 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) i++; } - /* check if the end of pulsing character has arrived or the right number of digits */ - if (ftdmchan->caller_data.dnis.digits[i] == 0xF) { + /* check if the end of pulsing (ST) character has arrived or the right number of digits */ + if (ftdmchan->caller_data.dnis.digits[i-1] == 'F') { SS7_DEBUG_CHAN(ftdmchan, "Received the end of pulsing character %s\n", ""); + /* remove the ST */ + ftdmchan->caller_data.dnis.digits[i-1] = '\0'; + /*now go to the RING state */ ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_RING); - } else if (i >= g_ftdm_sngss7_data.min_digits) { + } else if (i > g_ftdm_sngss7_data.min_digits) { SS7_DEBUG_CHAN(ftdmchan, "Received %d digits (min digits = %d)\n", i, g_ftdm_sngss7_data.min_digits); /*now go to the RING state */ @@ -1012,30 +954,41 @@ static void ftdm_sangoma_ss7_process_state_change (ftdm_channel_t * ftdmchan) SS7_DEBUG_CHAN(ftdmchan,"Current flags: 0x%X\n", sngss7_info->flags); /**********************************************************************/ - if (sngss7_test_flag (sngss7_info, FLAG_INFID_PAUSED)) { - SS7_DEBUG_CHAN(ftdmchan, "Processing PAUSE flag %s\n", ""); - - /* bring the channel signaling status to down */ - sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; - sigev.sigstatus = FTDM_SIG_STATE_DOWN; - ftdm_span_send_signal (ftdmchan->span, &sigev); + if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) { - /* check the last state and return to it to allow the call to finish */ - goto suspend_goto_last; - } - - if (sngss7_test_flag (sngss7_info, FLAG_INFID_RESUME)) { - SS7_DEBUG_CHAN(ftdmchan, "Processing RESUME flag %s\n", ""); - - /* the reset flag is set for the first channel in the span at handle_resume */ - - /* clear the resume flag */ + /* clear the RESUME flag */ sngss7_clear_flag(sngss7_info, FLAG_INFID_RESUME); - /* go to restart state */ - goto suspend_goto_last; - } + /* if there are any resets present */ + if ((sngss7_test_flag (sngss7_info, FLAG_RESET_TX)) || + (sngss7_test_flag (sngss7_info, FLAG_RESET_RX)) || + (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_TX)) || + (sngss7_test_flag (sngss7_info, FLAG_GRP_RESET_RX))) { + /* go back to the reset state */ + goto suspend_goto_restart; + } else { + + /* bring the sig status back up */ + sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sigev.sigstatus = FTDM_SIG_STATE_UP; + ftdm_span_send_signal(ftdmchan->span, &sigev); + } + + /* go back to the last state */ + goto suspend_goto_last; + } /* if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) */ + + if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { + + /* bring the sig status down */ + sigev.event_id = FTDM_SIGEVENT_SIGSTATUS_CHANGED; + sigev.sigstatus = FTDM_SIG_STATE_DOWN; + ftdm_span_send_signal(ftdmchan->span, &sigev); + + /* go back to the last state */ + goto suspend_goto_last; + } /* if (sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) { */ /**********************************************************************/ if (sngss7_test_flag (sngss7_info, FLAG_CKT_MN_BLOCK_RX)) { SS7_DEBUG_CHAN(ftdmchan, "Processing CKT_MN_BLOCK_RX flag %s\n", ""); @@ -1304,6 +1257,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) for (x = 1; x < (span->chan_count + 1); x++) { /* extract the channel structure and sngss7 channel data */ ftdmchan = span->channels[x]; + if (ftdmchan->call_data == NULL) continue; sngss7_info = ftdmchan->call_data; sngss7_span = ftdmchan->span->mod_data; @@ -1312,7 +1266,7 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) /* throw the pause flag */ sngss7_set_flag(sngss7_info, FLAG_INFID_PAUSED); - +#if 0 /* throw the grp reset flag */ sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_TX); if (x == 1) { @@ -1320,7 +1274,10 @@ static ftdm_status_t ftdm_sangoma_ss7_start(ftdm_span_t * span) sngss7_span->tx_grs.circuit = sngss7_info->circuit->id; sngss7_span->tx_grs.range = span->chan_count -1; } - +#else + /* throw the channel into reset */ + sngss7_set_flag(sngss7_info, FLAG_RESET_TX); +#endif /* throw the channel to suspend */ ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); @@ -1454,6 +1411,8 @@ static FIO_SIG_LOAD_FUNCTION(ftdm_sangoma_ss7_init) sngss7_id = 0; + cmbLinkSetId = 1; + /* initalize the global gen_config flag */ g_ftdm_sngss7_data.gen_config = 0; diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h index 050f59e00e..415a897181 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_main.h @@ -139,7 +139,6 @@ typedef struct sng_mtp_link { uint32_t t23; uint32_t t24; uint32_t t25; - uint32_t t26; uint32_t t27; uint32_t t28; uint32_t t29; @@ -163,6 +162,8 @@ typedef struct sng_link_set { uint32_t flags; uint32_t apc; uint32_t linkType; + uint32_t switchType; + uint32_t ssf; uint32_t minActive; uint32_t numLinks; uint32_t links[16]; @@ -174,9 +175,11 @@ typedef struct sng_route { uint32_t flags; uint32_t dpc; uint32_t cmbLinkSetId; + uint32_t linkSetId; uint32_t linkType; uint32_t switchType; uint32_t ssf; + uint32_t nwId; uint32_t isSTP; uint32_t t6; uint32_t t8; @@ -188,6 +191,7 @@ typedef struct sng_route { uint32_t t19; uint32_t t21; uint32_t t25; + uint32_t t26; } sng_route_t; typedef struct sng_isup_intf { @@ -329,6 +333,8 @@ typedef struct sngss7_glare_data { typedef struct sngss7_group_data { uint32_t circuit; uint32_t range; + uint8_t status[255]; + uint8_t type; }sngss7_group_data_t; typedef struct sngss7_chan_data { @@ -348,6 +354,10 @@ typedef struct sngss7_span_data { ftdm_sched_t *sched; sngss7_group_data_t rx_grs; sngss7_group_data_t tx_grs; + sngss7_group_data_t rx_cgb; + sngss7_group_data_t tx_cgb; + sngss7_group_data_t rx_cgu; + sngss7_group_data_t tx_cgu; ftdm_queue_t *event_queue; }sngss7_span_data_t; @@ -376,8 +386,8 @@ typedef struct sngss7_event_data typedef enum { - FLAG_RESET_RX = (1 << 0), - FLAG_RESET_TX = (1 << 1), + FLAG_RESET_RX = (1 << 0), + FLAG_RESET_TX = (1 << 1), FLAG_RESET_SENT = (1 << 2), FLAG_RESET_TX_RSP = (1 << 3), FLAG_GRP_RESET_RX = (1 << 4), @@ -387,27 +397,25 @@ typedef enum { FLAG_GRP_RESET_TX = (1 << 8), FLAG_GRP_RESET_SENT = (1 << 9), FLAG_GRP_RESET_TX_RSP = (1 << 10), - FLAG_REMOTE_REL = (1 << 11), - FLAG_LOCAL_REL = (1 << 12), - FLAG_GLARE = (1 << 13), - FLAG_INFID_RESUME = (1 << 14), - FLAG_INFID_PAUSED = (1 << 15), + FLAG_REMOTE_REL = (1 << 11), + FLAG_LOCAL_REL = (1 << 12), + FLAG_GLARE = (1 << 13), + FLAG_INFID_RESUME = (1 << 14), + FLAG_INFID_PAUSED = (1 << 15), FLAG_CKT_UCIC_BLOCK = (1 << 16), FLAG_CKT_UCIC_UNBLK = (1 << 17), FLAG_CKT_LC_BLOCK_RX = (1 << 18), FLAG_CKT_LC_UNBLK_RX = (1 << 19), FLAG_CKT_MN_BLOCK_RX = (1 << 20), - FLAG_CKT_MN_BLOCK_TX = (1 << 21), - FLAG_CKT_MN_UNBLK_RX = (1 << 22), + FLAG_CKT_MN_UNBLK_RX = (1 << 21), + FLAG_CKT_MN_BLOCK_TX = (1 << 22), FLAG_CKT_MN_UNBLK_TX = (1 << 23), FLAG_GRP_HW_BLOCK_RX = (1 << 24), FLAG_GRP_HW_BLOCK_TX = (1 << 25), FLAG_GRP_MN_BLOCK_RX = (1 << 26), FLAG_GRP_MN_BLOCK_TX = (1 << 27), - FLAG_GRP_HW_UNBLK_RX = (1 << 28), - FLAG_GRP_HW_UNBLK_TX = (1 << 29), - FLAG_GRP_MN_UNBLK_RX = (1 << 30), - FLAG_GRP_MN_UNBLK_TX = (1 << 31) + FLAG_GRP_HW_UNBLK_TX = (1 << 28), + FLAG_GRP_MN_UNBLK_TX = (1 << 29) } flag_t; /******************************************************************************/ @@ -415,6 +423,7 @@ typedef enum { extern ftdm_sngss7_data_t g_ftdm_sngss7_data; extern uint32_t sngss7_id; extern ftdm_sched_t *sngss7_sched; +extern int cmbLinkSetId; /******************************************************************************/ /* PROTOTYPES *****************************************************************/ @@ -445,6 +454,14 @@ int ftmod_ss7_cc_isap_config(int id); int ftmod_ss7_inhibit_mtplink(uint32_t id); int ftmod_ss7_uninhibit_mtplink(uint32_t id); +int ftmod_ss7_activate_mtplink(uint32_t id); +int ftmod_ss7_deactivate_mtplink(uint32_t id); +int ftmod_ss7_deactivate2_mtplink(uint32_t id); +int ftmod_ss7_activate_mtplinkSet(uint32_t id); +int ftmod_ss7_deactivate_mtplinkSet(uint32_t id); +int ftmod_ss7_deactivate2_mtplinkSet(uint32_t id); +int ftmod_ss7_lpo_mtplink(uint32_t id); +int ftmod_ss7_lpr_mtplink(uint32_t id); int ftmod_ss7_mtplink_sta(uint32_t id, SnMngmt *cfm); int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm); @@ -465,6 +482,10 @@ void ft_to_sngss7_uba(ftdm_channel_t *ftdmchan); void ft_to_sngss7_lpa(ftdm_channel_t *ftdmchan); void ft_to_sngss7_gra(ftdm_channel_t *ftdmchan); void ft_to_sngss7_grs(ftdm_channel_t *ftdmchan); +void 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 sngss7_sta_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, uint8_t globalFlg, uint8_t evntType, SiStaEvnt *siStaEvnt); void sngss7_con_ind(uint32_t suInstId, uint32_t spInstId, uint32_t circuit, SiConEvnt *siConEvnt); @@ -524,6 +545,9 @@ int ftmod_ss7_parse_xml(ftdm_conf_parameter_t *ftdm_parameters, ftdm_span_t *spa void handle_isup_t35(void *userdata); ftdm_status_t ftdm_sngss7_handle_cli_cmd(ftdm_stream_handle_t *stream, const char *data); + +ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan); +ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan); /******************************************************************************/ /* MACROS *********************************************************************/ diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c index 4fac251c17..34abd265a6 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_out.c @@ -42,24 +42,30 @@ /******************************************************************************/ /* PROTOTYPES *****************************************************************/ -void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_anm (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_rel (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_rlc (ftdm_channel_t * ftdmchan); +void ft_to_sngss7_iam(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_acm(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_anm(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_rel(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_rlc(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_rsc (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_rsca (ftdm_channel_t * ftdmchan); +void ft_to_sngss7_rsc(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_rsca(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_blo (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_bla (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_ubl (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_uba (ftdm_channel_t * ftdmchan); +void ft_to_sngss7_blo(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_bla(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_ubl(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_uba(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_lpa (ftdm_channel_t * ftdmchan); +void ft_to_sngss7_lpa(ftdm_channel_t * ftdmchan); -void ft_to_sngss7_gra (ftdm_channel_t * ftdmchan); -void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan); +void ft_to_sngss7_gra(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_grs(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_cgba(ftdm_channel_t * ftdmchan); +void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan); /******************************************************************************/ /* FUNCTIONS ******************************************************************/ @@ -67,8 +73,9 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) { SS7_FUNC_TRACE_ENTER (__FUNCTION__); - sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; - SiConEvnt iam; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data;; + const char *nadi = NULL; + SiConEvnt iam; sngss7_info->suInstId = get_unique_id (); sngss7_info->spInstId = 0; @@ -98,7 +105,7 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) iam.fwdCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; iam.fwdCallInd.isdnUsrPrtInd.val = ISUP_USED; iam.fwdCallInd.isdnUsrPrtPrfInd.pres = PRSNT_NODEF; - iam.fwdCallInd.isdnUsrPrtPrfInd.val = PREF_REQAW; + iam.fwdCallInd.isdnUsrPrtPrfInd.val = PREF_PREFAW; iam.fwdCallInd.isdnAccInd.pres = PRSNT_NODEF; iam.fwdCallInd.isdnAccInd.val = ISDNACC_ISDN; iam.fwdCallInd.sccpMethInd.pres = PRSNT_NODEF; @@ -113,21 +120,88 @@ void ft_to_sngss7_iam (ftdm_channel_t * ftdmchan) 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.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS88) || + (g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].switchType == LSI_SW_ANS92) || + (g_ftdm_sngss7_data.cfg.isupIntf[sngss7_info->circuit->infId].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); + copy_cgPtyNum_to_sngss7 (&ftdmchan->caller_data, &iam.cgPtyNum); + + /* check if the user would like a custom NADI value for the calling Pty Num */ + nadi = ftdm_channel_get_var(ftdmchan, "ss7_nadi"); + if ((nadi != NULL) && (*nadi)) { + SS7_DEBUG_CHAN(ftdmchan,"Found user supplied NADI value \"%s\"\n", nadi); + iam.cgPtyNum.natAddrInd.val = atoi(nadi); + } else { + SS7_DEBUG_CHAN(ftdmchan,"No user supplied NADI value found, using \"3\" %s\n", " "); + iam.cgPtyNum.natAddrInd.val = 0x03; + } + sng_cc_con_request (sngss7_info->spId, sngss7_info->suInstId, sngss7_info->spInstId, sngss7_info->circuit->id, &iam, 0); - - SS7_MSG_TRACE(ftdmchan, sngss7_info, "Tx IAM\n"); + + SS7_INFO_CHAN(ftdmchan,"Tx IAM clg = \"%s\", cld = \"%s\"\n", + ftdmchan->caller_data.cid_num.digits, + ftdmchan->caller_data.dnis.digits); SS7_FUNC_TRACE_EXIT (__FUNCTION__); return; @@ -144,29 +218,29 @@ void ft_to_sngss7_acm (ftdm_channel_t * ftdmchan) memset (&acm, 0x0, sizeof (acm)); /* fill in the needed information for the ACM */ - acm.bckCallInd.eh.pres = PRSNT_NODEF; - acm.bckCallInd.chrgInd.pres = PRSNT_NODEF; - acm.bckCallInd.chrgInd.val = 0x00; - acm.bckCallInd.cadPtyStatInd.pres = PRSNT_NODEF; - acm.bckCallInd.cadPtyStatInd.val = 0x01; - acm.bckCallInd.cadPtyCatInd.pres = PRSNT_NODEF; - acm.bckCallInd.cadPtyCatInd.val = 0x00; - acm.bckCallInd.end2EndMethInd.pres = PRSNT_NODEF; - acm.bckCallInd.end2EndMethInd.val = 0x00; - acm.bckCallInd.intInd.pres = PRSNT_NODEF; - acm.bckCallInd.intInd.val = 0x00; - acm.bckCallInd.end2EndInfoInd.pres = PRSNT_NODEF; - acm.bckCallInd.end2EndInfoInd.val = 0x00; - acm.bckCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; - acm.bckCallInd.isdnUsrPrtInd.val = 0x0; - acm.bckCallInd.holdInd.pres = PRSNT_NODEF; - acm.bckCallInd.holdInd.val = 0x00; - acm.bckCallInd.isdnAccInd.pres = PRSNT_NODEF; - acm.bckCallInd.isdnAccInd.val = 0x0; - acm.bckCallInd.echoCtrlDevInd.pres = PRSNT_NODEF; - acm.bckCallInd.echoCtrlDevInd.val = 0x0; - acm.bckCallInd.sccpMethInd.pres = PRSNT_NODEF; - acm.bckCallInd.sccpMethInd.val = 0x00; + acm.bckCallInd.eh.pres = PRSNT_NODEF; + acm.bckCallInd.chrgInd.pres = PRSNT_NODEF; + acm.bckCallInd.chrgInd.val = CHRG_CHRG; + acm.bckCallInd.cadPtyStatInd.pres = PRSNT_NODEF; + acm.bckCallInd.cadPtyStatInd.val = 0x01; + acm.bckCallInd.cadPtyCatInd.pres = PRSNT_NODEF; + acm.bckCallInd.cadPtyCatInd.val = CADCAT_ORDSUBS; + acm.bckCallInd.end2EndMethInd.pres = PRSNT_NODEF; + acm.bckCallInd.end2EndMethInd.val = E2EMTH_NOMETH; + acm.bckCallInd.intInd.pres = PRSNT_NODEF; + acm.bckCallInd.intInd.val = INTIND_NOINTW; + acm.bckCallInd.end2EndInfoInd.pres = PRSNT_NODEF; + acm.bckCallInd.end2EndInfoInd.val = E2EINF_NOINFO; + acm.bckCallInd.isdnUsrPrtInd.pres = PRSNT_NODEF; + acm.bckCallInd.isdnUsrPrtInd.val = ISUP_USED; + acm.bckCallInd.holdInd.pres = PRSNT_NODEF; + acm.bckCallInd.holdInd.val = HOLD_NOTREQD; + acm.bckCallInd.isdnAccInd.pres = PRSNT_NODEF; + acm.bckCallInd.isdnAccInd.val = ISDNACC_NONISDN; + acm.bckCallInd.echoCtrlDevInd.pres = PRSNT_NODEF; + acm.bckCallInd.echoCtrlDevInd.val = 0x1; /* ec device present */ + acm.bckCallInd.sccpMethInd.pres = PRSNT_NODEF; + acm.bckCallInd.sccpMethInd.val = SCCPMTH_NOIND; /* send the ACM request to LibSngSS7 */ sng_cc_con_status (1, @@ -463,7 +537,7 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan) SiStaEvnt grs; - memset (&grs, 0x0, sizeof (grs)); + memset (&grs, 0x0, sizeof(grs)); grs.rangStat.eh.pres = PRSNT_NODEF; grs.rangStat.range.pres = PRSNT_NODEF; @@ -485,6 +559,201 @@ void ft_to_sngss7_grs (ftdm_channel_t * ftdmchan) return; } +/******************************************************************************/ +void ft_to_sngss7_cgba(ftdm_channel_t * ftdmchan) +{ + SS7_FUNC_TRACE_ENTER (__FUNCTION__); + + sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + int x = 0; + + SiStaEvnt cgba; + + memset (&cgba, 0x0, sizeof(cgba)); + + /* fill in the circuit group supervisory message */ + cgba.cgsmti.eh.pres = PRSNT_NODEF; + cgba.cgsmti.typeInd.pres = PRSNT_NODEF; + cgba.cgsmti.typeInd.val = sngss7_span->rx_cgb.type; + + cgba.rangStat.eh.pres = PRSNT_NODEF; + /* fill in the range */ + cgba.rangStat.range.pres = PRSNT_NODEF; + cgba.rangStat.range.val = sngss7_span->rx_cgb.range; + /* fill in the status */ + cgba.rangStat.status.pres = PRSNT_NODEF; + cgba.rangStat.status.len = ((sngss7_span->rx_cgb.range + 1) >> 3) + (((sngss7_span->rx_cgb.range + 1) & 0x07) ? 1 : 0); + for(x = 0; x < cgba.rangStat.status.len; x++){ + cgba.rangStat.status.val[x] = sngss7_span->rx_cgb.status[x]; + } + + sng_cc_sta_request (1, + 0, + 0, + sngss7_span->rx_cgb.circuit, + 0, + SIT_STA_CGBRSP, + &cgba); + + SS7_INFO_CHAN(ftdmchan, "Tx CGBA (%d:%d)\n", + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + sngss7_span->rx_cgb.range)); + + /* clean out the saved data */ + memset(&sngss7_span->rx_cgb, 0x0, sizeof(sngss7_group_data_t)); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); + return; +} + +/******************************************************************************/ +void ft_to_sngss7_cgua(ftdm_channel_t * ftdmchan) +{ + SS7_FUNC_TRACE_ENTER (__FUNCTION__); + + sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + int x = 0; + + SiStaEvnt cgua; + + memset (&cgua, 0x0, sizeof(cgua)); + + /* fill in the circuit group supervisory message */ + cgua.cgsmti.eh.pres = PRSNT_NODEF; + cgua.cgsmti.typeInd.pres = PRSNT_NODEF; + cgua.cgsmti.typeInd.val = sngss7_span->rx_cgu.type; + + cgua.rangStat.eh.pres = PRSNT_NODEF; + /* fill in the range */ + cgua.rangStat.range.pres = PRSNT_NODEF; + cgua.rangStat.range.val = sngss7_span->rx_cgu.range; + /* fill in the status */ + cgua.rangStat.status.pres = PRSNT_NODEF; + cgua.rangStat.status.len = ((sngss7_span->rx_cgu.range + 1) >> 3) + (((sngss7_span->rx_cgu.range + 1) & 0x07) ? 1 : 0); + for(x = 0; x < cgua.rangStat.status.len; x++){ + cgua.rangStat.status.val[x] = sngss7_span->rx_cgu.status[x]; + } + + sng_cc_sta_request (1, + 0, + 0, + sngss7_span->rx_cgu.circuit, + 0, + SIT_STA_CGURSP, + &cgua); + + SS7_INFO_CHAN(ftdmchan, "Tx CGUA (%d:%d)\n", + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + sngss7_span->rx_cgu.range)); + + /* clean out the saved data */ + memset(&sngss7_span->rx_cgu, 0x0, sizeof(sngss7_group_data_t)); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); + return; +} + +/******************************************************************************/ +void ft_to_sngss7_cgb(ftdm_channel_t * ftdmchan) +{ + SS7_FUNC_TRACE_ENTER (__FUNCTION__); + + sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + SiStaEvnt cgb; + int x = 0; + + + memset (&cgb, 0x0, sizeof(cgb)); + + /* fill in the circuit group supervisory message */ + cgb.cgsmti.eh.pres = PRSNT_NODEF; + cgb.cgsmti.typeInd.pres = PRSNT_NODEF; + cgb.cgsmti.typeInd.val = sngss7_span->tx_cgb.type; + + /* fill in the range */ + cgb.rangStat.eh.pres = PRSNT_NODEF; + cgb.rangStat.range.pres = PRSNT_NODEF; + cgb.rangStat.range.val = sngss7_span->tx_cgb.range; + + /* fill in the status */ + cgb.rangStat.status.pres = PRSNT_NODEF; + cgb.rangStat.status.len = ((sngss7_span->tx_cgb.range + 1) >> 3) + (((sngss7_span->tx_cgb.range + 1) & 0x07) ? 1 : 0); + for(x = 0; x < cgb.rangStat.status.len; x++){ + cgb.rangStat.status.val[x] = sngss7_span->tx_cgb.status[x]; + } + + sng_cc_sta_request (1, + 0, + 0, + sngss7_span->tx_cgb.circuit, + 0, + SIT_STA_CGBREQ, + &cgb); + + SS7_INFO_CHAN(ftdmchan, "Tx CGB (%d:%d)\n", + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + sngss7_span->tx_cgb.range)); + + /* clean out the saved data */ + memset(&sngss7_span->tx_cgb, 0x0, sizeof(sngss7_group_data_t)); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); + return; +} + +/******************************************************************************/ +void ft_to_sngss7_cgu(ftdm_channel_t * ftdmchan) +{ + SS7_FUNC_TRACE_ENTER (__FUNCTION__); + + sngss7_span_data_t *sngss7_span = ftdmchan->span->mod_data; + sngss7_chan_data_t *sngss7_info = ftdmchan->call_data; + SiStaEvnt cgu; + int x = 0; + + + memset (&cgu, 0x0, sizeof(cgu)); + + /* fill in the circuit group supervisory message */ + cgu.cgsmti.eh.pres = PRSNT_NODEF; + cgu.cgsmti.typeInd.pres = PRSNT_NODEF; + cgu.cgsmti.typeInd.val = sngss7_span->tx_cgu.type; + + /* fill in the range */ + cgu.rangStat.eh.pres = PRSNT_NODEF; + cgu.rangStat.range.pres = PRSNT_NODEF; + cgu.rangStat.range.val = sngss7_span->tx_cgu.range; + + /* fill in the status */ + cgu.rangStat.status.pres = PRSNT_NODEF; + cgu.rangStat.status.len = ((sngss7_span->tx_cgu.range + 1) >> 3) + (((sngss7_span->tx_cgu.range + 1) & 0x07) ? 1 : 0); + for(x = 0; x < cgu.rangStat.status.len; x++){ + cgu.rangStat.status.val[x] = sngss7_span->tx_cgu.status[x]; + } + + sng_cc_sta_request (1, + 0, + 0, + sngss7_span->tx_cgu.circuit, + 0, + SIT_STA_CGUREQ, + &cgu); + + SS7_INFO_CHAN(ftdmchan, "Tx CGU (%d:%d)\n", + sngss7_info->circuit->cic, + (sngss7_info->circuit->cic + sngss7_span->tx_cgu.range)); + + /* clean out the saved data */ + memset(&sngss7_span->tx_cgu, 0x0, sizeof(sngss7_group_data_t)); + + SS7_FUNC_TRACE_EXIT (__FUNCTION__); + return; +} + + /******************************************************************************/ /* For Emacs: * Local Variables: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c index 305e1a50f5..d238462046 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_sta.c @@ -68,7 +68,7 @@ int ftmod_ss7_mtplinkSet_sta(uint32_t id, SnMngmt *cfm) sta.hdr.elmId.elmnt = STLNKSET; sta.hdr.elmId.elmntInst1 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].id; - sta.hdr.elmId.elmntInst2 = 1; + sta.hdr.elmId.elmntInst2 = g_ftdm_sngss7_data.cfg.mtpLinkSet[id].links[0]; return(sng_sta_mtp3(&sta, cfm)); } diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c index 97957f3c82..694e9a4ed8 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_support.c @@ -57,6 +57,8 @@ unsigned long get_unique_id(void); ftdm_status_t extract_chan_data(uint32_t circuit, sngss7_chan_data_t **sngss7_info, ftdm_channel_t **ftdmchan); +ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan); +ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan); /******************************************************************************/ /* FUNCTIONS ******************************************************************/ @@ -72,9 +74,10 @@ uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum) int k; int j; int flag; + int odd; char tmp[2]; - unsigned char lower; - unsigned char upper; + uint8_t lower; + uint8_t upper; /**************************************************************************/ cgPtyNum->eh.pres = PRSNT_NODEF; @@ -104,81 +107,73 @@ uint8_t copy_cgPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCgPtyNum *cgPtyNum) k = 0; j = 0; flag = 0; + odd = 0; + upper = 0x0; + lower = 0x0; while (1) { + /* grab a digit from the ftdm digits */ tmp[0] = ftdm->cid_num.digits[k]; + /* check if the digit is a number and that is not null */ + while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) { + /* move on to the next value */ + k++; + tmp[0] = ftdm->cid_num.digits[k]; + } /* while(!(isdigit(tmp))) */ + + /* check if tmp is null or a digit */ if (tmp[0] != '\0') { - if (isdigit(tmp[0])) { - lower = atoi(&tmp[0]); + /* push it into the lower nibble */ + lower = atoi(&tmp[0]); + /* move to the next digit */ + k++; + /* grab a digit from the ftdm digits */ + tmp[0] = ftdm->cid_num.digits[k]; + + /* check if the digit is a number and that is not null */ + while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) { k++; tmp[0] = ftdm->cid_num.digits[k]; - } else { - while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) { - k++; - tmp[0] = ftdm->cid_num.digits[k]; - } /* while(!(isdigit(tmp))) */ + } /* while(!(isdigit(tmp))) */ - if (tmp[0] != '\0') { - lower = atoi(&tmp[0]); - k++; - tmp[0] = ftdm->cid_num.digits[k]; - } else { - flag = 1; - lower = 0xf; - } /* if (tmp != '\0') */ - } /* (isdigit(tmp)) */ - } else { - flag = 1; - lower = 0xf; - } /* if (tmp != '\0') */ - - tmp[0] = ftdm->cid_num.digits[k]; - - if (tmp[0] != '\0') { - if (isdigit(tmp[0])) { + /* check if tmp is null or a digit */ + if (tmp[0] != '\0') { + /* push the digit into the upper nibble */ upper = (atoi(&tmp[0])) << 4; } else { - while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) { - k++; - tmp[0] = ftdm->cid_num.digits[k]; - } /* while(!(isdigit(tmp))) */ - - if (tmp[0] != '\0') { - upper = (atoi(&tmp[0])) << 4; - k++; - } else { - flag = 1; - upper = 0xf; - } /* if (tmp != '\0') */ - } /* if (isdigit(tmp)) */ - } else { - if (flag == 1) { + /* there is no upper ... fill in 0 */ upper = 0x0; - } else { + /* throw the odd flag */ + odd = 1; + /* throw the end flag */ flag = 1; - upper = 0xf; - } /* if (flag == 1) */ - } /* if (tmp != '\0') */ + } /* if (tmp != '\0') */ + } else { + /* keep the odd flag down */ + odd = 0; + /* throw the flag */ + flag = 1; + } + /* push the digits into the trillium structure */ cgPtyNum->addrSig.val[j] = upper | lower; + /* increment the trillium pointer */ j++; - if (flag) { - break; - } else { - k++; - } + /* if the flag is up we're through all the digits */ + if (flag) break; + + /* move to the next digit */ + k++; } /* while(1) */ cgPtyNum->addrSig.len = j; /**************************************************************************/ cgPtyNum->oddEven.pres = PRSNT_NODEF; - - cgPtyNum->oddEven.val = ((cgPtyNum->addrSig.val[j] >> 4) == 0x0 ) ? 0x01 : 0x00; - + cgPtyNum->oddEven.val = odd; /**************************************************************************/ return 0; } @@ -196,9 +191,10 @@ uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum) int k; int j; int flag; + int odd; char tmp[2]; - unsigned char lower; - unsigned char upper; + uint8_t lower; + uint8_t upper; /**************************************************************************/ cdPtyNum->eh.pres = PRSNT_NODEF; @@ -217,77 +213,74 @@ uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum) /* atoi will search through memory starting from the pointer it is given until * it finds the \0...since tmp is on the stack it will start going through the * possibly causing corruption. Hard code a \0 to prevent this - */ + */ /* dnis */ tmp[1] = '\0'; k = 0; j = 0; flag = 0; + odd = 0; + upper = 0x0; + lower = 0x0; while (1) { + /* grab a digit from the ftdm digits */ tmp[0] = ftdm->dnis.digits[k]; + /* check if the digit is a number and that is not null */ + while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) { + /* move on to the next value */ + k++; + tmp[0] = ftdm->dnis.digits[k]; + } /* while(!(isdigit(tmp))) */ + + /* check if tmp is null or a digit */ if (tmp[0] != '\0') { - if (isdigit(tmp[0])) { - lower = atoi(&tmp[0]); + /* push it into the lower nibble */ + lower = atoi(&tmp[0]); + /* move to the next digit */ + k++; + /* grab a digit from the ftdm digits */ + tmp[0] = ftdm->dnis.digits[k]; + + /* check if the digit is a number and that is not null */ + while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) { k++; tmp[0] = ftdm->dnis.digits[k]; - } else { - while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) { - k++; - tmp[0] = ftdm->dnis.digits[k]; - } /* while(!(isdigit(tmp))) */ + } /* while(!(isdigit(tmp))) */ - if (tmp[0] != '\0') { - lower = atoi(&tmp[0]); - k++; - tmp[0] = ftdm->dnis.digits[k]; - } else { - flag = 1; - lower = 0xf; - } /* if (tmp != '\0') */ - } /* (isdigit(tmp)) */ - } else { - flag = 1; - lower = 0xf; - } /* if (tmp != '\0') */ - - tmp[0] = ftdm->dnis.digits[k]; - - if (tmp[0] != '\0') { - if (isdigit(tmp[0])) { + /* check if tmp is null or a digit */ + if (tmp[0] != '\0') { + /* push the digit into the upper nibble */ upper = (atoi(&tmp[0])) << 4; } else { - while (!(isdigit(tmp[0])) && (tmp[0] != '\0')) { - k++; - tmp[0] = ftdm->dnis.digits[k]; - } /* while(!(isdigit(tmp))) */ - - if (tmp[0] != '\0') { - upper = (atoi(&tmp[0])) << 4; - k++; - } else { - flag = 1; - upper = 0xf; - } /* if (tmp != '\0') */ - } /* if (isdigit(tmp)) */ - } else { - if (flag == 1) { - upper = 0x0; - } else { + /* there is no upper ... fill in ST */ + upper = 0xF; + /* throw the odd flag */ + odd = 1; + /* throw the end flag */ flag = 1; - upper = 0xf; - } /* if (flag == 1) */ - } /* if (tmp != '\0') */ + } /* if (tmp != '\0') */ + } else { + /* keep the odd flag down */ + odd = 1; + /* need to add the ST */ + lower = 0xF; + upper = 0x0; + /* throw the flag */ + flag = 1; + } + /* push the digits into the trillium structure */ cdPtyNum->addrSig.val[j] = upper | lower; + /* increment the trillium pointer */ j++; - if (flag) { - break; - } else { - k++; - } + /* if the flag is up we're through all the digits */ + if (flag) break; + + /* move to the next digit */ + k++; } /* while(1) */ cdPtyNum->addrSig.len = j; @@ -295,7 +288,7 @@ uint8_t copy_cdPtyNum_to_sngss7(ftdm_caller_data_t *ftdm, SiCdPtyNum *cdPtyNum) /**************************************************************************/ cdPtyNum->oddEven.pres = PRSNT_NODEF; - cdPtyNum->oddEven.val = ((cdPtyNum->addrSig.val[j] >> 4) == 0x0 ) ? 0x01 : 0x00; + cdPtyNum->oddEven.val = odd; /**************************************************************************/ return 0; @@ -313,9 +306,9 @@ uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven) j = 0; for (i = 0; i < str.len; i++) { - sprintf(&ftdm[j], "%d", (str.val[i] & 0x0F)); + sprintf(&ftdm[j], "%X", (str.val[i] & 0x0F)); j++; - sprintf(&ftdm[j], "%d", ((str.val[i] & 0xF0) >> 4)); + sprintf(&ftdm[j], "%X", ((str.val[i] & 0xF0) >> 4)); j++; } @@ -325,6 +318,8 @@ uint8_t copy_tknStr_from_sngss7(TknStr str, char *ftdm, TknU8 oddEven) } else { ftdm[j] = '\0'; } + + } else { SS7_ERROR("Asked to copy tknStr that is not present!\n"); return 1; @@ -451,6 +446,149 @@ unsigned long get_unique_id(void) } /******************************************************************************/ +ftdm_status_t check_if_rx_grs_processed(ftdm_span_t *ftdmspan) +{ + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + sngss7_span_data_t *sngss7_span = (sngss7_span_data_t *)ftdmspan->mod_data; + int i; + int byte = 0; + int bit = 0; + + + ftdm_log(FTDM_LOG_DEBUG, "Found Rx GRS on span %d...checking circuits\n", ftdmspan->span_id); + + /* check all the circuits in the range to see if they are done resetting */ + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + SS7_ASSERT; + } + + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + + /* check if there is a state change pending on the channel */ + if (!ftdm_test_flag(ftdmchan, FTDM_CHANNEL_STATE_CHANGE)) { + /* check the state to the GRP_RESET_RX_DN flag */ + if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) { + /* this channel is still resetting...do nothing */ + goto GRS_UNLOCK_ALL; + } /* if (!sngss7_test_flag(sngss7_info, FLAG_GRP_RESET_RX_DN)) */ + } else { + /* state change pending */ + goto GRS_UNLOCK_ALL; + } + } /* for ( i = circuit; i < (circuit + range + 1); i++) */ + + SS7_DEBUG("All circuits out of reset for GRS: circuit=%d, range=%d\n", + sngss7_span->rx_grs.circuit, + sngss7_span->rx_grs.range); + + /* check all the circuits in the range to see if they are done resetting */ + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n",i); + SS7_ASSERT; + } + + /* throw the GRP reset flag complete flag */ + sngss7_set_flag(sngss7_info, FLAG_GRP_RESET_RX_CMPLT); + + /* move the channel to the down state */ + ftdm_set_state_locked(ftdmchan, FTDM_CHANNEL_STATE_DOWN); + + /* update the status map if the ckt is in blocked state */ + if ((sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_CKT_MN_BLOCK_TX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX)) || + (sngss7_test_flag(sngss7_info, FLAG_GRP_MN_BLOCK_RX))) { + + sngss7_span->rx_grs.status[byte] = (sngss7_span->rx_grs.status[byte] | (1 << bit)); + } /* if blocked */ + + /* update the bit and byte counter*/ + bit ++; + if (bit == 8) { + byte++; + bit = 0; + } + } /* for ( i = circuit; i < (circuit + range + 1); i++) */ + +GRS_UNLOCK_ALL: + for ( i = sngss7_span->rx_grs.circuit; i < (sngss7_span->rx_grs.circuit + sngss7_span->rx_grs.range + 1); i++) { + /* extract the channel in question */ + if (extract_chan_data(i, &sngss7_info, &ftdmchan)) { + SS7_ERROR("Failed to extract channel data for circuit = %d!\n", i); + SS7_ASSERT; + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + } + + return FTDM_SUCCESS; +} + +/******************************************************************************/ +ftdm_status_t check_for_res_sus_flag(ftdm_span_t *ftdmspan) +{ + ftdm_channel_t *ftdmchan = NULL; + sngss7_chan_data_t *sngss7_info = NULL; + ftdm_sigmsg_t sigev; + int x; + + for (x = 1; x < (ftdmspan->chan_count + 1); x++) { + + /* extract the channel structure and sngss7 channel data */ + ftdmchan = ftdmspan->channels[x]; + + /* if the call data is NULL move on */ + if (ftdmchan->call_data == NULL) continue; + + sngss7_info = ftdmchan->call_data; + + /* lock the channel */ + ftdm_mutex_lock(ftdmchan->mutex); + + memset (&sigev, 0, sizeof (sigev)); + + sigev.chan_id = ftdmchan->chan_id; + sigev.span_id = ftdmchan->span_id; + sigev.channel = ftdmchan; + + /* if we have the PAUSED flag and the sig status is still UP */ + if ((sngss7_test_flag(sngss7_info, FLAG_INFID_PAUSED)) && + (ftdm_test_flag(ftdmchan, FTDM_CHANNEL_SIG_UP))) { + + /* throw the channel into SUSPENDED to process the flag */ + /* after doing this once the sig status will be down */ + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } + + /* if the RESUME flag is up go to SUSPENDED to process the flag */ + /* after doing this the flag will be cleared */ + if (sngss7_test_flag(sngss7_info, FLAG_INFID_RESUME)) { + ftdm_set_state_locked (ftdmchan, FTDM_CHANNEL_STATE_SUSPENDED); + } + + /* unlock the channel */ + ftdm_mutex_unlock(ftdmchan->mutex); + + } /* for (x = 1; x < (span->chan_count + 1); x++) */ + + /* signal the core that sig events are queued for processing */ + ftdm_span_trigger_signals(ftdmspan); + + return FTDM_SUCCESS; +} + +/******************************************************************************/ + /******************************************************************************/ /* For Emacs: diff --git a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c index aa639d1c3a..bd1be4b6a4 100644 --- a/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c +++ b/libs/freetdm/src/ftmod/ftmod_sangoma_ss7/ftmod_sangoma_ss7_xml.c @@ -46,6 +46,8 @@ typedef struct sng_timeslot int gap; int hole; }sng_timeslot_t; + +int cmbLinkSetId; /******************************************************************************/ /* PROTOTYPES *****************************************************************/ @@ -343,11 +345,11 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset) /**********************************************************************/ } else if (!strcasecmp(parm->var, "apc")) { mtpLinkSet.apc = atoi(parm->val); - SS7_DEBUG("\tFoundmtpLinkSet->apc = %d\n", mtpLinkSet.apc); + SS7_DEBUG("\tFound mtpLinkSet->apc = %d\n", mtpLinkSet.apc); /**********************************************************************/ } else if (!strcasecmp(parm->var, "minActive")) { mtpLinkSet.minActive = atoi(parm->val); - SS7_DEBUG("\tFoundmtpLinkSet->minActive = %d\n", mtpLinkSet.minActive); + SS7_DEBUG("\tFound mtpLinkSet->minActive = %d\n", mtpLinkSet.minActive); /**********************************************************************/ } else { SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); @@ -385,8 +387,6 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset) if (count < 1 || count > 15 ) { SS7_ERROR("Invalid number of mtp_links found (%d)\n", count); return FTDM_FAIL; - } else { - mtpLinkSet.numLinks = count; } /* now we need to see if this linkset exists already or not and grab an Id */ @@ -418,8 +418,7 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset) mtpLink[i].mtp3.apc = mtpLinkSet.apc; mtpLink[i].mtp3.linkSetId = mtpLinkSet.id; - /* fill in the mtplink structure */ - mtpLinkSet.links[count] = ftmod_ss7_fill_in_mtpLink(&mtpLink[i]); + ftmod_ss7_fill_in_mtpLink(&mtpLink[i]); /* increment the links counter */ count++; @@ -428,6 +427,10 @@ static int ftmod_ss7_parse_mtp_linkset(ftdm_conf_node_t *mtp_linkset) i++; } + mtpLinkSet.linkType = mtpLink[0].mtp3.linkType; + mtpLinkSet.switchType = mtpLink[0].mtp3.switchType; + mtpLinkSet.ssf = mtpLink[0].mtp3.ssf; + ftmod_ss7_fill_in_mtpLinkSet(&mtpLinkSet); return FTDM_SUCCESS; @@ -497,27 +500,27 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t * if (!strcasecmp(parm->val, "itu92")) { mtpLink->mtp2.linkType = LSD_SW_ITU92; mtpLink->mtp3.linkType = LSN_SW_ITU; - SS7_DEBUG("\tFoundmtpLink->linkType = \"ITU92\"\n"); + SS7_DEBUG("\tFound mtpLink->linkType = \"ITU92\"\n"); } else if (!strcasecmp(parm->val, "itu88")) { mtpLink->mtp2.linkType = LSD_SW_ITU88; mtpLink->mtp3.linkType = LSN_SW_ITU; - SS7_DEBUG("\tFoundmtpLink->linkType = \"ITU88\"\n"); + SS7_DEBUG("\tFound mtpLink->linkType = \"ITU88\"\n"); } else if (!strcasecmp(parm->val, "ansi96")) { mtpLink->mtp2.linkType = LSD_SW_ANSI92; mtpLink->mtp3.linkType = LSN_SW_ANS96; - SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI96\"\n"); + SS7_DEBUG("\tFound mtpLink->linkType = \"ANSI96\"\n"); } else if (!strcasecmp(parm->val, "ansi92")) { mtpLink->mtp2.linkType = LSD_SW_ANSI92; mtpLink->mtp3.linkType = LSN_SW_ANS; - SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI92\"\n"); + SS7_DEBUG("\tFound mtpLink->linkType = \"ANSI92\"\n"); } else if (!strcasecmp(parm->val, "ansi88")) { mtpLink->mtp2.linkType = LSD_SW_ANSI88; mtpLink->mtp3.linkType = LSN_SW_ANS; - SS7_DEBUG("\tFoundmtpLink->linkType = \"ANSI88\"\n"); + SS7_DEBUG("\tFound mtpLink->linkType = \"ANSI88\"\n"); } else if (!strcasecmp(parm->val, "etsi")) { mtpLink->mtp2.linkType = LSD_SW_ITU92; mtpLink->mtp3.linkType = LSN_SW_ITU; - SS7_DEBUG("\tFoundmtpLink->linkType = \"ETSI\"\n"); + SS7_DEBUG("\tFound mtpLink->linkType = \"ETSI\"\n"); } else { SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val); return FTDM_FAIL; @@ -526,31 +529,40 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t * } else if (!strcasecmp(parm->var, "switchType")) { if (!strcasecmp(parm->val, "itu97")) { mtpLink->mtp3.switchType = LSI_SW_ITU97; - SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU97\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"ITU97\"\n"); } else if (!strcasecmp(parm->val, "itu88")) { mtpLink->mtp3.switchType = LSI_SW_ITU; - SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU88\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"ITU88\"\n"); } else if (!strcasecmp(parm->val, "itu92")) { mtpLink->mtp3.switchType = LSI_SW_ITU; - SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU92\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"ITU92\"\n"); } else if (!strcasecmp(parm->val, "itu00")) { mtpLink->mtp3.switchType = LSI_SW_ITU2000; - SS7_DEBUG("\tFoundmtpLink->switchType = \"ITU00\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"ITU00\"\n"); } else if (!strcasecmp(parm->val, "ETSIV2")) { mtpLink->mtp3.switchType = LSI_SW_ETSI; - SS7_DEBUG("\tFoundmtpLink->switchType = \"ETSIV2\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"ETSIV2\"\n"); } else if (!strcasecmp(parm->val, "ETSIV3")) { mtpLink->mtp3.switchType = LSI_SW_ETSIV3; - SS7_DEBUG("\tFoundmtpLink->switchType = \"ETSIV3\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"ETSIV3\"\n"); } else if (!strcasecmp(parm->val, "UK")) { mtpLink->mtp3.switchType = LSI_SW_UK; - SS7_DEBUG("\tFoundmtpLink->switchType = \"UK\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"UK\"\n"); } else if (!strcasecmp(parm->val, "RUSSIA")) { mtpLink->mtp3.switchType = LSI_SW_RUSSIA; - SS7_DEBUG("\tFoundmtpLink->switchType = \"RUSSIA\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"RUSSIA\"\n"); } else if (!strcasecmp(parm->val, "INDIA")) { mtpLink->mtp3.switchType = LSI_SW_INDIA; - SS7_DEBUG("\tFoundmtpLink->switchType = \"INDIA\"\n"); + SS7_DEBUG("\tFound mtpLink->switchType = \"INDIA\"\n"); + } else if (!strcasecmp(parm->val, "ansi88")) { + mtpLink->mtp3.switchType = LSI_SW_ANS88; + SS7_DEBUG("\tFound mtpLink->switchType = \"ANSI88\"\n"); + } else if (!strcasecmp(parm->val, "ansi92")) { + mtpLink->mtp3.switchType = LSI_SW_ANS92; + SS7_DEBUG("\tFound mtpLink->switchType = \"ANSI92\"\n"); + } else if (!strcasecmp(parm->val, "ansi95")) { + mtpLink->mtp3.switchType = LSI_SW_ANS95; + SS7_DEBUG("\tFound mtpLink->switchType = \"ANSI95\"\n"); } else { SS7_ERROR("\tFound an invalid linktype of \"%s\"!\n", parm->val); return FTDM_FAIL; @@ -568,7 +580,7 @@ static int ftmod_ss7_parse_mtp_link(ftdm_conf_node_t *mtp_link, sng_mtp_link_t * /**********************************************************************/ } else if (!strcasecmp(parm->var, "slc")) { mtpLink->mtp3.slc = atoi(parm->val); - SS7_DEBUG("\tFoundmtpLink->slc = \"%d\"\n",mtpLink->mtp3.slc); + SS7_DEBUG("\tFound mtpLink->slc = \"%d\"\n",mtpLink->mtp3.slc); /**********************************************************************/ } else { SS7_ERROR("\tFound an invalid parameter \"%s\"!\n", parm->val); @@ -649,14 +661,17 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route) /* check if the name matches */ if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[x].name, parm->val)) { - /* grab the mtpLink id value first*/ - int id = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].links[0]; - /* now, harvest the required infomormation from the global structure */ - mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.linkType; - mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.switchType; - mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLink[id].mtp3.ssf; - mtpRoute.cmbLinkSetId = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id; + mtpRoute.linkType = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].linkType; + mtpRoute.switchType = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].switchType; + mtpRoute.ssf = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].ssf; + mtpRoute.linkSetId = g_ftdm_sngss7_data.cfg.mtpLinkSet[x].id; + cmbLinkSetId++; + mtpRoute.cmbLinkSetId = cmbLinkSetId; + + /* update the linkset with the new cmbLinkSet value */ + g_ftdm_sngss7_data.cfg.mtpLinkSet[x].numLinks++; + g_ftdm_sngss7_data.cfg.mtpLinkSet[x].links[g_ftdm_sngss7_data.cfg.mtpLinkSet[x].numLinks-1] = mtpRoute.cmbLinkSetId; break; } x++; @@ -692,9 +707,11 @@ static int ftmod_ss7_parse_mtp_route(ftdm_conf_node_t *mtp_route) parm = parm + 1; } + ftmod_ss7_fill_in_nsap(&mtpRoute); + ftmod_ss7_fill_in_mtp3_route(&mtpRoute); - ftmod_ss7_fill_in_nsap(&mtpRoute); + return FTDM_SUCCESS; } @@ -738,7 +755,6 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) int num_parms = isup_interface->n_parameters; int i; int linkSetId; - int linkId; memset(&sng_isup, 0x0, sizeof(sng_isup)); memset(&sng_isap, 0x0, sizeof(sng_isap)); @@ -772,36 +788,25 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) /* check if the name matches */ if (!strcasecmp((char *)g_ftdm_sngss7_data.cfg.mtpRoute[x].name, parm->val)) { - /* now, harvest the required information from the global structure */ sng_isup.mtpRouteId = g_ftdm_sngss7_data.cfg.mtpRoute[x].id; sng_isup.dpc = g_ftdm_sngss7_data.cfg.mtpRoute[x].dpc; sng_isup.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType; sng_isap.switchType = g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType; - /* find the nwID from the nsap */ - int y = 1; - while (g_ftdm_sngss7_data.cfg.nsap[y].id != 0) { - - if ((g_ftdm_sngss7_data.cfg.nsap[y].linkType == g_ftdm_sngss7_data.cfg.mtpRoute[x].linkType) && - (g_ftdm_sngss7_data.cfg.nsap[y].switchType == g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType) && - (g_ftdm_sngss7_data.cfg.nsap[y].ssf == g_ftdm_sngss7_data.cfg.mtpRoute[x].ssf)) { - + /* find the NSAP corresponding to this switchType and SSF */ + int z = 1; + while (g_ftdm_sngss7_data.cfg.nsap[z].id != 0) { + if ((g_ftdm_sngss7_data.cfg.nsap[z].linkType == g_ftdm_sngss7_data.cfg.mtpRoute[x].linkType) && + (g_ftdm_sngss7_data.cfg.nsap[z].switchType == g_ftdm_sngss7_data.cfg.mtpRoute[x].switchType) && + (g_ftdm_sngss7_data.cfg.nsap[z].ssf == g_ftdm_sngss7_data.cfg.mtpRoute[x].ssf)) { + sng_isup.nwId = g_ftdm_sngss7_data.cfg.nsap[z].nwId; /* we have a match so break out of this loop */ break; } /* move on to the next one */ - y++; - } /* while (g_ftdm_sngss7_data.cfg.mtp3_isup[y].id != 0) */ - - /* check how we exited the last while loop */ - if (g_ftdm_sngss7_data.cfg.nsap[y].id == 0) { - SS7_ERROR("\tFailed to find the nwID for = \"%s\"!\n", parm->val); - return FTDM_FAIL; - } else { - sng_isup.nwId = g_ftdm_sngss7_data.cfg.nsap[y].nwId; + z++; } - break; } x++; @@ -846,10 +851,15 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) } /* trickle down the SPC to all sub entities */ - linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].cmbLinkSetId; - for (i = 0; i < g_ftdm_sngss7_data.cfg.mtpLinkSet[linkSetId].numLinks; i ++) { - linkId = g_ftdm_sngss7_data.cfg.mtpLinkSet[linkSetId].links[i]; - g_ftdm_sngss7_data.cfg.mtpLink[linkId].mtp3.spc = g_ftdm_sngss7_data.cfg.spc; + linkSetId = g_ftdm_sngss7_data.cfg.mtpRoute[sng_isup.mtpRouteId].linkSetId; + + i = 1; + while (g_ftdm_sngss7_data.cfg.mtpLink[i].id != 0) { + if (g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.linkSetId == linkSetId) { + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp3.spc = g_ftdm_sngss7_data.cfg.spc; + } + + i++; } ftmod_ss7_fill_in_isap(&sng_isap); @@ -858,8 +868,6 @@ static int ftmod_ss7_parse_isup_interface(ftdm_conf_node_t *isup_interface) ftmod_ss7_fill_in_isup_interface(&sng_isup); - g_ftdm_sngss7_data.cfg.isap[sng_isap.id].spId = sng_isup.id; - return FTDM_SUCCESS; } @@ -957,7 +965,7 @@ static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink) if ( mtpLink->mtp2.t7 != 0 ) { g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7 = mtpLink->mtp2.t7; }else { - g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7 = 20; + g_ftdm_sngss7_data.cfg.mtpLink[i].mtp2.t7 = 40; } if (mtpLink->mtp3.t1 != 0) { @@ -1057,21 +1065,19 @@ static int ftmod_ss7_fill_in_mtpLink(sng_mtp_link_t *mtpLink) /******************************************************************************/ static int ftmod_ss7_fill_in_mtpLinkSet(sng_link_set_t *mtpLinkSet) { - int count; int i = mtpLinkSet->id; strcpy((char *)g_ftdm_sngss7_data.cfg.mtpLinkSet[i].name, (char *)mtpLinkSet->name); g_ftdm_sngss7_data.cfg.mtpLinkSet[i].id = mtpLinkSet->id; g_ftdm_sngss7_data.cfg.mtpLinkSet[i].apc = mtpLinkSet->apc; - g_ftdm_sngss7_data.cfg.mtpLinkSet[i].linkType = g_ftdm_sngss7_data.cfg.mtpLink[1].mtp3.linkType; /* KONRAD FIX ME */ + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].linkType = mtpLinkSet->linkType; + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].switchType = mtpLinkSet->switchType; + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].ssf = mtpLinkSet->ssf; + + /* these values are filled in as we find routes and start allocating cmbLinkSetIds */ g_ftdm_sngss7_data.cfg.mtpLinkSet[i].minActive = mtpLinkSet->minActive; - g_ftdm_sngss7_data.cfg.mtpLinkSet[i].numLinks = mtpLinkSet->numLinks; - - for (count = 0; count < mtpLinkSet->numLinks; count++) { - g_ftdm_sngss7_data.cfg.mtpLinkSet[i].links[count] = mtpLinkSet->links[count]; - } - + g_ftdm_sngss7_data.cfg.mtpLinkSet[i].numLinks = 0; return 0; } @@ -1083,8 +1089,7 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route) /* go through all the existing routes and see if we find a match */ i = 1; while (g_ftdm_sngss7_data.cfg.mtpRoute[i].id != 0) { - if (g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc == mtp3_route->dpc) { - + if (!strcasecmp(g_ftdm_sngss7_data.cfg.mtpRoute[i].name, mtp3_route->name)) { /* we have a match so break out of this loop */ break; } @@ -1106,8 +1111,10 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route) g_ftdm_sngss7_data.cfg.mtpRoute[i].dpc = mtp3_route->dpc; g_ftdm_sngss7_data.cfg.mtpRoute[i].linkType = mtp3_route->linkType; g_ftdm_sngss7_data.cfg.mtpRoute[i].switchType = mtp3_route->switchType; - g_ftdm_sngss7_data.cfg.mtpRoute[i].cmbLinkSetId = 1; /* mtp3_route->cmbLinkSetId;*/ + g_ftdm_sngss7_data.cfg.mtpRoute[i].cmbLinkSetId = mtp3_route->cmbLinkSetId; g_ftdm_sngss7_data.cfg.mtpRoute[i].isSTP = mtp3_route->isSTP; + g_ftdm_sngss7_data.cfg.mtpRoute[i].nwId = mtp3_route->nwId; + g_ftdm_sngss7_data.cfg.mtpRoute[i].linkSetId = mtp3_route->linkSetId; g_ftdm_sngss7_data.cfg.mtpRoute[i].ssf = mtp3_route->ssf; if (mtp3_route->t6 != 0) { g_ftdm_sngss7_data.cfg.mtpRoute[i].t6 = mtp3_route->t6; @@ -1159,6 +1166,11 @@ static int ftmod_ss7_fill_in_mtp3_route(sng_route_t *mtp3_route) } else { g_ftdm_sngss7_data.cfg.mtpRoute[i].t25 = 100; } + if (mtp3_route->t26 != 0) { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t26 = mtp3_route->t26; + } else { + g_ftdm_sngss7_data.cfg.mtpRoute[i].t26 = 100; + } return 0; } @@ -1184,15 +1196,17 @@ static int ftmod_ss7_fill_in_nsap(sng_route_t *mtp3_route) if (g_ftdm_sngss7_data.cfg.nsap[i].id == 0) { g_ftdm_sngss7_data.cfg.nsap[i].id = i; + mtp3_route->nwId = i; SS7_DEBUG("found new mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id); } else { g_ftdm_sngss7_data.cfg.nsap[i].id = i; + mtp3_route->nwId = i; SS7_DEBUG("found existing mtp3_isup interface, id is = %d\n", g_ftdm_sngss7_data.cfg.nsap[i].id); } g_ftdm_sngss7_data.cfg.nsap[i].spId = g_ftdm_sngss7_data.cfg.nsap[i].id; g_ftdm_sngss7_data.cfg.nsap[i].suId = g_ftdm_sngss7_data.cfg.nsap[i].id; - g_ftdm_sngss7_data.cfg.nsap[i].nwId = g_ftdm_sngss7_data.cfg.nsap[i].id; + g_ftdm_sngss7_data.cfg.nsap[i].nwId = mtp3_route->nwId; g_ftdm_sngss7_data.cfg.nsap[i].linkType = mtp3_route->linkType; g_ftdm_sngss7_data.cfg.nsap[i].switchType = mtp3_route->switchType; g_ftdm_sngss7_data.cfg.nsap[i].ssf = mtp3_route->ssf; @@ -1208,7 +1222,7 @@ static int ftmod_ss7_fill_in_isup_interface(sng_isup_inf_t *sng_isup) /* go through all the existing interfaces and see if we find a match */ i = 1; while (g_ftdm_sngss7_data.cfg.isupIntf[i].id != 0) { - if (g_ftdm_sngss7_data.cfg.isupIntf[i].nwId == sng_isup->nwId) { + if (!strcasecmp(g_ftdm_sngss7_data.cfg.isupIntf[i].name, sng_isup->name)) { /* we have a match so break out of this loop */ break; @@ -1381,7 +1395,8 @@ static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap) } g_ftdm_sngss7_data.cfg.isap[i].id = sng_isap->id; - g_ftdm_sngss7_data.cfg.isap[i].suId = 1; /*KONRAD FIX ME */ + g_ftdm_sngss7_data.cfg.isap[i].suId = sng_isap->id; + g_ftdm_sngss7_data.cfg.isap[i].spId = sng_isap->id; g_ftdm_sngss7_data.cfg.isap[i].switchType = sng_isap->switchType; g_ftdm_sngss7_data.cfg.isap[i].ssf = sng_isap->ssf; @@ -1458,7 +1473,7 @@ static int ftmod_ss7_fill_in_isap(sng_isap_t *sng_isap) if (sng_isap->tex != 0) { g_ftdm_sngss7_data.cfg.isap[i].tex = sng_isap->tex; } else { - g_ftdm_sngss7_data.cfg.isap[i].tex = 10; + g_ftdm_sngss7_data.cfg.isap[i].tex = 1000; } if (sng_isap->tcrm != 0) { g_ftdm_sngss7_data.cfg.isap[i].tcrm = sng_isap->tcrm; @@ -1499,7 +1514,9 @@ static int ftmod_ss7_fill_in_self_route(int spc, int linkType, int switchType, i SS7_DEBUG("found existing mtp3 self route\n"); return FTDM_SUCCESS; } else { - SS7_ERROR("found new mtp3 self route but it does not much the route already configured\n"); + SS7_ERROR("found new mtp3 self route but it does not match the route already configured (dpc=%d:spc=%d)\n", + g_ftdm_sngss7_data.cfg.mtpRoute[0].dpc, + spc); return FTDM_FAIL; } @@ -1583,11 +1600,10 @@ static int ftmod_ss7_fill_in_circuits(char *ch_map, int cicbase, int typeCntrl, g_ftdm_sngss7_data.cfg.isupCkt[x].chan = count; if (timeslot.siglink) { g_ftdm_sngss7_data.cfg.isupCkt[x].type = SIG; - } else if (timeslot.hole) { - g_ftdm_sngss7_data.cfg.isupCkt[x].type = HOLE; } else { - g_ftdm_sngss7_data.cfg.isupCkt[x].type = VOICE; + g_ftdm_sngss7_data.cfg.isupCkt[x].type = HOLE; } + if (timeslot.channel) { g_ftdm_sngss7_data.cfg.isupCkt[x].cic = cicbase; cicbase++; @@ -1608,6 +1624,10 @@ static int ftmod_ss7_fill_in_circuits(char *ch_map, int cicbase, int typeCntrl, g_ftdm_sngss7_data.cfg.isupCkt[x].obj = ss7_info; } /* if (g_ftdm_sngss7_data.cfg.isupCkt[x].id == 0) */ + + /* increment the span channel count */ + count++; + } else { /* if ((timeslot.siglink) || (timeslot.gap)) */ /* find the ftdm the channel structure for this channel*/ i = 1; diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 0437e02e51..1f50a2ccaa 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -386,7 +386,7 @@ typedef struct ftdm_conf_parameter { } ftdm_conf_parameter_t; /*! \brief Opaque general purpose iterator */ -typedef void ftdm_iterator_t; +typedef struct ftdm_iterator ftdm_iterator_t; /*! \brief Channel commands that can be executed through ftdm_channel_command() */ typedef enum { @@ -1032,8 +1032,19 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_add_var(ftdm_channel_t *ftdmchan, const c FT_DECLARE(const char *) ftdm_channel_get_var(ftdm_channel_t *ftdmchan, const char *var_name); /*! \brief Get an iterator to iterate over the channel variables - * \note The iterator pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. */ -FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan); + * \param ftdmchan The channel structure containing the variables + * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator. + * \note The iterator pointer returned is only valid while the channel is open and it'll be destroyed when the channel is closed. + * This iterator is completely non-thread safe, if you are adding variables or removing variables while iterating + * results are unpredictable + */ +FT_DECLARE(ftdm_iterator_t *) ftdm_channel_get_var_iterator(const ftdm_channel_t *ftdmchan, ftdm_iterator_t *iter); + +/*! \brief Get iterator current value (depends on the iterator type) + * \note Channel iterators return a pointer to ftdm_channel_t + * Variable iterators return a pointer to the variable name (not the variable value) + */ +FT_DECLARE(void *) ftdm_iterator_current(ftdm_iterator_t *iter); /*! \brief Get variable name and value for the current iterator position */ FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, const char **var_name, const char **var_val); @@ -1041,6 +1052,11 @@ FT_DECLARE(ftdm_status_t) ftdm_channel_get_current_var(ftdm_iterator_t *iter, co /*! \brief Advance iterator */ FT_DECLARE(ftdm_iterator_t *) ftdm_iterator_next(ftdm_iterator_t *iter); +/*! \brief Free iterator + * \note You must free an iterator after using it unless you plan to reuse it + */ +FT_DECLARE(ftdm_status_t) ftdm_iterator_free(ftdm_iterator_t *iter); + /*! \brief Get the span pointer associated to the channel */ FT_DECLARE(ftdm_span_t *) ftdm_channel_get_span(const ftdm_channel_t *ftdmchan); @@ -1144,6 +1160,12 @@ FT_DECLARE(uint32_t) ftdm_span_get_id(const ftdm_span_t *span); /*! \brief Get the span name */ FT_DECLARE(const char *) ftdm_span_get_name(const ftdm_span_t *span); +/*! \brief Get iterator for the span channels + * \param span The span containing the channels + * \param iter Optional iterator. You can reuse an old iterator (not previously freed) to avoid the extra allocation of a new iterator. + */ +FT_DECLARE(ftdm_iterator_t *) ftdm_span_get_chan_iterator(const ftdm_span_t *span, ftdm_iterator_t *iter); + /*! * \brief Execute a text command. The text command output will be returned and must be free'd * diff --git a/libs/freetdm/src/include/private/ftdm_core.h b/libs/freetdm/src/include/private/ftdm_core.h index 74bea8148c..d8947f6de4 100644 --- a/libs/freetdm/src/include/private/ftdm_core.h +++ b/libs/freetdm/src/include/private/ftdm_core.h @@ -619,6 +619,9 @@ FT_DECLARE(ftdm_status_t) ftdm_span_trigger_signals(const ftdm_span_t *span); #define ftdm_log_chan(fchan, level, format, ...) ftdm_log(level, "[s%dc%d][%d:%d] " format, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id, __VA_ARGS__) #define ftdm_log_chan_msg(fchan, level, msg) ftdm_log(level, "[s%dc%d][%d:%d] " msg, fchan->span_id, fchan->chan_id, fchan->physical_span_id, fchan->physical_chan_id) +#define ftdm_span_lock(span) ftdm_mutex_lock(span->mutex) +#define ftdm_span_unlock(span) ftdm_mutex_unlock(span->mutex) + FT_DECLARE_DATA extern const char *FTDM_LEVEL_NAMES[9]; static __inline__ void ftdm_abort(void) diff --git a/libs/freetdm/src/include/private/ftdm_types.h b/libs/freetdm/src/include/private/ftdm_types.h index d8e8b5c2e6..ba6956344d 100644 --- a/libs/freetdm/src/include/private/ftdm_types.h +++ b/libs/freetdm/src/include/private/ftdm_types.h @@ -366,6 +366,23 @@ typedef ftdm_status_t (*ftdm_span_start_t)(ftdm_span_t *span); typedef ftdm_status_t (*ftdm_span_stop_t)(ftdm_span_t *span); typedef ftdm_status_t (*ftdm_channel_sig_read_t)(ftdm_channel_t *ftdmchan, void *data, ftdm_size_t size); +typedef enum { + FTDM_ITERATOR_VARS = 1, + FTDM_ITERATOR_CHANS, +} ftdm_iterator_type_t; + +struct ftdm_iterator { + ftdm_iterator_type_t type; + unsigned int allocated:1; + union { + struct { + int32_t index; + const ftdm_span_t *span; + } chaniter; + ftdm_hash_iterator_t *hashiter; + } pvt; +}; + #ifdef __cplusplus } #endif