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"))) { if ((spans = switch_xml_child(cfg, "pri_spans"))) {
for (myspan = switch_xml_child(spans, "span"); myspan; myspan = myspan->next) { 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"); char *name = (char *) switch_xml_attr(myspan, "name");
ftdm_conf_parameter_t spanparameters[10];
ftdm_status_t zstatus = FTDM_FAIL; ftdm_status_t zstatus = FTDM_FAIL;
const char *context = "default"; const char *context = "default";
const char *dialplan = "XML"; const char *dialplan = "XML";
//Q921NetUser_t mode = Q931_TE; unsigned paramindex = 0;
//Q931Dialect_t dialect = Q931_Dialect_National;
char *mode = NULL;
char *dialect = NULL;
uint32_t span_id = 0;
ftdm_span_t *span = NULL; ftdm_span_t *span = NULL;
const char *tonegroup = NULL; uint32_t span_id = 0;
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);
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 *var = (char *) switch_xml_attr_soft(param, "name");
char *val = (char *) switch_xml_attr_soft(param, "value"); char *val = (char *) switch_xml_attr_soft(param, "value");
if (!strcasecmp(var, "tonegroup")) { if (ftdm_array_len(spanparameters) == paramindex) {
tonegroup = val; ftdm_log(FTDM_LOG_ERROR, "Too many parameters for pri span '%s', ignoring everything after '%s'\n", name, var);
} else if (!strcasecmp(var, "mode")) { break;
mode = val; }
} else if (!strcasecmp(var, "dialect")) {
dialect = val; if (!strcasecmp(var, "context")) {
} 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")) {
context = val; context = val;
} else if (!strcasecmp(var, "opts")) {
opts = val;
} else if (!strcasecmp(var, "dialplan")) { } else if (!strcasecmp(var, "dialplan")) {
dialplan = val; dialplan = val;
} else if (!strcasecmp(var, "digit_timeout") || !strcasecmp(var, "digit-timeout")) { } else {
digit_timeout = val; spanparameters[paramindex].var = var;
} spanparameters[paramindex].val = val;
} paramindex++;
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);
} }
} }
if (digit_timeout) { zstatus = ftdm_span_find_by_name(name, &span);
to = atoi(digit_timeout);
}
if (zstatus != FTDM_SUCCESS) { 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; continue;
} }
if (!span_id) { span_id = ftdm_span_get_id(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);
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));
continue; continue;
} }

View File

@ -54,6 +54,11 @@
#define DEFAULT_NATIONAL_PREFIX "0" #define DEFAULT_NATIONAL_PREFIX "0"
#define DEFAULT_INTERNATIONAL_PREFIX "00" #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 * PCAP
* Based on Helmut Kuper's (<helmut.kuper@ewetel.de>) implementation, * 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) static int32_t parse_loglevel(const char *level)
{ {
if (!level) { if (!level)
return -1; return -1;
}
if (!strcasecmp(level, "debug")) { if (!strcasecmp(level, "debug")) {
return FTDM_LOG_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 || !flags)
return -1;
if (!in) {
return 0;
}
if (strstr(in, "suggest_channel")) { if (strstr(in, "suggest_channel")) {
flags |= FTDM_ISDN_OPT_SUGGEST_CHANNEL; *flags |= FTDM_ISDN_OPT_SUGGEST_CHANNEL;
} }
if (strstr(in, "omit_display")) { if (strstr(in, "omit_display")) {
flags |= FTDM_ISDN_OPT_OMIT_DISPLAY_IE; *flags |= FTDM_ISDN_OPT_OMIT_DISPLAY_IE;
} }
if (strstr(in, "disable_tones")) { 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) { if (!in || !dialect)
return Q931_Dialect_Count; return -1;
}
#if __UNSUPPORTED__ #if __UNSUPPORTED__
if (!strcasecmp(in, "national")) { if (!strcasecmp(in, "national")) {
return Q931_Dialect_National; *dialect = Q931_Dialect_National;
return 0;
} }
if (!strcasecmp(in, "dms")) { if (!strcasecmp(in, "dms")) {
return Q931_Dialect_DMS; *dialect = Q931_Dialect_DMS;
return 0;
} }
#endif #endif
if (!strcasecmp(in, "5ess")) { if (!strcasecmp(in, "5ess")) {
return Q931_Dialect_5ESS; *dialect = Q931_Dialect_5ESS;
return 0;
} }
if (!strcasecmp(in, "dss1")) { if (!strcasecmp(in, "dss1") || !strcasecmp(in, "euroisdn")) {
return Q931_Dialect_DSS1; *dialect = Q931_Dialect_DSS1;
return 0;
} }
if (!strcasecmp(in, "q931")) { 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; 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; Q931Dialect_t dialect = Q931_Dialect_National;
ftdm_channel_t *dchan = NULL;
ftdm_isdn_data_t *isdn_data;
int32_t digit_timeout = 0; int32_t digit_timeout = 0;
const char *tonemap = "us";
int dchan_count = 0, bchan_count = 0;
int q921loglevel = -1; int q921loglevel = -1;
int q931loglevel = -1; int q931loglevel = -1;
uint32_t i;
if (span->signal_type) { 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; return FTDM_FAIL;
} }
if (span->trunk_type >= FTDM_TRUNK_NONE) { if (ftdm_span_get_trunk_type(span) >= FTDM_TRUNK_NONE) {
ftdm_log(FTDM_LOG_WARNING, "Invalid trunk type '%s' defaulting to T1.\n", ftdm_trunk_type2str(span->trunk_type)); 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; span->trunk_type = FTDM_TRUNK_T1;
} }
for(i = 1; i <= span->chan_count; i++) { for (i = 1; i <= ftdm_span_get_chan_count(span); i++) {
if (span->channels[i]->type == FTDM_CHAN_TYPE_DQ921) { ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
if (x > 1) {
snprintf(span->last_error, sizeof(span->last_error), "Span has more than 2 D-Channels!"); 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; return FTDM_FAIL;
} }
if (ftdm_channel_open(span->span_id, i, &dchans[x]) == FTDM_SUCCESS) { 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", x, dchans[x]->span_id, dchans[x]->chan_id); ftdm_log(FTDM_LOG_DEBUG, "opening d-channel #%d %d:%d\n", dchan_count,
dchans[x]->state = FTDM_CHANNEL_STATE_UP; ftdm_channel_get_span_id(dchan), ftdm_channel_get_id(dchan));
x++; dchan->state = FTDM_CHANNEL_STATE_UP;
} }
dchan_count++;
break;
case FTDM_CHAN_TYPE_B:
bchan_count++;
break;
default:
break;
} }
} }
if (!x) { if (!dchan_count) {
snprintf(span->last_error, sizeof(span->last_error), "Span has no D-Channels!"); 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; return FTDM_FAIL;
} }
@ -2611,52 +2651,55 @@ static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span)
isdn_data->mode = Q931_TE; isdn_data->mode = Q931_TE;
dialect = Q931_Dialect_Q931; 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 (!strcasecmp(var, "mode")) {
if (!(val = va_arg(ap, char *))) { if ((isdn_data->mode = parse_mode(val)) < 0) {
break; 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")) { } else if (!strcasecmp(var, "dialect")) {
if (!(val = va_arg(ap, char *))) { if (parse_dialect(val, &dialect) < 0) {
break; ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown dialect '%s'\n", val);
}
dialect = parse_dialect(val);
if (dialect == Q931_Dialect_Count) {
snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown dialect [%s]!", val); snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown dialect [%s]!", val);
return FTDM_FAIL; return FTDM_FAIL;
} }
} else if (!strcasecmp(var, "opts")) { } else if (!strcasecmp(var, "opts")) {
if (!(val = va_arg(ap, char *))) { if (parse_opts(val, &isdn_data->opts) < 0) {
break; 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")) { } else if (!strcasecmp(var, "tonemap")) {
if (!(val = va_arg(ap, char *))) {
break;
}
tonemap = (const char *)val; tonemap = (const char *)val;
} else if (!strcasecmp(var, "digit_timeout")) { } else if (!strcasecmp(var, "digit_timeout")) {
int *optp; digit_timeout = atoi(val);
if (!(optp = va_arg(ap, int *))) { if (digit_timeout < 3000 || digit_timeout > 30000) {
break; 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")) { } else if (!strcasecmp(var, "q921loglevel")) {
q921loglevel = va_arg(ap, int); if ((q921loglevel = parse_loglevel(val)) < 0) {
if (q921loglevel < Q921_LOG_NONE) { ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown loglevel '%s'\n", val);
q921loglevel = Q921_LOG_NONE; snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown loglevel [%s]!", val);
} else if (q921loglevel > Q921_LOG_DEBUG) { return FTDM_FAIL;
q921loglevel = Q921_LOG_DEBUG;
} }
} else if (!strcasecmp(var, "q931loglevel")) { } else if (!strcasecmp(var, "q931loglevel")) {
q931loglevel = va_arg(ap, int); if ((q931loglevel = parse_loglevel(val)) < 0) {
if (q931loglevel < Q931_LOG_NONE) { ftdm_log(FTDM_LOG_ERROR, "Invalid/unknown loglevel '%s'\n", val);
q931loglevel = Q931_LOG_NONE; snprintf(span->last_error, sizeof(span->last_error), "Invalid/unknown loglevel [%s]!", val);
} else if (q931loglevel > Q931_LOG_DEBUG) { return FTDM_FAIL;
q931loglevel = Q931_LOG_DEBUG;
} }
} else { } else {
ftdm_log(FTDM_LOG_ERROR, "Unknown parameter '%s'\n", var);
snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var); snprintf(span->last_error, sizeof(span->last_error), "Unknown parameter [%s]", var);
return FTDM_FAIL; return FTDM_FAIL;
} }
@ -2665,39 +2708,35 @@ static FIO_SIG_CONFIGURE_FUNCTION(isdn_configure_span)
if (!digit_timeout) { if (!digit_timeout) {
digit_timeout = DEFAULT_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 */ /* allocate per b-chan data */
if (isdn_data->mode == Q931_NT) { if (isdn_data->mode == Q931_NT) {
ftdm_isdn_bchan_data_t *data; 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) { if (!data) {
return FTDM_FAIL; return FTDM_FAIL;
} }
for (i = 1; i <= span->chan_count; i++, data++) { for (i = 1; i <= ftdm_span_get_chan_count(span); i++, data++) {
if (span->channels[i]->type == FTDM_CHAN_TYPE_B) { ftdm_channel_t *chan = ftdm_span_get_channel(span, i);
span->channels[i]->mod_data = data;
if (ftdm_channel_get_type(chan) == FTDM_CHAN_TYPE_B) {
chan->mod_data = data;
memset(data, 0, sizeof(ftdm_isdn_bchan_data_t)); memset(data, 0, sizeof(ftdm_isdn_bchan_data_t));
} }
} }
} }
isdn_data->sig_cb = sig_cb; isdn_data->sig_cb = sig_cb;
isdn_data->dchans[0] = dchans[0]; isdn_data->dchan = dchan;
isdn_data->dchans[1] = dchans[1];
isdn_data->dchan = isdn_data->dchans[0];
isdn_data->digit_timeout = digit_timeout; isdn_data->digit_timeout = digit_timeout;
Q921_InitTrunk(&isdn_data->q921, Q921_InitTrunk(&isdn_data->q921,
0, 0,
0, 0,
isdn_data->mode, 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, 0,
ftdm_isdn_921_21, ftdm_isdn_921_21,
(Q921Tx23CB_t)ftdm_isdn_921_23, (Q921Tx23CB_t)ftdm_isdn_921_23,
@ -2798,7 +2837,7 @@ ftdm_module_t ftdm_module = {
.io_unload = NULL, .io_unload = NULL,
.sig_load = isdn_load, .sig_load = isdn_load,
.sig_unload = isdn_unload, .sig_unload = isdn_unload,
.sig_configure = isdn_configure_span .configure_span_signaling = isdn_configure_span
}; };
/* For Emacs: /* For Emacs: