freetdm: convert ftmod_isdn to use (+ pri_spans) to use ftdm_configure_span_signaling() interface.

Signed-off-by: Stefan Knoblich <s.knoblich@axsentis.de>
This commit is contained in:
Stefan Knoblich 2010-11-14 15:44:50 +01:00
parent 197e4b71d6
commit 47af9933c4
2 changed files with 150 additions and 164 deletions

View File

@ -2923,102 +2923,49 @@ static switch_status_t load_config(void)
if ((spans = switch_xml_child(cfg, "pri_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) {
char *id = (char *) switch_xml_attr(myspan, "id");
char *name = (char *) switch_xml_attr(myspan, "name");
ftdm_conf_parameter_t spanparameters[10];
ftdm_status_t zstatus = FTDM_FAIL;
const char *context = "default";
const char *dialplan = "XML";
//Q921NetUser_t mode = Q931_TE;
//Q931Dialect_t dialect = Q931_Dialect_National;
char *mode = NULL;
char *dialect = NULL;
uint32_t span_id = 0;
unsigned paramindex = 0;
ftdm_span_t *span = NULL;
const char *tonegroup = NULL;
char *digit_timeout = NULL;
const char *opts = "none";
uint32_t to = 0;
int q921loglevel = -1;
int q931loglevel = -1;
// quick debug
//switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ID: '%s', Name:'%s'\n",id,name);
uint32_t span_id = 0;
for (param = switch_xml_child(myspan, "param"); param; param = param->next) {
if (!name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required attribute 'name'\n");
continue;
}
for (param = switch_xml_child(myspan, "param"); param && paramindex < 10; param = param->next) {
char *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "tonegroup")) {
tonegroup = val;
} else if (!strcasecmp(var, "mode")) {
mode = val;
} else if (!strcasecmp(var, "dialect")) {
dialect = val;
} else if (!strcasecmp(var, "q921loglevel")) {
if ((q921loglevel = switch_log_str2level(val)) == SWITCH_LOG_INVALID) {
q921loglevel = -1;
}
} else if (!strcasecmp(var, "q931loglevel")) {
if ((q931loglevel = switch_log_str2level(val)) == SWITCH_LOG_INVALID) {
q931loglevel = -1;
}
} else if (!strcasecmp(var, "context")) {
if (ftdm_array_len(spanparameters) == paramindex) {
ftdm_log(FTDM_LOG_ERROR, "Too many parameters for pri span '%s', ignoring everything after '%s'\n", name, var);
break;
}
if (!strcasecmp(var, "context")) {
context = val;
} else if (!strcasecmp(var, "opts")) {
opts = val;
} else if (!strcasecmp(var, "dialplan")) {
dialplan = val;
} else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) {
digit_timeout = val;
}
}
if (!id && !name) {
switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "span missing required param 'id'\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);
} else {
spanparameters[paramindex].var = var;
spanparameters[paramindex].val = val;
paramindex++;
}
}
if (digit_timeout) {
to = atoi(digit_timeout);
}
zstatus = ftdm_span_find_by_name(name, &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));
ftdm_log(FTDM_LOG_ERROR, "Error finding FreeTDM span %s\n", name);
continue;
}
if (!span_id) {
span_id = ftdm_span_get_id(span);
}
if (!tonegroup) {
tonegroup = "us";
}
if (ftdm_configure_span(span, "isdn", on_clear_channel_signal,
"mode", mode,
"dialect", dialect,
"digit_timeout", &to,
"opts", opts,
"tonemap", tonegroup,
"q921loglevel", q921loglevel,
"q931loglevel", q931loglevel,
FTDM_TAG_END) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error starting FreeTDM span %d mode: %s dialect: %s error: %s\n", span_id,
mode, dialect, ftdm_span_get_last_error(span));
span_id = ftdm_span_get_id(span);
if (ftdm_configure_span_signaling(span, "isdn", on_clear_channel_signal, spanparameters) != FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_ERROR, "Error configuring FreeTDM span %s\n", name);
continue;
}

View File

@ -54,6 +54,11 @@
#define DEFAULT_NATIONAL_PREFIX "0"
#define DEFAULT_INTERNATIONAL_PREFIX "00"
static const char *ftdm_span_get_trunk_type_str(const ftdm_span_t *span)
{
return ftdm_trunk_type2str(span->trunk_type);
}
/*****************************************************************************************
* PCAP
* Based on Helmut Kuper's (<helmut.kuper@ewetel.de>) implementation,
@ -2266,9 +2271,8 @@ static ftdm_status_t ftdm_isdn_start(ftdm_span_t *span)
static int32_t parse_loglevel(const char *level)
{
if (!level) {
if (!level)
return -1;
}
if (!strcasecmp(level, "debug")) {
return FTDM_LOG_LEVEL_DEBUG;
@ -2291,53 +2295,53 @@ static int32_t parse_loglevel(const char *level)
}
}
static uint32_t parse_opts(const char *in)
static int parse_opts(const char *in, uint32_t *flags)
{
uint32_t flags = 0;
if (!in) {
return 0;
}
if (!in || !flags)
return -1;
if (strstr(in, "suggest_channel")) {
flags |= FTDM_ISDN_OPT_SUGGEST_CHANNEL;
*flags |= FTDM_ISDN_OPT_SUGGEST_CHANNEL;
}
if (strstr(in, "omit_display")) {
flags |= FTDM_ISDN_OPT_OMIT_DISPLAY_IE;
*flags |= FTDM_ISDN_OPT_OMIT_DISPLAY_IE;
}
if (strstr(in, "disable_tones")) {
flags |= FTDM_ISDN_OPT_DISABLE_TONES;
*flags |= FTDM_ISDN_OPT_DISABLE_TONES;
}
return flags;
return 0;
}
static uint32_t parse_dialect(const char *in)
static int parse_dialect(const char *in, uint32_t *dialect)
{
if (!in) {
return Q931_Dialect_Count;
}
if (!in || !dialect)
return -1;
#if __UNSUPPORTED__
if (!strcasecmp(in, "national")) {
return Q931_Dialect_National;
*dialect = Q931_Dialect_National;
return 0;
}
if (!strcasecmp(in, "dms")) {
return Q931_Dialect_DMS;
*dialect = Q931_Dialect_DMS;
return 0;
}
#endif
if (!strcasecmp(in, "5ess")) {
return Q931_Dialect_5ESS;
*dialect = Q931_Dialect_5ESS;
return 0;
}
if (!strcasecmp(in, "dss1")) {
return Q931_Dialect_DSS1;
if (!strcasecmp(in, "dss1") || !strcasecmp(in, "euroisdn")) {
*dialect = Q931_Dialect_DSS1;
return 0;
}
if (!strcasecmp(in, "q931")) {
return Q931_Dialect_Q931;
*dialect = Q931_Dialect_Q931;
return 0;
}
return Q931_Dialect_Count;
return -1;
}
@ -2563,44 +2567,80 @@ done:
return FTDM_SUCCESS;
}
static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span)
static int parse_mode(const char *mode)
{
if (!mode)
return -1;
if (!strcasecmp(mode, "user") || !strcasecmp(mode, "cpe")) {
return Q931_TE;
}
if (!strcasecmp(mode, "net") || !strcasecmp(mode, "network")) {
return Q931_NT;
}
return -1;
}
static FIO_CONFIGURE_SPAN_SIGNALING_FUNCTION(isdn_configure_span)
{
uint32_t i, x = 0;
ftdm_channel_t *dchans[2] = { 0 };
ftdm_isdn_data_t *isdn_data;
const char *tonemap = "us";
char *var, *val;
Q931Dialect_t dialect = Q931_Dialect_National;
ftdm_channel_t *dchan = NULL;
ftdm_isdn_data_t *isdn_data;
int32_t digit_timeout = 0;
const char *tonemap = "us";
int dchan_count = 0, bchan_count = 0;
int q921loglevel = -1;
int q931loglevel = -1;
uint32_t i;
if (span->signal_type) {
snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d].", span->signal_type);
ftdm_log(FTDM_LOG_ERROR, "Span is already configured for signalling [%d]\n", span->signal_type);
snprintf(span->last_error, sizeof(span->last_error), "Span is already configured for signalling [%d]", span->signal_type);
return FTDM_FAIL;
}
if (span->trunk_type >= FTDM_TRUNK_NONE) {
ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type));
if (ftdm_span_get_trunk_type(span) >= FTDM_TRUNK_NONE) {
ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1\n", ftdm_span_get_trunk_type_str(span));
span->trunk_type = FTDM_TRUNK_T1;
}
for(i = 1; i <= span->chan_count; i++) {
if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) {
if (x > 1) {
snprintf(span->last_error, sizeof(span->last_error), "Span has more than 2 D-Channels!");
for (i = 1; i <= ftdm_span_get_chan_count(span); i++) {
ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
switch (ftdm_channel_get_type(chan)) {
case FTDM_CHAN_TYPE_DQ921:
if (dchan_count > 1) {
ftdm_log(FTDM_LOG_ERROR, "Span has more than 1 D-Channel!\n");
snprintf(span->last_error, sizeof(span->last_error), "Span has more than 1 D-Channel!");
return FTDM_FAIL;
}
if (ftdm_channel_open(span->span_id, i, &dchans[x]) == FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", x, dchans[x]->span_id, dchans[x]->chan_id);
dchans[x]->state = FTDM_CHANNEL_STATE_UP;
x++;
if (ftdm_channel_open(ftdm_span_get_id(span), i, &dchan) == FTDM_SUCCESS) {
ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", dchan_count,
ftdm_channel_get_span_id(dchan), ftdm_channel_get_id(dchan));
dchan->state = FTDM_CHANNEL_STATE_UP;
}
dchan_count++;
break;
case FTDM_CHAN_TYPE_B:
bchan_count++;
break;
default:
break;
}
}
if (!x) {
snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channels!");
if (!dchan_count) {
ftdm_log(FTDM_LOG_ERROR, "Span has no D-Channel!\n");
snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channel!");
return FTDM_FAIL;
}
if (!bchan_count) {
ftdm_log(FTDM_LOG_ERROR, "Span has no B-Channels!\n");
snprintf(span->last_error, sizeof(span->last_error), "Span has no B-Channels!");
return FTDM_FAIL;
}
@ -2611,52 +2651,55 @@ static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span)
isdn_data->mode = Q931_TE;
dialect = Q931_Dialect_Q931;
while((var = va_arg(ap, char *))) {
for (i = 0; ftdm_parameters[i].var; i++) {
const char *var = ftdm_parameters[i].var;
const char *val = ftdm_parameters[i].val;
if (!val) {
ftdm_log(FTDM_LOG_ERROR, "Variable '%s' has no value\n", var);
return FTDM_FAIL;
}
if (!strcasecmp(var, "mode")) {
if (!(val = va_arg(ap, char *))) {
break;
if ((isdn_data->mode = parse_mode(val)) < 0) {
ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown mode '%s'\n", val);
snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown mode [%s]!", val);
return FTDM_FAIL;
}
isdn_data->mode = strcasecmp(val, "net") ? Q931_TE : Q931_NT;
} else if (!strcasecmp(var, "dialect")) {
if (!(val = va_arg(ap, char *))) {
break;
}
dialect = parse_dialect(val);
if (dialect == Q931_Dialect_Count) {
if (parse_dialect(val, &dialect) < 0) {
ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown dialect '%s'\n", val);
snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown dialect [%s]!", val);
return FTDM_FAIL;
}
} else if (!strcasecmp(var, "opts")) {
if (!(val = va_arg(ap, char *))) {
break;
if (parse_opts(val, &isdn_data->opts) < 0) {
ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown options '%s'\n", val);
snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown options [%s]!", val);
return FTDM_FAIL;
}
isdn_data->opts = parse_opts(val);
} else if (!strcasecmp(var, "tonemap")) {
if (!(val = va_arg(ap, char *))) {
break;
}
tonemap = (const char *)val;
} else if (!strcasecmp(var, "digit_timeout")) {
int *optp;
if (!(optp = va_arg(ap, int *))) {
break;
digit_timeout = atoi(val);
if (digit_timeout < 3000 || digit_timeout > 30000) {
ftdm_log(FTDM_LOG_WARNING, "Digit timeout %d ms outside of range (3000 - 30000 ms), using default (10000 ms)\n", digit_timeout);
digit_timeout = DEFAULT_DIGIT_TIMEOUT;
}
digit_timeout = *optp;
} else if (!strcasecmp(var, "q921loglevel")) {
q921loglevel = va_arg(ap, int);
if (q921loglevel < Q921_LOG_NONE) {
q921loglevel = Q921_LOG_NONE;
} else if (q921loglevel > Q921_LOG_DEBUG) {
q921loglevel = Q921_LOG_DEBUG;
if ((q921loglevel = parse_loglevel(val)) < 0) {
ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown loglevel '%s'\n", val);
snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown loglevel [%s]!", val);
return FTDM_FAIL;
}
} else if (!strcasecmp(var, "q931loglevel")) {
q931loglevel = va_arg(ap, int);
if (q931loglevel < Q931_LOG_NONE) {
q931loglevel = Q931_LOG_NONE;
} else if (q931loglevel > Q931_LOG_DEBUG) {
q931loglevel = Q931_LOG_DEBUG;
if ((q931loglevel = parse_loglevel(val)) < 0) {
ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown loglevel '%s'\n", val);
snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown loglevel [%s]!", val);
return FTDM_FAIL;
}
} else {
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s'\n", var);
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
return FTDM_FAIL;
}
@ -2665,39 +2708,35 @@ static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span)
if (!digit_timeout) {
digit_timeout = DEFAULT_DIGIT_TIMEOUT;
}
else if (digit_timeout < 3000 || digit_timeout > 30000) {
ftdm_log(FTDM_LOG_WARNING, "Digit timeout %d ms outside of range (3000 - 30000 ms), using default (10000 ms)\n", digit_timeout);
digit_timeout = DEFAULT_DIGIT_TIMEOUT;
}
/* allocate per b-chan data */
if (isdn_data->mode == Q931_NT) {
ftdm_isdn_bchan_data_t *data;
data = malloc(span->chan_count * sizeof(ftdm_isdn_bchan_data_t));
data = malloc(bchan_count * sizeof(ftdm_isdn_bchan_data_t));
if (!data) {
return FTDM_FAIL;
}
for (i = 1; i <= span->chan_count; i++, data++) {
if (span->channels[i]->type == FTDM_CHAN_TYPE_B) {
span->channels[i]->mod_data = data;
for (i = 1; i <= ftdm_span_get_chan_count(span); i++, data++) {
ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) {
chan->mod_data = data;
memset(data, 0, sizeof(ftdm_isdn_bchan_data_t));
}
}
}
isdn_data->sig_cb = sig_cb;
isdn_data->dchans[0] = dchans[0];
isdn_data->dchans[1] = dchans[1];
isdn_data->dchan = isdn_data->dchans[0];
isdn_data->sig_cb = sig_cb;
isdn_data->dchan = dchan;
isdn_data->digit_timeout = digit_timeout;
Q921_InitTrunk(&isdn_data->q921,
0,
0,
isdn_data->mode,
span->trunk_type == FTDM_TRUNK_BRI_PTMP ? Q921_PTMP : Q921_PTP,
(ftdm_span_get_trunk_type(span) == FTDM_TRUNK_BRI_PTMP) ? Q921_PTMP : Q921_PTP,
0,
ftdm_isdn_921_21,
(Q921Tx23CB_t)ftdm_isdn_921_23,
@ -2798,7 +2837,7 @@ ftdm_module_t ftdm_module = {
.io_unload = NULL,
.sig_load = isdn_load,
.sig_unload = isdn_unload,
.sig_configure = isdn_configure_span
.configure_span_signaling = isdn_configure_span
};
/* For Emacs: