From 99402dd4e02fcf2c64ab240ce96a7a306e6c6c35 Mon Sep 17 00:00:00 2001 From: Moises Silva Date: Wed, 14 Apr 2010 17:59:39 -0400 Subject: [PATCH] implemented freetdm config nodes and ss7 initial configuration --- libs/freetdm/mod_freetdm/mod_freetdm.c | 150 +++++++++++++++++++++++-- libs/freetdm/src/ftdm_config.c | 80 +++++++++++++ libs/freetdm/src/include/freetdm.h | 3 + libs/freetdm/src/include/ftdm_types.h | 26 ++++- 4 files changed, 246 insertions(+), 13 deletions(-) diff --git a/libs/freetdm/mod_freetdm/mod_freetdm.c b/libs/freetdm/mod_freetdm/mod_freetdm.c index d70a0a550b..bc0fd28126 100644 --- a/libs/freetdm/mod_freetdm/mod_freetdm.c +++ b/libs/freetdm/mod_freetdm/mod_freetdm.c @@ -2032,9 +2032,133 @@ static uint32_t enable_analog_option(const char *str, uint32_t current_options) } +/* create ftdm_conf_node_t tree based on a fixed pattern XML configuration list + * last 2 args are for limited aka dumb recursivity + * */ +static int add_config_list_nodes(switch_xml_t swnode, ftdm_conf_node_t *rootnode, + const char *list_name, const char *list_element_name, + const char *sub_list_name, const char *sub_list_element_name) +{ + char *var, *val; + switch_xml_t list; + switch_xml_t element; + switch_xml_t param; + + ftdm_conf_node_t *n_list; + ftdm_conf_node_t *n_element; + + list = switch_xml_child(swnode, list_name); + if (!list) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "no list %s found\n", list_name); + return -1; + } + + if ((FTDM_SUCCESS != ftdm_conf_node_create(list_name, &n_list, rootnode))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node\n", list_name); + return -1; + } + + for (element = switch_xml_child(list, list_element_name); element; element = element->next) { + char *element_name = (char *) switch_xml_attr(element, "name"); + + if (!element_name) { + continue; + } + + if ((FTDM_SUCCESS != ftdm_conf_node_create(list_element_name, &n_element, n_list))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create %s node for %s\n", list_element_name, element_name); + return -1; + } + ftdm_conf_node_add_param(n_element, "name", element_name); + + for (param = switch_xml_child(element, "param"); param; param = param->next) { + var = (char *) switch_xml_attr_soft(param, "name"); + val = (char *) switch_xml_attr_soft(param, "value"); + ftdm_conf_node_add_param(n_element, var, val); + } + + if (sub_list_name && sub_list_element_name) { + if (add_config_list_nodes(element, n_element, sub_list_name, sub_list_element_name, NULL, NULL)) { + return -1; + } + } + } + + return 0; +} + static ftdm_conf_node_t *get_ss7_config_node(switch_xml_t cfg, const char *confname) { - return NULL; + switch_xml_t signode, ss7configs, isup; + ftdm_conf_node_t *rootnode; + + /* try to find the conf in the hash first */ + rootnode = switch_core_hash_find(globals.ss7_configs, confname); + if (rootnode) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "ss7 config %s was found in the hash already\n", confname); + return rootnode; + } + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "not found %s config in hash, searching in xml ...\n", confname); + + signode = switch_xml_child(cfg, "signaling_configs"); + if (!signode) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'signaling_configs' XML config section\n"); + return NULL; + } + + ss7configs = switch_xml_child(signode, "sngss7_configs"); + if (!ss7configs) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found 'sngss7_configs' XML config section\n"); + return NULL; + } + + /* search the isup config */ + for (isup = switch_xml_child(ss7configs, "sng_isup"); isup; isup = isup->next) { + char *name = (char *) switch_xml_attr(isup, "name"); + if (!name) { + continue; + } + if (!strcasecmp(name, confname)) { + break; + } + } + + if (!isup) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "not found '%s' sng_isup XML config section\n", confname); + return NULL; + } + + /* found our XML chunk, create the root node */ + if ((FTDM_SUCCESS != ftdm_conf_node_create("sng_isup", &rootnode, NULL))) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to create root node for sng_isup config %s\n", confname); + return NULL; + } + + /* add mtp linksets */ + if (add_config_list_nodes(isup, rootnode, "mtp_linksets", "mtp_linkset", "mtp_links", "mtp_link")) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_linksets for sng_isup config %s\n", confname); + ftdm_conf_node_destroy(rootnode); + return NULL; + } + + /* add mtp routes */ + if (add_config_list_nodes(isup, rootnode, "mtp_routes", "mtp_route", NULL, NULL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process mtp_routes for sng_isup config %s\n", confname); + ftdm_conf_node_destroy(rootnode); + return NULL; + } + + /* add isup interfaces */ + if (add_config_list_nodes(isup, rootnode, "isup_interfaces", "isup_interface", NULL, NULL)) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "failed to process isup_interfaces for sng_isup config %s\n", confname); + ftdm_conf_node_destroy(rootnode); + return NULL; + } + + switch_core_hash_insert(globals.ss7_configs, confname, rootnode); + + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_INFO, "Added SS7 node configuration %s\n", confname); + return rootnode; } static switch_status_t load_config(void) @@ -2079,8 +2203,12 @@ static switch_status_t load_config(void) char *configname = (char *) switch_xml_attr(myspan, "config"); ftdm_span_t *span = NULL; uint32_t span_id = 0; - if (!name || !configname || !id) { - switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required param 'id' or 'name' or 'config', skipping ...\n"); + if (!name && !id) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute 'id' or 'name', skipping ...\n"); + continue; + } + if (!configname) { + switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "ss7 span missing required attribute, skipping ...\n"); continue; } if (name) { @@ -2106,13 +2234,19 @@ static switch_status_t load_config(void) } ss7confnode = get_ss7_config_node(cfg, configname); - - if (ftdm_configure_span("ss7", span, on_ss7_signal, - "confnode", ss7confnode, - TAG_END) != FTDM_SUCCESS) { - ftdm_log(FTDM_LOG_ERROR, "Error configuring ss7 FreeTDM span %d\n", span_id); + if (!ss7confnode) { + ftdm_log(FTDM_LOG_ERROR, "Error finding ss7config '%s' for FreeTDM span id: %s\n", configname, switch_str_nil(id)); continue; } + + if (0) { + if (ftdm_configure_span("ss7", span, on_ss7_signal, + "confnode", ss7confnode, + TAG_END) != FTDM_SUCCESS) { + ftdm_log(FTDM_LOG_ERROR, "Error configuring ss7 FreeTDM span %d\n", span_id); + continue; + } + } ftdm_log(FTDM_LOG_DEBUG, "Configured ss7 FreeTDM span %d with config node %s\n", span_id, configname); } } diff --git a/libs/freetdm/src/ftdm_config.c b/libs/freetdm/src/ftdm_config.c index a7a8f041b1..5f9895d04b 100644 --- a/libs/freetdm/src/ftdm_config.c +++ b/libs/freetdm/src/ftdm_config.c @@ -29,6 +29,10 @@ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Contributors: + * + * Moises Silva */ #include "freetdm.h" @@ -239,6 +243,82 @@ FT_DECLARE (int) ftdm_config_get_cas_bits(char *strvalue, unsigned char *outbits return 0; } +#define PARAMETERS_CHUNK_SIZE 20 +FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent) +{ + ftdm_conf_node_t *newnode; + ftdm_conf_node_t *sibling = NULL; + + ftdm_assert_return(name != NULL, FTDM_FAIL, "null node name"); + + newnode = ftdm_calloc(1, sizeof(**node)); + if (!newnode) { + return FTDM_MEMERR; + } + + strncpy(newnode->name, name, sizeof(newnode->name)-1); + newnode->name[sizeof(newnode->name)-1] = 0; + + newnode->parameters = ftdm_calloc(PARAMETERS_CHUNK_SIZE, sizeof(*newnode->parameters)); + if (!newnode->parameters) { + ftdm_safe_free(newnode); + return FTDM_MEMERR; + } + newnode->t_parameters = PARAMETERS_CHUNK_SIZE; + + if (parent) { + /* store who my parent is */ + newnode->parent = parent; + /* save any siblings */ + sibling = parent->child; + /* as a newborn I am first */ + parent->child = newnode; + if (sibling) { + /* store a pointer to my next sibling */ + newnode->next = sibling; + } + } + + *node = newnode; + + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val) +{ + void *newparameters; + + ftdm_assert_return(param != NULL, FTDM_FAIL, "param is null"); + ftdm_assert_return(val != NULL, FTDM_FAIL, "val is null"); + + if (node->n_parameters == node->t_parameters) { + newparameters = ftdm_realloc(node->parameters, (node->t_parameters + PARAMETERS_CHUNK_SIZE) * sizeof(*node->parameters)); + if (!newparameters) { + return FTDM_MEMERR; + } + node->parameters = newparameters; + node->t_parameters = node->n_parameters + PARAMETERS_CHUNK_SIZE; + } + node->parameters[node->n_parameters].var = param; + node->parameters[node->n_parameters].val = val; + node->n_parameters++; + return FTDM_SUCCESS; +} + +FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node) +{ + ftdm_conf_node_t *curr = NULL; + ftdm_conf_node_t *child = node->child; + while (child) { + curr = child; + child = curr->next; + ftdm_conf_node_destroy(curr); + } + ftdm_free(node->parameters); + ftdm_free(node); + return FTDM_SUCCESS; +} + /* For Emacs: * Local Variables: * mode:c diff --git a/libs/freetdm/src/include/freetdm.h b/libs/freetdm/src/include/freetdm.h index 263e79d40f..a924e3587a 100644 --- a/libs/freetdm/src/include/freetdm.h +++ b/libs/freetdm/src/include/freetdm.h @@ -827,6 +827,9 @@ FT_DECLARE(char *) ftdm_api_execute(const char *type, const char *cmd); FT_DECLARE(int) ftdm_vasprintf(char **ret, const char *fmt, va_list ap); FT_DECLARE(ftdm_status_t) ftdm_channel_set_caller_data(ftdm_channel_t *ftdmchan, ftdm_caller_data_t *caller_data); FT_DECLARE(void) ftdm_cpu_monitor_disable(void); +FT_DECLARE(ftdm_status_t) ftdm_conf_node_create(const char *name, ftdm_conf_node_t **node, ftdm_conf_node_t *parent); +FT_DECLARE(ftdm_status_t) ftdm_conf_node_add_param(ftdm_conf_node_t *node, const char *param, const char *val); +FT_DECLARE(ftdm_status_t) ftdm_conf_node_destroy(ftdm_conf_node_t *node); FIO_CODEC_FUNCTION(fio_slin2ulaw); FIO_CODEC_FUNCTION(fio_ulaw2slin); diff --git a/libs/freetdm/src/include/ftdm_types.h b/libs/freetdm/src/include/ftdm_types.h index c172ccb4ca..bf7720efd1 100644 --- a/libs/freetdm/src/include/ftdm_types.h +++ b/libs/freetdm/src/include/ftdm_types.h @@ -572,12 +572,28 @@ typedef ftdm_status_t (*fio_api_t) FIO_API_ARGS ; #include "ftdm_dso.h" +#define FTDM_NODE_NAME_SIZE 50 typedef struct ftdm_conf_node_s { - char name[255]; - ftdm_conf_parameter_t attr[10]; - ftdm_conf_parameter_t settings[100]; - struct ftdm_conf_node_t *childs; - struct ftdm_config_node_s *next; + /* node name */ + char name[FTDM_NODE_NAME_SIZE]; + + /* total slots for parameters */ + unsigned int t_parameters; + + /* current number of parameters */ + unsigned int n_parameters; + + /* array of parameters */ + ftdm_conf_parameter_t *parameters; + + /* first node child */ + struct ftdm_conf_node_s *child; + + /* next node sibling */ + struct ftdm_conf_node_s *next; + + /* my parent if any */ + struct ftdm_conf_node_s *parent; } ftdm_conf_node_t; typedef struct {