From 47af9933c425e2921d4350dfc78206b27ca01be7 Mon Sep 17 00:00:00 2001 From: Stefan Knoblich Date: Sun, 14 Nov 2010 15:44:50 +0100 Subject: [PATCH] freetdm: convert ftmod_isdn to use (+ pri_spans) to use ftdm_configure_span_signaling() interface. Signed-off-by: Stefan Knoblich --- libs/freetdm/mod_freetdm/mod_freetdm.c | 101 ++------- .../freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c | 213 +++++++++++------- 2 files changed, 150 insertions(+), 164 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index 4fda283aeb..aaddbf69f0 100755 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -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; } diff --git a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c index 2b34552950..c5294bf1b2 100644 --- a/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c +++ b/libs/freetdm/src/ftmod/ftmod_isdn/ftmod_isdn.c @@ -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 () 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: