diff options
Diffstat (limited to 'channels/chan_misdn_config.c')
-rw-r--r-- | channels/chan_misdn_config.c | 1358 |
1 files changed, 520 insertions, 838 deletions
diff --git a/channels/chan_misdn_config.c b/channels/chan_misdn_config.c index 317515cc5..05f3eabc9 100644 --- a/channels/chan_misdn_config.c +++ b/channels/chan_misdn_config.c @@ -26,10 +26,10 @@ * \ingroup channel_drivers */ - #include <stdlib.h> #include <stdio.h> #include <string.h> +#include <errno.h> #include "chan_misdn_config.h" @@ -39,392 +39,316 @@ #include <asterisk/lock.h> #include <asterisk/pbx.h> #include <asterisk/strings.h> - - #include <asterisk/utils.h> + #define AST_LOAD_CFG ast_config_load #define AST_DESTROY_CFG ast_config_destroy -#define DEF_ECHOCANCEL 128 -#define DEF_ECHOTRAINING 1 +#define NO_DEFAULT "<>" +#define NONE 0 + +#define GEN_CFG 1 +#define PORT_CFG 2 +#define NUM_GEN_ELEMENTS (sizeof(gen_spec) / sizeof(struct misdn_cfg_spec)) +#define NUM_PORT_ELEMENTS (sizeof(port_spec) / sizeof(struct misdn_cfg_spec)) + +enum misdn_cfg_type { + MISDN_CTYPE_STR, + MISDN_CTYPE_INT, + MISDN_CTYPE_BOOL, + MISDN_CTYPE_BOOLINT, + MISDN_CTYPE_MSNLIST, + MISDN_CTYPE_ASTGROUP +}; struct msn_list { char *msn; struct msn_list *next; }; -struct port_config { - char *name; - int *rxgain; - int *txgain; - int *te_choose_channel; - char *context; - char *language; - char *musicclass; - char *callerid; - char *method; - int *dialplan; - int *localdialplan; - char *nationalprefix; - char *internationalprefix; - int *pres; - int *always_immediate; - int *immediate; - int *senddtmf; - int *hold_allowed; - int *early_bconnect; - int *use_callingpres; - int *echocancel; - int *echocancelwhenbridged; - int *echotraining; - int *jitterbuffer; - int *jitterbuffer_upper_threshold; - struct msn_list *msn_list; - ast_group_t *callgroup; /* Call group */ - ast_group_t *pickupgroup; /* Pickup group */ +union misdn_cfg_pt { + char *str; + int *num; + struct msn_list *ml; + ast_group_t *grp; + void *any; +}; + +struct misdn_cfg_spec { + char name[BUFFERSIZE]; + enum misdn_cfg_elements elem; + enum misdn_cfg_type type; + char def[BUFFERSIZE]; + int boolint_def; +}; + +static const struct misdn_cfg_spec port_spec[] = { + { "name", MISDN_CFG_GROUPNAME, MISDN_CTYPE_STR, "default", NONE }, + { "rxgain", MISDN_CFG_RXGAIN, MISDN_CTYPE_INT, "0", NONE }, + { "txgain", MISDN_CFG_TXGAIN, MISDN_CTYPE_INT, "0", NONE }, + { "te_choose_channel", MISDN_CFG_TE_CHOOSE_CHANNEL, MISDN_CTYPE_BOOL, "no", NONE }, + { "context", MISDN_CFG_CONTEXT, MISDN_CTYPE_STR, "default", NONE }, + { "language", MISDN_CFG_LANGUAGE, MISDN_CTYPE_STR, "en", NONE }, + { "musicclass", MISDN_CFG_MUSICCLASS, MISDN_CTYPE_STR, "default", NONE }, + { "callerid", MISDN_CFG_CALLERID, MISDN_CTYPE_STR, "", NONE }, + { "method", MISDN_CFG_METHOD, MISDN_CTYPE_STR, "standard", NONE }, + { "dialplan", MISDN_CFG_DIALPLAN, MISDN_CTYPE_INT, "0", NONE }, + { "localdialplan", MISDN_CFG_LOCALDIALPLAN, MISDN_CTYPE_INT, "0", NONE }, + { "nationalprefix", MISDN_CFG_NATPREFIX, MISDN_CTYPE_STR, "0", NONE }, + { "internationalprefix", MISDN_CFG_INTERNATPREFIX, MISDN_CTYPE_STR, "00", NONE }, + { "presentation", MISDN_CFG_PRES, MISDN_CTYPE_INT, "-1", NONE }, + { "screen", MISDN_CFG_SCREEN, MISDN_CTYPE_INT, "-1", NONE }, + { "always_immediate", MISDN_CFG_ALWAYS_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE }, + { "immediate", MISDN_CFG_IMMEDIATE, MISDN_CTYPE_BOOL, "no", NONE }, + { "senddtmf", MISDN_CFG_SENDDTMF, MISDN_CTYPE_BOOL, "no", NONE }, + { "hold_allowed", MISDN_CFG_HOLD_ALLOWED, MISDN_CTYPE_BOOL, "no", NONE }, + { "early_bconnect", MISDN_CFG_EARLY_BCONNECT, MISDN_CTYPE_BOOL, "yes", NONE }, + { "echocancel", MISDN_CFG_ECHOCANCEL, MISDN_CTYPE_BOOLINT, "0", 128 }, + { "echocancelwhenbridged", MISDN_CFG_ECHOCANCELWHENBRIDGED, MISDN_CTYPE_BOOL, "no", NONE }, + { "echotraining", MISDN_CFG_ECHOTRAINING, MISDN_CTYPE_BOOLINT, "1", 1 }, + { "need_more_infos", MISDN_CFG_NEED_MORE_INFOS, MISDN_CTYPE_BOOL, "0", NONE }, + { "jitterbuffer", MISDN_CFG_JITTERBUFFER, MISDN_CTYPE_INT, "0", NONE }, + { "jitterbuffer_upper_threshold", MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD, MISDN_CTYPE_INT, "0", NONE }, + { "callgroup", MISDN_CFG_CALLGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE }, + { "pickupgroup", MISDN_CFG_PICKUPGROUP, MISDN_CTYPE_ASTGROUP, NO_DEFAULT, NONE }, + { "msns", MISDN_CFG_MSNS, MISDN_CTYPE_MSNLIST, NO_DEFAULT, NONE } }; -struct general_config { - int *debug; - char *tracefile; - int *trace_calls; - char *trace_dir; - int *bridging; - int *stop_tone_after_first_digit; - int *append_digits2exten; - int *l1_info_ok; - int *clear_l3; - int *dynamic_crypt; - char *crypt_prefix; - char *crypt_keys; +static const struct misdn_cfg_spec gen_spec[] = { + { "debug", MISDN_GEN_DEBUG, MISDN_CTYPE_INT, "0", NONE }, + { "misdn_init", MISDN_GEN_MISDN_INIT, MISDN_CTYPE_STR, "/etc/misdn-init.conf", NONE }, + { "tracefile", MISDN_GEN_TRACEFILE, MISDN_CTYPE_STR, "/var/log/misdn.trace", NONE }, + { "bridging", MISDN_GEN_BRIDGING, MISDN_CTYPE_BOOL, "yes", NONE }, + { "stop_tone_after_first_digit", MISDN_GEN_STOP_TONE, MISDN_CTYPE_BOOL, "yes", NONE }, + { "append_digits2exten", MISDN_GEN_APPEND_DIGITS2EXTEN, MISDN_CTYPE_BOOL, "yes", NONE }, + { "dynamic_crypt", MISDN_GEN_DYNAMIC_CRYPT, MISDN_CTYPE_BOOL, "no", NONE }, + { "crypt_prefix", MISDN_GEN_CRYPT_PREFIX, MISDN_CTYPE_STR, NO_DEFAULT, NONE }, + { "crypt_keys", MISDN_GEN_CRYPT_KEYS, MISDN_CTYPE_STR, NO_DEFAULT, NONE } }; /* array of port configs, default is at position 0. */ -static struct port_config **port_cfg; +static union misdn_cfg_pt **port_cfg; /* max number of available ports, is set on init */ static int max_ports; /* general config */ -static struct general_config *general_cfg; +static union misdn_cfg_pt *general_cfg; /* storing the ptp flag separated to save memory */ static int *ptp; +/* maps enum config elements to array positions */ +static int *map; static ast_mutex_t config_mutex; +#define CLI_ERROR(name, value, section) ({ \ + ast_log(LOG_WARNING, "misdn.conf: \"%s=%s\" (section: %s) invalid or out of range. " \ + "Please edit your misdn.conf and then do a \"misdn reload\".\n", name, value, section); \ +}) + +static void _enum_array_map (void) +{ + int i, j; + + for (i = MISDN_CFG_FIRST + 1; i < MISDN_CFG_LAST; ++i) { + if (i == MISDN_CFG_PTP) + continue; + for (j = 0; j < NUM_PORT_ELEMENTS; ++j) { + if (port_spec[j].elem == i) { + map[i] = j; + break; + } + } + } + for (i = MISDN_GEN_FIRST + 1; i < MISDN_GEN_LAST; ++i) { + for (j = 0; j < NUM_GEN_ELEMENTS; ++j) { + if (gen_spec[j].elem == i) { + map[i] = j; + break; + } + } + } +} + +static int get_cfg_position (char *name, int type) +{ + int i; -static inline void misdn_cfg_lock (void) { + switch (type) { + case PORT_CFG: + for (i = 0; i < NUM_PORT_ELEMENTS; ++i) { + if (!strcasecmp(name, port_spec[i].name)) + return i; + } + break; + case GEN_CFG: + for (i = 0; i < NUM_GEN_ELEMENTS; ++i) { + if (!strcasecmp(name, gen_spec[i].name)) + return i; + } + } + + return -1; +} + +static inline void misdn_cfg_lock (void) +{ ast_mutex_lock(&config_mutex); } -static inline void misdn_cfg_unlock (void) { +static inline void misdn_cfg_unlock (void) +{ ast_mutex_unlock(&config_mutex); } -static void free_msn_list (struct msn_list* iter) { +static void _free_msn_list (struct msn_list* iter) +{ if (iter->next) - free_msn_list(iter->next); + _free_msn_list(iter->next); if (iter->msn) free(iter->msn); free(iter); } -static void free_port_cfg (void) { - - struct port_config **free_list = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *)); - +static void _free_port_cfg (void) +{ int i, j; - - for (i = 0; i < max_ports; i++) { - if (port_cfg[i]) { - for (j = 0; j < max_ports && free_list[j]; j++) { - if (free_list[j] && free_list[j] == port_cfg[i]) - continue; /* already in list */ - free_list[j] = port_cfg[i]; + int gn = map[MISDN_CFG_GROUPNAME]; + union misdn_cfg_pt* free_list[max_ports + 1]; + + memset(free_list, 0, sizeof(free_list)); + free_list[0] = port_cfg[0]; + for (i = 1; i <= max_ports; ++i) { + if (port_cfg[i][gn].str) { + /* we always have a groupname in the non-default case, so this is fine */ + for (j = 1; j <= max_ports; ++j) { + if (free_list[j] && free_list[j][gn].str == port_cfg[i][gn].str) + break; + else if (!free_list[j]) { + free_list[j] = port_cfg[i]; + break; + } } } } - -#define FREE_ELEM(elem) ({ \ - if (free_list[i]->elem) \ - free(free_list[i]->elem); \ - }) - - for (i = 0; i < max_ports; i++) { - if (free_list[i]) { - FREE_ELEM(name); - FREE_ELEM(rxgain); - FREE_ELEM(txgain); - FREE_ELEM(te_choose_channel); - FREE_ELEM(context); - FREE_ELEM(language); - FREE_ELEM(musicclass); - FREE_ELEM(callerid); - FREE_ELEM(method); - FREE_ELEM(dialplan); - FREE_ELEM(localdialplan); - FREE_ELEM(nationalprefix); - FREE_ELEM(internationalprefix); - FREE_ELEM(pres); - FREE_ELEM(always_immediate); - FREE_ELEM(senddtmf); - FREE_ELEM(immediate); - FREE_ELEM(hold_allowed); - FREE_ELEM(early_bconnect); - FREE_ELEM(use_callingpres); - FREE_ELEM(echocancel); - FREE_ELEM(echocancelwhenbridged); - FREE_ELEM(echotraining); - FREE_ELEM(jitterbuffer); - FREE_ELEM(jitterbuffer_upper_threshold); - if (free_list[i]->msn_list) - free_msn_list(free_list[i]->msn_list); - FREE_ELEM(callgroup); - FREE_ELEM(pickupgroup); - free(free_list[i]); + for (j = 0; free_list[j]; ++j) { + for (i = 0; i < NUM_PORT_ELEMENTS; ++i) { + if (free_list[j][i].any) { + if (port_spec[i].type == MISDN_CTYPE_MSNLIST) + _free_msn_list(free_list[j][i].ml); + else + free(free_list[j][i].any); + } } } - free(free_list); } -static void free_general_cfg (void) { +static void _free_general_cfg (void) +{ + int i; -#define FREE_GEN_ELEM(elem) ({ \ - if (general_cfg->elem) \ - free(general_cfg->elem); \ - }) - - FREE_GEN_ELEM(debug); - FREE_GEN_ELEM(tracefile); - FREE_GEN_ELEM(trace_calls); - FREE_GEN_ELEM(trace_dir); - FREE_GEN_ELEM(bridging); - FREE_GEN_ELEM(stop_tone_after_first_digit); - FREE_GEN_ELEM(append_digits2exten); - FREE_GEN_ELEM(l1_info_ok); - FREE_GEN_ELEM(clear_l3); - FREE_GEN_ELEM(dynamic_crypt); - FREE_GEN_ELEM(crypt_prefix); - FREE_GEN_ELEM(crypt_keys); + for (i = 0; i < NUM_GEN_ELEMENTS; i++) + if (general_cfg[i].any) + free(general_cfg[i].any); } -#define GET_PORTCFG_STRCPY(item) ({ \ - char *temp; \ - if (port_cfg[port] && port_cfg[port]->item) \ - temp = port_cfg[port]->item; \ - else \ - temp = port_cfg[0]->item; \ - if (!temp || !memccpy((void *)buf, (void *)temp, '\0', bufsize)) \ - memset(buf, 0, 1); \ - }) - -#define GET_GENCFG_STRCPY(item) ({ \ - if (general_cfg && general_cfg->item) { \ - if (!memccpy((void *)buf, (void *)general_cfg->item, '\0', bufsize)) \ - memset(buf, 0, 1); \ - } else \ - memset(buf, 0, 1); \ - }) - -#define GET_PORTCFG_MEMCPY(item) ({ \ - typeof(port_cfg[0]->item) temp; \ - if (port_cfg[port] && port_cfg[port]->item) \ - temp = port_cfg[port]->item; \ - else \ - temp = port_cfg[0]->item; \ - if (temp) { \ - int l = sizeof(*temp); \ - if (l > bufsize) \ - memset(buf, 0, bufsize); \ - else \ - memcpy(buf, temp, l); \ - } else \ - memset(buf, 0, bufsize); \ - }) - -#define GET_GENCFG_MEMCPY(item) ({ \ - if (general_cfg && general_cfg->item) { \ - typeof(general_cfg->item) temp = general_cfg->item; \ - int l = sizeof(*temp); \ - if (l > bufsize) \ - memset(buf, 0, bufsize); \ - else \ - memcpy(buf, temp, l); \ - } else \ - memset(buf, 0, bufsize); \ - }) - -void misdn_cfg_get(int port, enum misdn_cfg_elements elem, void *buf, int bufsize) { - - if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) { +void misdn_cfg_get (int port, enum misdn_cfg_elements elem, void *buf, int bufsize) +{ + int place; + + if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) { memset(buf, 0, bufsize); ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Port number %d is not valid.\n", port); return; } misdn_cfg_lock(); - - switch (elem) { - - /* port config elements */ - - case MISDN_CFG_PTP: if (sizeof(ptp[port]) <= bufsize) - memcpy(buf, &ptp[port], sizeof(ptp[port])); - else - buf = 0; /* error, should not happen */ - break; - case MISDN_CFG_GROUPNAME: GET_PORTCFG_STRCPY(name); - break; - case MISDN_CFG_RXGAIN: GET_PORTCFG_MEMCPY(rxgain); - break; - case MISDN_CFG_TXGAIN: GET_PORTCFG_MEMCPY(txgain); - break; - case MISDN_CFG_JITTERBUFFER: GET_PORTCFG_MEMCPY(jitterbuffer); - break; - case MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD: GET_PORTCFG_MEMCPY(jitterbuffer_upper_threshold); - break; -case MISDN_CFG_TE_CHOOSE_CHANNEL: - GET_PORTCFG_MEMCPY(te_choose_channel); - break; - case MISDN_CFG_CONTEXT: GET_PORTCFG_STRCPY(context); - break; - case MISDN_CFG_LANGUAGE: GET_PORTCFG_STRCPY(language); - break; - case MISDN_CFG_MUSICCLASS: GET_PORTCFG_STRCPY(musicclass); - break; - case MISDN_CFG_CALLERID: GET_PORTCFG_STRCPY(callerid); - break; - case MISDN_CFG_METHOD: GET_PORTCFG_STRCPY(method); - break; - case MISDN_CFG_DIALPLAN: GET_PORTCFG_MEMCPY(dialplan); - break; - case MISDN_CFG_LOCALDIALPLAN: GET_PORTCFG_MEMCPY(localdialplan); - break; - case MISDN_CFG_NATPREFIX: GET_PORTCFG_STRCPY(nationalprefix); - break; - case MISDN_CFG_INTERNATPREFIX: - GET_PORTCFG_STRCPY(internationalprefix); - break; - case MISDN_CFG_PRES: GET_PORTCFG_MEMCPY(pres); - break; - case MISDN_CFG_ALWAYS_IMMEDIATE: - GET_PORTCFG_MEMCPY(always_immediate); - break; - case MISDN_CFG_SENDDTMF: - GET_PORTCFG_MEMCPY(senddtmf); - break; - case MISDN_CFG_IMMEDIATE: GET_PORTCFG_MEMCPY(immediate); - break; - case MISDN_CFG_HOLD_ALLOWED: - GET_PORTCFG_MEMCPY(hold_allowed); - break; - case MISDN_CFG_EARLY_BCONNECT: - GET_PORTCFG_MEMCPY(early_bconnect); - break; - case MISDN_CFG_USE_CALLINGPRES: - GET_PORTCFG_MEMCPY(use_callingpres); - break; - case MISDN_CFG_ECHOCANCEL: - GET_PORTCFG_MEMCPY(echocancel ); - break; - case MISDN_CFG_ECHOCANCELWHENBRIDGED: - GET_PORTCFG_MEMCPY(echocancelwhenbridged); - break; - case MISDN_CFG_ECHOTRAINING: - GET_PORTCFG_MEMCPY(echotraining); - break; - case MISDN_CFG_CALLGROUP: GET_PORTCFG_MEMCPY(callgroup); - break; - case MISDN_CFG_PICKUPGROUP: GET_PORTCFG_MEMCPY(pickupgroup); - break; - - /* general config elements */ - - case MISDN_GEN_DEBUG: GET_GENCFG_MEMCPY(debug); - break; - case MISDN_GEN_TRACEFILE: GET_GENCFG_STRCPY(tracefile); - break; - case MISDN_GEN_TRACE_CALLS: GET_GENCFG_MEMCPY(trace_calls); - break; - case MISDN_GEN_TRACE_DIR: GET_GENCFG_STRCPY(trace_dir); - break; - case MISDN_GEN_BRIDGING: GET_GENCFG_MEMCPY(bridging); - break; - case MISDN_GEN_STOP_TONE: GET_GENCFG_MEMCPY(stop_tone_after_first_digit); - break; - case MISDN_GEN_APPEND_DIGITS2EXTEN: - GET_GENCFG_MEMCPY(append_digits2exten); - break; - case MISDN_GEN_L1_INFO_OK: GET_GENCFG_MEMCPY(l1_info_ok); - break; - case MISDN_GEN_CLEAR_L3: GET_GENCFG_MEMCPY(clear_l3); - break; - case MISDN_GEN_DYNAMIC_CRYPT: GET_GENCFG_MEMCPY(dynamic_crypt); - break; - case MISDN_GEN_CRYPT_PREFIX: GET_GENCFG_STRCPY(crypt_prefix); - break; - case MISDN_GEN_CRYPT_KEYS: GET_GENCFG_STRCPY(crypt_keys); - break; - default: memset(buf, 0, bufsize); + if (elem == MISDN_CFG_PTP) { + if (!memcpy(buf, &ptp[port], (bufsize > ptp[port]) ? sizeof(ptp[port]) : bufsize)) + memset(buf, 0, bufsize); + } else { + if ((place = map[elem]) < 0) { + memset (buf, 0, bufsize); + ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get! Invalid element (%d) requested.\n", elem); + } else { + if (elem < MISDN_CFG_LAST) { + switch (port_spec[place].type) { + case MISDN_CTYPE_STR: + if (port_cfg[port][place].str) { + if (!memccpy(buf, port_cfg[port][place].str, 0, bufsize)) + memset(buf, 0, 1); + } else if (port_cfg[0][place].str) { + if (!memccpy(buf, port_cfg[0][place].str, 0, bufsize)) + memset(buf, 0, 1); + } + break; + default: + if (port_cfg[port][place].any) + memcpy(buf, port_cfg[port][place].any, bufsize); + else if (port_cfg[0][place].any) + memcpy(buf, port_cfg[0][place].any, bufsize); + else + memset(buf, 0, bufsize); + } + } else { + switch (gen_spec[place].type) { + case MISDN_CTYPE_STR: + if (!general_cfg[place].str || !memccpy(buf, general_cfg[place].str, 0, bufsize)) + memset(buf, 0, 1); + break; + default: + if (general_cfg[place].any) + memcpy(buf, general_cfg[place].any, bufsize); + else + memset(buf, 0, bufsize); + } + } + } } - misdn_cfg_unlock(); } -int misdn_cfg_is_msn_valid (int port, char* msn) { - +int misdn_cfg_is_msn_valid (int port, char* msn) +{ + int re = 0; + struct msn_list *iter; + if (!misdn_cfg_is_port_valid(port)) { ast_log(LOG_WARNING, "Invalid call to misdn_cfg_is_msn_valid! Port number %d is not valid.\n", port); return 0; } - - struct msn_list *iter; - + misdn_cfg_lock(); - - if (port_cfg[port]->msn_list) - iter = port_cfg[port]->msn_list; + if (port_cfg[port][MISDN_CFG_MSNS-1].ml) + iter = port_cfg[port][MISDN_CFG_MSNS-1].ml; else - iter = port_cfg[0]->msn_list; + iter = port_cfg[0][MISDN_CFG_MSNS-1].ml; for (; iter; iter = iter->next) if (*(iter->msn) == '*' || ast_extension_match(iter->msn, msn)) { - misdn_cfg_unlock(); - return 1; + re = 1; + break; } - - misdn_cfg_unlock(); - - return 0; -} - -int misdn_cfg_is_port_valid (int port) { - - misdn_cfg_lock(); - - if (port < 1 || port > max_ports) { - misdn_cfg_unlock(); - return 0; - } - - int valid = (port_cfg[port] != NULL); - misdn_cfg_unlock(); - return valid; + return re; } -int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth) { +int misdn_cfg_is_port_valid (int port) +{ + return (port >= 1 && port <= max_ports); +} +int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth) +{ int i, re = 0; char *method = NULL; misdn_cfg_lock(); - - for (i = 0; i < max_ports; i++) { - if (port_cfg[i]) { - if (!strcasecmp(port_cfg[i]->name, group)) - method = port_cfg[i]->method ? port_cfg[i]->method : port_cfg[0]->method; + for (i = 1; i <= max_ports; i++) { + if (port_cfg[i] && port_cfg[i][map[MISDN_CFG_GROUPNAME]].str) { + if (!strcasecmp(port_cfg[i][map[MISDN_CFG_GROUPNAME]].str, group)) + method = (port_cfg[i][map[MISDN_CFG_METHOD]].str ? + port_cfg[i][map[MISDN_CFG_METHOD]].str : port_cfg[0][map[MISDN_CFG_METHOD]].str); } } - if (method) { switch (meth) { case METHOD_STANDARD: re = !strcasecmp(method, "standard"); @@ -433,22 +357,22 @@ int misdn_cfg_is_group_method (char *group, enum misdn_cfg_method meth) { break; } } - misdn_cfg_unlock(); return re; } -void misdn_cfg_get_ports_string (char *ports) { - *ports = 0; +void misdn_cfg_get_ports_string (char *ports) +{ char tmp[16]; - int l; - - misdn_cfg_lock(); + int l, i; + int gn = map[MISDN_CFG_GROUPNAME]; + + *ports = 0; - int i = 1; - for (; i <= max_ports; i++) { - if (port_cfg[i]) { + misdn_cfg_lock(); + for (i = 1; i <= max_ports; i++) { + if (port_cfg[i][gn].str) { if (ptp[i]) sprintf(tmp, "%dptp,", i); else @@ -456,583 +380,331 @@ void misdn_cfg_get_ports_string (char *ports) { strcat(ports, tmp); } } - misdn_cfg_unlock(); if ((l = strlen(ports))) ports[l-1] = 0; } -#define GET_CFG_STRING(typestr, type) ({ \ - if (port_cfg[port] && port_cfg[port]->type) \ - snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[port]->type); \ - else \ - snprintf(buf, bufsize, "%s " #typestr ": %s", begin, port_cfg[0]->type); \ - }) \ - -#define GET_GEN_STRING(typestr, type) ({ \ - snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? general_cfg->type : "not set"); \ - }) \ - -#define GET_CFG_INT(typestr, type) ({ \ - if (port_cfg[port] && port_cfg[port]->type) \ - snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[port]->type); \ - else \ - snprintf(buf, bufsize, "%s " #typestr ": %d", begin, *port_cfg[0]->type); \ - }) \ - -#define GET_GEN_INT(typestr, type) ({ \ - snprintf(buf, bufsize, "%s " #typestr ": %d", begin, general_cfg->type ? *general_cfg->type : 0); \ - }) \ - -#define GET_CFG_BOOL(typestr, type, yes, no) ({ \ - int bool; \ - if (port_cfg[port] && port_cfg[port]->type) \ - bool = *port_cfg[port]->type; \ - else \ - bool = *port_cfg[0]->type; \ - snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \ - }) \ - -#define GET_CFG_HYBRID(typestr, type, yes, no) ({ \ - int bool; \ - if (port_cfg[port] && port_cfg[port]->type) \ - bool = *port_cfg[port]->type; \ - else \ - bool = *port_cfg[0]->type; \ - if (bool == 1 || bool == 0) \ - snprintf(buf, bufsize, "%s " #typestr ": %s", begin, bool ? #yes : #no); \ - else \ - snprintf(buf, bufsize, "%s " #typestr ": %d", begin, bool); \ - }) \ - -#define GET_GEN_BOOL(typestr, type, yes, no) ({ \ - snprintf(buf, bufsize, "%s " #typestr ": %s", begin, general_cfg->type ? (*general_cfg->type ? #yes : #no) : "not set"); \ - }) \ - -#define GET_CFG_AST_GROUP_T(typestr, type) ({ \ - ast_group_t *tmp; \ - if (port_cfg[port] && port_cfg[port]->type) \ - tmp = port_cfg[port]->type; \ - else \ - tmp = port_cfg[0]->type; \ - if (tmp) { \ - char tmpbuf[256]; \ - snprintf(buf, bufsize, "%s " #typestr ": %s", begin, ast_print_group(tmpbuf, sizeof(tmpbuf), *tmp)); \ - } else \ - snprintf(buf, bufsize, "%s " #typestr ": %s", begin, "none"); \ - }) \ - -void misdn_cfg_get_config_string(int port, enum misdn_cfg_elements elem, char* buf, int bufsize) { - - if (!(elem > MISDN_GEN_FIRST) && !misdn_cfg_is_port_valid(port)) { +void misdn_cfg_get_config_string (int port, enum misdn_cfg_elements elem, char* buf, int bufsize) +{ + int place; + char tempbuf[BUFFERSIZE] = ""; + struct msn_list *iter; + + if ((elem < MISDN_CFG_LAST) && !misdn_cfg_is_port_valid(port)) { *buf = 0; ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Port number %d is not valid.\n", port); return; } - - char begin[] = " -> "; - + + place = map[elem]; + misdn_cfg_lock(); - - switch (elem) { - - case MISDN_CFG_PTP: snprintf(buf, bufsize, "%s PTP: %s", begin, ptp[port] ? "yes" : "no"); - break; - case MISDN_CFG_GROUPNAME: GET_CFG_STRING(GROUPNAME, name); - break; - case MISDN_CFG_RXGAIN: GET_CFG_INT(RXGAIN, rxgain); + if (elem == MISDN_CFG_PTP) { + snprintf(buf, bufsize, " -> ptp: %s", ptp[port] ? "yes" : "no"); + } + else if (elem > MISDN_CFG_FIRST && elem < MISDN_CFG_LAST) { + switch (port_spec[place].type) { + case MISDN_CTYPE_INT: + case MISDN_CTYPE_BOOLINT: + if (port_cfg[port][place].num) + snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[port][place].num); + else if (port_cfg[0][place].num) + snprintf(buf, bufsize, " -> %s: %d", port_spec[place].name, *port_cfg[0][place].num); + else + snprintf(buf, bufsize, " -> %s:", port_spec[place].name); break; - case MISDN_CFG_TXGAIN: GET_CFG_INT(TXGAIN, txgain); - break; - case MISDN_CFG_JITTERBUFFER: GET_CFG_INT(JITTERBUFFER, jitterbuffer); - break; - case MISDN_CFG_JITTERBUFFER_UPPER_THRESHOLD: GET_CFG_INT(JITTERBUFFER_UPPER_THRESHOLD, jitterbuffer_upper_threshold); - break; - case MISDN_CFG_TE_CHOOSE_CHANNEL: - GET_CFG_BOOL(TE_CHOOSE_CHANNEL, te_choose_channel, yes, no); - break; - case MISDN_CFG_CONTEXT: GET_CFG_STRING(CONTEXT, context); - break; - case MISDN_CFG_LANGUAGE: GET_CFG_STRING(LANGUAGE, language); - break; - case MISDN_CFG_MUSICCLASS: GET_CFG_STRING(MUSICCLASS, musicclass); - break; - case MISDN_CFG_CALLERID: GET_CFG_STRING(CALLERID, callerid); - break; - case MISDN_CFG_METHOD: GET_CFG_STRING(METHOD, method); - break; - case MISDN_CFG_DIALPLAN: GET_CFG_INT(DIALPLAN, dialplan); - break; - case MISDN_CFG_LOCALDIALPLAN: GET_CFG_INT(LOCALDIALPLAN, localdialplan); - break; - case MISDN_CFG_NATPREFIX: GET_CFG_STRING(NATIONALPREFIX, nationalprefix); - break; - case MISDN_CFG_INTERNATPREFIX: - GET_CFG_STRING(INTERNATIONALPREFIX, internationalprefix); - break; - case MISDN_CFG_PRES: GET_CFG_BOOL(PRESENTATION, pres, allowed, not_screened); - break; - case MISDN_CFG_ALWAYS_IMMEDIATE: - GET_CFG_BOOL(ALWAYS_IMMEDIATE, always_immediate, yes, no); - break; - case MISDN_CFG_SENDDTMF: - GET_CFG_BOOL(SENDDTMF, senddtmf, yes, no); - break; - case MISDN_CFG_IMMEDIATE: GET_CFG_BOOL(IMMEDIATE, immediate, yes, no); - break; - case MISDN_CFG_HOLD_ALLOWED: - GET_CFG_BOOL(HOLD_ALLOWED, hold_allowed, yes, no); - break; - case MISDN_CFG_EARLY_BCONNECT: - GET_CFG_BOOL(EARLY_BCONNECT, early_bconnect, yes, no); - break; - case MISDN_CFG_USE_CALLINGPRES: - GET_CFG_BOOL(USE_CALLINGPRES, use_callingpres, yes, no); - break; - case MISDN_CFG_ECHOCANCEL: GET_CFG_HYBRID(ECHOCANCEL, echocancel, yes, no); - break; - case MISDN_CFG_ECHOCANCELWHENBRIDGED: - GET_CFG_BOOL(ECHOCANCELWHENBRIDGED, echocancelwhenbridged, yes, no); - break; - case MISDN_CFG_ECHOTRAINING: - GET_CFG_HYBRID(ECHOTRAINING, echotraining, yes, no); - break; - case MISDN_CFG_CALLGROUP: GET_CFG_AST_GROUP_T(CALLINGGROUP, callgroup); - break; - case MISDN_CFG_PICKUPGROUP: GET_CFG_AST_GROUP_T(PICKUPGROUP, pickupgroup); - break; - case MISDN_CFG_MSNS: { - char tmpbuffer[BUFFERSIZE]; - tmpbuffer[0] = 0; - struct msn_list *iter; - if (port_cfg[port]->msn_list) - iter = port_cfg[port]->msn_list; - else - iter = port_cfg[0]->msn_list; - if (iter) { - for (; iter; iter = iter->next) - sprintf(tmpbuffer, "%s%s, ", tmpbuffer, iter->msn); - tmpbuffer[strlen(tmpbuffer)-2] = 0; - } - snprintf(buf, bufsize, "%s MSNs: %s", begin, *tmpbuffer ? tmpbuffer : "none"); \ - } - break; - - /* general config elements */ - - case MISDN_GEN_DEBUG: GET_GEN_INT(DEBUG_LEVEL, debug); - break; - case MISDN_GEN_TRACEFILE: GET_GEN_STRING(TRACEFILE, tracefile); - break; - case MISDN_GEN_TRACE_CALLS: GET_GEN_BOOL(TRACE_CALLS, trace_calls, true, false); - break; - case MISDN_GEN_TRACE_DIR: GET_GEN_STRING(TRACE_DIR, trace_dir); - break; - case MISDN_GEN_BRIDGING: GET_GEN_BOOL(BRIDGING, bridging, yes, no); - break; - case MISDN_GEN_STOP_TONE: GET_GEN_BOOL(STOP_TONE_AFTER_FIRST_DIGIT, stop_tone_after_first_digit, yes, no); - break; - case MISDN_GEN_APPEND_DIGITS2EXTEN: - GET_GEN_BOOL(APPEND_DIGITS2EXTEN, append_digits2exten, yes, no); - break; - case MISDN_GEN_L1_INFO_OK: GET_GEN_BOOL(L1_INFO_OK, l1_info_ok, yes, no); - break; - case MISDN_GEN_CLEAR_L3: GET_GEN_BOOL(CLEAR_L3, clear_l3, yes, no); - break; - case MISDN_GEN_DYNAMIC_CRYPT: - GET_GEN_BOOL(DYNAMIC_CRYPT,dynamic_crypt, yes, no); - break; - case MISDN_GEN_CRYPT_PREFIX: - GET_GEN_STRING(CRYPT_PREFIX, crypt_prefix); - break; - case MISDN_GEN_CRYPT_KEYS: GET_GEN_STRING(CRYPT_KEYS, crypt_keys); - break; - - default: *buf = 0; - break; + case MISDN_CTYPE_BOOL: + if (port_cfg[port][place].num) + snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[port][place].num ? "yes" : "no"); + else if (port_cfg[0][place].num) + snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, *port_cfg[0][place].num ? "yes" : "no"); + else + snprintf(buf, bufsize, " -> %s:", port_spec[place].name); + break; + case MISDN_CTYPE_ASTGROUP: + if (port_cfg[port][place].grp) + snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, + ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[port][place].grp)); + else if (port_cfg[0][place].grp) + snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, + ast_print_group(tempbuf, sizeof(tempbuf), *port_cfg[0][place].grp)); + else + snprintf(buf, bufsize, " -> %s:", port_spec[place].name); + break; + case MISDN_CTYPE_MSNLIST: + if (port_cfg[port][place].ml) + iter = port_cfg[port][place].ml; + else + iter = port_cfg[0][place].ml; + if (iter) { + for (; iter; iter = iter->next) + sprintf(tempbuf, "%s%s, ", tempbuf, iter->msn); + tempbuf[strlen(tempbuf)-2] = 0; + } + snprintf(buf, bufsize, " -> msns: %s", *tempbuf ? tempbuf : "none"); + break; + case MISDN_CTYPE_STR: + if ( port_cfg[port][place].str) { + snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[port][place].str); + } else if (port_cfg[0][place].str) { + snprintf(buf, bufsize, " -> %s: %s", port_spec[place].name, port_cfg[0][place].str); + } else { + snprintf(buf, bufsize, " -> %s:", port_spec[place].name); + } + break; + } + } else if (elem > MISDN_GEN_FIRST && elem < MISDN_GEN_LAST) { + switch (gen_spec[place].type) { + case MISDN_CTYPE_INT: + case MISDN_CTYPE_BOOLINT: + if (general_cfg[place].num) + snprintf(buf, bufsize, " -> %s: %d", gen_spec[place].name, *general_cfg[place].num); + else + snprintf(buf, bufsize, " -> %s:", gen_spec[place].name); + break; + case MISDN_CTYPE_BOOL: + if (general_cfg[place].num) + snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, *general_cfg[place].num ? "yes" : "no"); + else + snprintf(buf, bufsize, " -> %s:", gen_spec[place].name); + break; + case MISDN_CTYPE_STR: + if ( general_cfg[place].str) { + snprintf(buf, bufsize, " -> %s: %s", gen_spec[place].name, general_cfg[place].str); + } else { + snprintf(buf, bufsize, " -> %s:", gen_spec[place].name); + } + break; + default: + snprintf(buf, bufsize, " -> type of %s not handled yet", gen_spec[place].name); + break; + } + } else { + *buf = 0; + ast_log(LOG_WARNING, "Invalid call to misdn_cfg_get_config_string! Invalid config element (%d) requested.\n", elem); } - misdn_cfg_unlock(); } -int misdn_cfg_get_next_port (int port) { +int misdn_cfg_get_next_port (int port) +{ + int p = -1; + int gn = map[MISDN_CFG_GROUPNAME]; misdn_cfg_lock(); - for (port++; port <= max_ports; port++) { - if (port_cfg[port]) { - misdn_cfg_unlock(); - return port; + if (port_cfg[port][gn].str) { + p = port; + break; } } - misdn_cfg_unlock(); - - return -1; -} -int misdn_cfg_get_next_port_spin (int port) { + return p; +} - int ret = misdn_cfg_get_next_port(port); +int misdn_cfg_get_next_port_spin (int port) +{ + int p = misdn_cfg_get_next_port(port); + return (p > 0) ? p : misdn_cfg_get_next_port(0); +} - if (ret > 0) - return ret; +static int _parse (union misdn_cfg_pt *dest, char *value, enum misdn_cfg_type type, int boolint_def) +{ + int re = 0; + int len, tmp; + char *valtmp; + + switch (type) { + case MISDN_CTYPE_STR: + if ((len = strlen(value))) { + dest->str = (char *)malloc((len + 1) * sizeof(char)); + strncpy(dest->str, value, len); + dest->str[len] = 0; + } else { + dest->str = (char *)malloc( sizeof(char)); + dest->str[0] = 0; + } + break; + case MISDN_CTYPE_INT: + if (sscanf(value, "%d", &tmp)) { + dest->num = (int *)malloc(sizeof(int)); + memcpy(dest->num, &tmp, sizeof(int)); + } else + re = -1; + break; + case MISDN_CTYPE_BOOL: + dest->num = (int *)malloc(sizeof(int)); + *(dest->num) = (ast_true(value) ? 1 : 0); + break; + case MISDN_CTYPE_BOOLINT: + dest->num = (int *)malloc(sizeof(int)); + if (sscanf(value, "%d", &tmp)) { + memcpy(dest->num, &tmp, sizeof(int)); + } else { + *(dest->num) = (ast_true(value) ? boolint_def : 0); + } + break; + case MISDN_CTYPE_MSNLIST: + for (valtmp = strsep(&value, ","); valtmp; valtmp = strsep(&value, ",")) { + if ((len = strlen(valtmp))) { + struct msn_list *ml = (struct msn_list *)malloc(sizeof(struct msn_list)); + ml->msn = (char *)calloc(len+1, sizeof(char)); + strncpy(ml->msn, valtmp, len); + ml->next = dest->ml; + dest->ml = ml; + } + } + break; + case MISDN_CTYPE_ASTGROUP: + dest->grp = (ast_group_t *)malloc(sizeof(ast_group_t)); + *(dest->grp) = ast_get_group(value); + break; + } - return misdn_cfg_get_next_port(0); + return re; } -#define PARSE_GEN_INT(item) ({ \ - if (!strcasecmp(v->name, #item)) { \ - int temp; \ - if (!sscanf(v->value, "%d", &temp)) { \ - ast_log(LOG_WARNING, "Value \"%s\" for \"" #item "\" (generals section) invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", v->value); \ - } else { \ - general_cfg->item = (int *)malloc(sizeof(int)); \ - memcpy(general_cfg->item, &temp, sizeof(int)); \ - } \ - continue; \ - } \ - }) \ - -#define PARSE_GEN_BOOL(item) ({ \ - if (!strcasecmp(v->name, #item)) { \ - general_cfg->item = (int *)malloc(sizeof(int)); \ - *(general_cfg->item) = ast_true(v->value)?1:0; \ - continue; \ - } \ - }) - -#define PARSE_GEN_STR(item) ({ \ - if (!strcasecmp(v->name, #item)) { \ - int l = strlen(v->value); \ - if (l) { \ - general_cfg->item = (char *)calloc(l+1, sizeof(char)); \ - strncpy(general_cfg->item,v->value, l); \ - } \ - continue; \ - } \ - }) - -static void build_general_config(struct ast_variable *v) { - - if (!v) - return; +static void _build_general_config (struct ast_variable *v) +{ + int pos; for (; v; v = v->next) { - - PARSE_GEN_INT(debug); - PARSE_GEN_STR(tracefile); - PARSE_GEN_BOOL(trace_calls); - PARSE_GEN_STR(trace_dir); - PARSE_GEN_BOOL(bridging); - PARSE_GEN_BOOL(stop_tone_after_first_digit); - PARSE_GEN_BOOL(append_digits2exten); - PARSE_GEN_BOOL(l1_info_ok); - PARSE_GEN_BOOL(clear_l3); - PARSE_GEN_BOOL(dynamic_crypt); - PARSE_GEN_STR(crypt_prefix); - PARSE_GEN_STR(crypt_keys); - + if (((pos = get_cfg_position(v->name, GEN_CFG)) < 0) || + (_parse(&general_cfg[pos], v->value, gen_spec[pos].type, gen_spec[pos].boolint_def) < 0)) + CLI_ERROR(v->name, v->value, "general"); } } -#define PARSE_CFG_HYBRID(item, def) ({ \ - if (!strcasecmp(v->name, #item)) { \ - new->item = (int *)malloc(sizeof(int)); \ - if (!sscanf(v->value, "%d", new->item)) { \ - if (ast_true(v->value)) \ - *new->item = def; \ - else \ - *new->item = 0; \ - } \ - continue; \ - } \ - }) \ - -#define PARSE_CFG_INT(item) ({ \ - if (!strcasecmp(v->name, #item)) { \ - new->item = (int *)malloc(sizeof(int)); \ - if (!sscanf(v->value, "%d", new->item)) { \ - ast_log(LOG_WARNING, "Value \"%s\" for \"" #item "\" of group \"%s\" invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", v->value, cat); \ - free(new->item); \ - new->item = NULL; \ - } \ - continue; \ - } \ - }) \ - -#define PARSE_CFG_BOOL(item) ({ \ - if (!strcasecmp(v->name, #item)) { \ - new->item = (int *)malloc(sizeof(int)); \ - *(new->item) = ast_true(v->value)?1:0; \ - continue; \ - } \ - }) - -#define PARSE_CFG_STR(item) ({ \ - if (!strcasecmp(v->name, #item)) { \ - int l = strlen(v->value); \ - if (l) { \ - new->item = (char *)calloc(l+1, sizeof(char)); \ - strncpy(new->item,v->value,l); \ - } \ - continue; \ - } \ - }) - -static void build_port_config(struct ast_variable *v, char *cat) { +static void _build_port_config (struct ast_variable *v, char *cat) +{ + int pos, i; + union misdn_cfg_pt cfg_tmp[NUM_PORT_ELEMENTS]; + int cfg_for_ports[max_ports + 1]; + if (!v || !cat) return; - int cfg_for_ports[max_ports + 1]; - int i = 0; - for (; i < (max_ports + 1); i++) { - cfg_for_ports[i] = 0; - } - - /* we store the default config at position 0 */ + memset(cfg_tmp, 0, sizeof(cfg_tmp)); + memset(cfg_for_ports, 0, sizeof(cfg_for_ports)); + if (!strcasecmp(cat, "default")) { cfg_for_ports[0] = 1; } - struct port_config* new = (struct port_config *)calloc(1, sizeof(struct port_config)); - - { - int l = strlen(cat); - new->name = (char *)calloc(l+1, sizeof(char)); - strncpy(new->name, cat, l); + if (((pos = get_cfg_position("name", PORT_CFG)) < 0) || + (_parse(&cfg_tmp[pos], cat, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) { + CLI_ERROR(v->name, v->value, cat); + return; } - - for (; v; v=v->next) { + + for (; v; v = v->next) { if (!strcasecmp(v->name, "ports")) { - char *value; + char *token; char ptpbuf[BUFFERSIZE] = ""; int start, end; - for (value = strsep(&v->value, ","); value; value = strsep(&v->value, ","), *ptpbuf = 0) { - if (!*value) + for (token = strsep(&v->value, ","); token; token = strsep(&v->value, ","), *ptpbuf = 0) { + if (!*token) continue; - if (sscanf(value, "%d-%d%s", &start, &end, ptpbuf) >= 2) { + if (sscanf(token, "%d-%d%s", &start, &end, ptpbuf) >= 2) { for (; start <= end; start++) { if (start <= max_ports && start > 0) { cfg_for_ports[start] = 1; ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0; } else - ast_log(LOG_WARNING, "Port value '%s' of group '%s' invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat); + CLI_ERROR(v->name, v->value, cat); } } else { - if (sscanf(value, "%d%s", &start, ptpbuf)) { + if (sscanf(token, "%d%s", &start, ptpbuf)) { if (start <= max_ports && start > 0) { cfg_for_ports[start] = 1; ptp[start] = (strstr(ptpbuf, "ptp")) ? 1 : 0; } else - ast_log(LOG_WARNING, "Port value '%s' of group '%s' invalid or out of range! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat); + CLI_ERROR(v->name, v->value, cat); } else - ast_log(LOG_ERROR, "Syntax error parsing token \"msns=%s\" at group '%s'! Please edit your misdn.conf and then do a \"misdn reload\".\n", value, cat); + CLI_ERROR(v->name, v->value, cat); } } - continue; + } else { + if (((pos = get_cfg_position(v->name, PORT_CFG)) < 0) || + (_parse(&cfg_tmp[pos], v->value, port_spec[pos].type, port_spec[pos].boolint_def) < 0)) + CLI_ERROR(v->name, v->value, cat); } - PARSE_CFG_STR(context); - PARSE_CFG_INT(dialplan); - PARSE_CFG_INT(localdialplan); - PARSE_CFG_STR(nationalprefix); - PARSE_CFG_STR(internationalprefix); - PARSE_CFG_STR(language); - PARSE_CFG_STR(musicclass); - if (!strcasecmp(v->name, "presentation")) { - if (v->value && strlen(v->value)) { - new->pres = (int *)malloc(sizeof(int)); - if (!strcasecmp(v->value, "allowed")) { - *(new->pres) = 1; - } - /* TODO: i assume if it is not "allowed", it is "not_screened" */ - else { - *(new->pres) = 0; - } - } - continue; + } + + for (i = 0; i < (max_ports + 1); ++i) { + if (cfg_for_ports[i]) { + memcpy(port_cfg[i], cfg_tmp, sizeof(cfg_tmp)); } - PARSE_CFG_INT(rxgain); - PARSE_CFG_INT(txgain); - PARSE_CFG_INT(jitterbuffer); - PARSE_CFG_INT(jitterbuffer_upper_threshold); - PARSE_CFG_BOOL(te_choose_channel); - PARSE_CFG_BOOL(immediate); - PARSE_CFG_BOOL(always_immediate); - PARSE_CFG_BOOL(senddtmf); - PARSE_CFG_BOOL(hold_allowed); - PARSE_CFG_BOOL(early_bconnect); - PARSE_CFG_BOOL(use_callingpres); - PARSE_CFG_HYBRID(echocancel, DEF_ECHOCANCEL); - PARSE_CFG_BOOL(echocancelwhenbridged); - PARSE_CFG_HYBRID(echotraining, DEF_ECHOTRAINING); - PARSE_CFG_STR(callerid); - PARSE_CFG_STR(method); - if (!strcasecmp(v->name, "msns")) { - char *value; - int l; - for (value = strsep(&v->value, ","); value; value = strsep(&v->value, ",")) { - if ((l = strlen(value))) { - struct msn_list *ml = (struct msn_list *)calloc(1, sizeof(struct msn_list)); - ml->msn = (char *)calloc(l+1, sizeof(char)); - strncpy(ml->msn,value,l); - ml->next = new->msn_list; - new->msn_list = ml; + } +} + +void misdn_cfg_update_ptp (void) +{ + char misdn_init[BUFFERSIZE]; + char line[BUFFERSIZE]; + FILE *fp; + char *tok, *p, *end; + int port; + + misdn_cfg_get(0, MISDN_GEN_MISDN_INIT, &misdn_init, sizeof(misdn_init)); + + if (misdn_init) { + fp = fopen(misdn_init, "r"); + if (fp) { + while(fgets(line, sizeof(line), fp)) { + if (!strncmp(line, "nt_ptp", 6)) { + for (tok = strtok_r(line,",=", &p); + tok; + tok = strtok_r(NULL,",=", &p)) { + port = strtol(tok, &end, 10); + if (end != tok && misdn_cfg_is_port_valid(port)) { + misdn_cfg_lock(); + ptp[port] = 1; + misdn_cfg_unlock(); + } + } } } - continue; - } - if (!strcasecmp(v->name, "callgroup")) { - new->callgroup = (ast_group_t *)malloc(sizeof(ast_group_t)); - *(new->callgroup)=ast_get_group(v->value); - continue; - } - if (!strcasecmp(v->name, "pickupgroup")) { - new->pickupgroup = (ast_group_t *)malloc(sizeof(ast_group_t)); - *(new->pickupgroup)=ast_get_group(v->value); - continue; + fclose(fp); + } else { + ast_log(LOG_WARNING,"Couldn't open %s: %s\n", misdn_init, strerror(errno)); } } - /* store the new config in our array of port configs */ - for (i = 0; i < (max_ports + 1); i++) { - if (cfg_for_ports[i]) - port_cfg[i] = new; - } } +static void _fill_defaults (void) +{ + int i; -static void fill_defaults (void) { - - /* general defaults */ - if (!general_cfg->debug) - general_cfg->debug = (int*)calloc(1, sizeof(int)); - if (!general_cfg->trace_calls) - general_cfg->trace_calls = (int*)calloc(1, sizeof(int)); - if (!general_cfg->trace_dir) { - general_cfg->trace_dir = (char *)malloc(10 * sizeof(char)); - sprintf(general_cfg->trace_dir, "/var/log/"); - } - if (!general_cfg->bridging) { - general_cfg->bridging = (int*)malloc(sizeof(int)); - *general_cfg->bridging = 1; + for (i = 0; i < NUM_PORT_ELEMENTS; ++i) { + if (!port_cfg[0][i].any && strcasecmp(port_spec[i].def, NO_DEFAULT)) + _parse(&(port_cfg[0][i]), (char *)port_spec[i].def, port_spec[i].type, port_spec[i].boolint_def); } - if (!general_cfg->stop_tone_after_first_digit) { - general_cfg->stop_tone_after_first_digit = (int*)malloc(sizeof(int)); - *general_cfg->stop_tone_after_first_digit = 1; - } - if (!general_cfg->append_digits2exten) { - general_cfg->append_digits2exten = (int*)malloc(sizeof(int)); - *general_cfg->append_digits2exten = 1; - } - if (!general_cfg->l1_info_ok) { - general_cfg->l1_info_ok = (int*)malloc(sizeof(int)); - *general_cfg->l1_info_ok = 1; - } - if (!general_cfg->clear_l3) - general_cfg->clear_l3 =(int*)calloc(1, sizeof(int)); - if (!general_cfg->dynamic_crypt) - general_cfg->dynamic_crypt = (int*)calloc(1, sizeof(int)); - - /* defaults for default port config */ - if (!port_cfg[0]) - port_cfg[0] = (struct port_config*)calloc(1, sizeof(struct port_config)); - if (!port_cfg[0]->name) { - port_cfg[0]->name = (char *)malloc(8 * sizeof(char)); - sprintf(port_cfg[0]->name, "default"); - } - if (!port_cfg[0]->rxgain) - port_cfg[0]->rxgain = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->txgain) - port_cfg[0]->txgain = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->jitterbuffer) - port_cfg[0]->jitterbuffer = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->jitterbuffer_upper_threshold) - port_cfg[0]->jitterbuffer_upper_threshold = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->te_choose_channel) - port_cfg[0]->te_choose_channel = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->context) { - port_cfg[0]->context = (char *)malloc(8 * sizeof(char)); - sprintf(port_cfg[0]->context, "default"); - } - if (!port_cfg[0]->language) { - port_cfg[0]->language = (char *)malloc(3 * sizeof(char)); - sprintf(port_cfg[0]->language, "en"); - } - if (!port_cfg[0]->musicclass) { - port_cfg[0]->musicclass = (char *)malloc(3 * sizeof(char)); - sprintf(port_cfg[0]->musicclass, "default"); - } - if (!port_cfg[0]->callerid) - port_cfg[0]->callerid = (char *)calloc(1, sizeof(char)); - if (!port_cfg[0]->method) { - port_cfg[0]->method = (char *)malloc(9 * sizeof(char)); - sprintf(port_cfg[0]->method, "standard"); - } - if (!port_cfg[0]->dialplan) - port_cfg[0]->dialplan = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->localdialplan) - port_cfg[0]->localdialplan = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->nationalprefix) { - port_cfg[0]->nationalprefix = (char *)malloc(2 * sizeof(char)); - sprintf(port_cfg[0]->nationalprefix, "0"); - } - if (!port_cfg[0]->internationalprefix) { - port_cfg[0]->internationalprefix = (char *)malloc(3 * sizeof(char)); - sprintf(port_cfg[0]->internationalprefix, "00"); - } - if (!port_cfg[0]->pres) { - port_cfg[0]->pres = (int *)malloc(sizeof(int)); - *port_cfg[0]->pres = 1; - } - if (!port_cfg[0]->always_immediate) - port_cfg[0]->always_immediate = (int *)calloc(1, sizeof(int)); - - if (!port_cfg[0]->senddtmf) - port_cfg[0]->senddtmf = (int *)calloc(1, sizeof(int)); - - if (!port_cfg[0]->immediate) - port_cfg[0]->immediate = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->hold_allowed) - port_cfg[0]->hold_allowed = (int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->early_bconnect) { - port_cfg[0]->early_bconnect = (int *)malloc(sizeof(int)); - *port_cfg[0]->early_bconnect = 1; - } - if (!port_cfg[0]->echocancel) - port_cfg[0]->echocancel=(int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->echocancelwhenbridged) - port_cfg[0]->echocancelwhenbridged=(int *)calloc(1, sizeof(int)); - if (!port_cfg[0]->echotraining) { - port_cfg[0]->echotraining=(int *)malloc(sizeof(int)); - *port_cfg[0]->echotraining = 1; - } - if (!port_cfg[0]->use_callingpres) { - port_cfg[0]->use_callingpres = (int *)malloc(sizeof(int)); - *port_cfg[0]->use_callingpres = 1; - } - if (!port_cfg[0]->msn_list) { - port_cfg[0]->msn_list = (struct msn_list *)malloc(sizeof(struct msn_list)); - port_cfg[0]->msn_list->next = NULL; - port_cfg[0]->msn_list->msn = (char *)calloc(2, sizeof(char)); - *(port_cfg[0]->msn_list->msn) = '*'; + for (i = 0; i < NUM_GEN_ELEMENTS; ++i) { + if (!general_cfg[i].any && strcasecmp(gen_spec[i].def, NO_DEFAULT)) + _parse(&(general_cfg[i]), (char *)gen_spec[i].def, gen_spec[i].type, gen_spec[i].boolint_def); } } -void misdn_cfg_reload (void) { +void misdn_cfg_reload (void) +{ misdn_cfg_init (0); } -void misdn_cfg_destroy (void) { - +void misdn_cfg_destroy (void) +{ misdn_cfg_lock(); - - free_port_cfg(); - free_general_cfg(); - + + _free_port_cfg(); + _free_general_cfg(); + free(port_cfg); free(general_cfg); free(ptp); + free(map); misdn_cfg_unlock(); ast_mutex_destroy(&config_mutex); @@ -1040,48 +712,58 @@ void misdn_cfg_destroy (void) { void misdn_cfg_init (int this_max_ports) { - char config[]="misdn.conf"; - + char config[] = "misdn.conf"; + char *cat, *p; + int i; struct ast_config *cfg; - cfg = AST_LOAD_CFG(config); - if (!cfg) { + struct ast_variable *v; + + if (!(cfg = AST_LOAD_CFG(config))) { ast_log(LOG_WARNING,"no misdn.conf ?\n"); return; } misdn_cfg_lock(); - + if (this_max_ports) { /* this is the first run */ max_ports = this_max_ports; - port_cfg = (struct port_config **)calloc(max_ports + 1, sizeof(struct port_config *)); - general_cfg = (struct general_config*)calloc(1, sizeof(struct general_config)); + p = (char *)calloc(1, (max_ports + 1) * sizeof(union misdn_cfg_pt *) + + (max_ports + 1) * NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt)); + port_cfg = (union misdn_cfg_pt **)p; + p += (max_ports + 1) * sizeof(union misdn_cfg_pt *); + for (i = 0; i <= max_ports; ++i) { + port_cfg[i] = (union misdn_cfg_pt *)p; + p += NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt); + } + general_cfg = (union misdn_cfg_pt *)calloc(1, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS); ptp = (int *)calloc(max_ports + 1, sizeof(int)); + map = (int *)calloc(MISDN_GEN_LAST + 1, sizeof(int)); + _enum_array_map(); } else { - free_port_cfg(); - free_general_cfg(); - port_cfg = memset(port_cfg, 0, sizeof(struct port_config *) * (max_ports + 1)); - general_cfg = memset(general_cfg, 0, sizeof(struct general_config)); - ptp = memset(ptp, 0, sizeof(int) * (max_ports + 1)); + /* misdn reload */ + _free_port_cfg(); + _free_general_cfg(); + memset(port_cfg[0], 0, NUM_PORT_ELEMENTS * sizeof(union misdn_cfg_pt) * (max_ports + 1)); + memset(general_cfg, 0, sizeof(union misdn_cfg_pt *) * NUM_GEN_ELEMENTS); + memset(ptp, 0, sizeof(int) * (max_ports + 1)); } - - char *cat; + cat = ast_category_browse(cfg, NULL); while(cat) { - struct ast_variable *v=ast_variable_browse(cfg,cat); + v = ast_variable_browse(cfg, cat); if (!strcasecmp(cat,"general")) { - build_general_config (v); + _build_general_config(v); } else { - build_port_config (v, cat); + _build_port_config(v, cat); } - cat=ast_category_browse(cfg,cat); + cat = ast_category_browse(cfg,cat); } - fill_defaults(); - + _fill_defaults(); + misdn_cfg_unlock(); - AST_DESTROY_CFG(cfg); } |